Replace UniversalImageLoader with Picasso

This commit is contained in:
Stypox 2021-03-27 14:37:44 +01:00
parent 9c5ac069d7
commit fcef783bbb
No known key found for this signature in database
GPG key ID: 4BDF1B40A49FDD23
32 changed files with 294 additions and 528 deletions

View file

@ -18,6 +18,7 @@ import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
@ -82,9 +83,9 @@ import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoListener;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import com.squareup.picasso.Transformation;
import org.schabi.newpipe.DownloaderImpl;
import org.schabi.newpipe.MainActivity;
@ -128,11 +129,11 @@ import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper;
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.external_communication.KoreUtils;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.SerializedCache;
import org.schabi.newpipe.util.external_communication.KoreUtils;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.views.ExpandableSurfaceView;
@ -196,7 +197,6 @@ import static org.schabi.newpipe.util.Localization.containsCaseInsensitive;
public final class Player implements
EventListener,
PlaybackListener,
ImageLoadingListener,
VideoListener,
SeekBar.OnSeekBarChangeListener,
View.OnClickListener,
@ -250,6 +250,9 @@ public final class Player implements
private static final int RENDERER_UNAVAILABLE = -1;
private static final String PICASSO_PLAYER_TAG = "PICASSO_PLAYER_TAG";
private static final String PICASSO_TRANSFORMATION_KEY = "PICASSO_TRANSFORMATION_KEY";
/*//////////////////////////////////////////////////////////////////////////
// Playback
//////////////////////////////////////////////////////////////////////////*/
@ -820,7 +823,7 @@ public final class Player implements
databaseUpdateDisposable.clear();
progressUpdateDisposable.set(null);
ImageLoader.getInstance().stop();
PicassoHelper.cancelTag(PICASSO_PLAYER_TAG);
if (binding != null) {
binding.endScreen.setImageBitmap(null);
@ -1215,14 +1218,71 @@ public final class Player implements
private void initThumbnail(final String url) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - initThumbnail() called");
Log.d(TAG, "Thumbnail - initThumbnail() called with url = ["
+ (url == null ? "null" : url) + "]");
}
if (url == null || url.isEmpty()) {
return;
}
ImageLoader.getInstance().resume();
ImageLoader.getInstance()
.loadImage(url, ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, this);
// scale down the notification thumbnail for performance
PicassoHelper.loadThumbnail(url)
.tag(PICASSO_PLAYER_TAG)
.transform(new Transformation() {
@Override
public Bitmap transform(final Bitmap source) {
final float notificationThumbnailWidth = Math.min(
context.getResources()
.getDimension(R.dimen.player_notification_thumbnail_width),
source.getWidth());
return Bitmap.createScaledBitmap(
source,
(int) notificationThumbnailWidth,
(int) (source.getHeight()
/ (source.getWidth() / notificationThumbnailWidth)),
true);
}
@Override
public String key() {
return PICASSO_TRANSFORMATION_KEY;
}
})
.into(new Target() {
@Override
public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingComplete() called with: "
+ "url = [" + url + "], " + "loadedImage = [" + bitmap + " -> "
+ bitmap.getWidth() + "x" + bitmap.getHeight()
+ "], from = [" + from + "]");
}
currentThumbnail = bitmap;
NotificationUtil.getInstance()
.createNotificationIfNeededAndUpdate(Player.this, false);
// there is a new thumbnail, so changed the end screen thumbnail, too.
updateEndScreenThumbnail();
}
@Override
public void onBitmapFailed(final Exception e, final Drawable errorDrawable) {
Log.e(TAG, "Thumbnail - onBitmapFailed() called with: url = ["
+ url + "]", e);
currentThumbnail = null;
NotificationUtil.getInstance()
.createNotificationIfNeededAndUpdate(Player.this, false);
}
@Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingStarted() called with: url = ["
+ url + "]");
}
}
});
}
/**
@ -1296,61 +1356,6 @@ public final class Player implements
return Math.min(currentThumbnail.getHeight(), screenHeight);
}
}
@Override
public void onLoadingStarted(final String imageUri, final View view) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingStarted() called on: "
+ "imageUri = [" + imageUri + "], view = [" + view + "]");
}
}
@Override
public void onLoadingFailed(final String imageUri, final View view,
final FailReason failReason) {
Log.e(TAG, "Thumbnail - onLoadingFailed() called on imageUri = [" + imageUri + "]",
failReason.getCause());
currentThumbnail = null;
NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false);
}
@Override
public void onLoadingComplete(final String imageUri, final View view,
final Bitmap loadedImage) {
// scale down the notification thumbnail for performance
final float notificationThumbnailWidth = Math.min(
context.getResources().getDimension(R.dimen.player_notification_thumbnail_width),
loadedImage.getWidth());
currentThumbnail = Bitmap.createScaledBitmap(
loadedImage,
(int) notificationThumbnailWidth,
(int) (loadedImage.getHeight()
/ (loadedImage.getWidth() / notificationThumbnailWidth)),
true);
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingComplete() called with: "
+ "imageUri = [" + imageUri + "], view = [" + view + "], "
+ "loadedImage = [" + loadedImage + "], "
+ loadedImage.getWidth() + "x" + loadedImage.getHeight()
+ ", scaled notification width = " + notificationThumbnailWidth);
}
NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false);
// there is a new thumbnail, thus the end screen thumbnail needs to be changed, too.
updateEndScreenThumbnail();
}
@Override
public void onLoadingCancelled(final String imageUri, final View view) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingCancelled() called with: "
+ "imageUri = [" + imageUri + "], view = [" + view + "]");
}
currentThumbnail = null;
NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false);
}
//endregion

View file

@ -5,11 +5,9 @@ import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.PicassoHelper;
public class PlayQueueItemBuilder {
private static final String TAG = PlayQueueItemBuilder.class.toString();
@ -35,8 +33,7 @@ public class PlayQueueItemBuilder {
holder.itemDurationView.setVisibility(View.GONE);
}
ImageLoader.getInstance().displayImage(item.getThumbnailUrl(), holder.itemThumbnailView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
PicassoHelper.loadThumbnail(item.getThumbnailUrl()).into(holder.itemThumbnailView);
holder.itemRoot.setOnClickListener(view -> {
if (onItemClickListener != null) {

View file

@ -1,16 +1,18 @@
package org.schabi.newpipe.player.seekbarpreview;
import static org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper.SeekbarPreviewThumbnailType;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.common.base.Stopwatch;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.extractor.stream.Frameset;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.PicassoHelper;
import java.util.Comparator;
import java.util.HashMap;
@ -21,11 +23,8 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import static org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper.SeekbarPreviewThumbnailType;
public class SeekbarPreviewThumbnailHolder {
// This has to be <= 23 chars on devices running Android 7 or lower (API <= 25)
@ -174,6 +173,7 @@ public class SeekbarPreviewThumbnailHolder {
}
}
@Nullable
private Bitmap getBitMapFrom(final String url) {
if (url == null) {
Log.w(TAG, "url is null; This should never happen");
@ -182,24 +182,11 @@ public class SeekbarPreviewThumbnailHolder {
final Stopwatch sw = Log.isLoggable(TAG, Log.DEBUG) ? Stopwatch.createStarted() : null;
try {
final SyncImageLoadingListener syncImageLoadingListener =
new SyncImageLoadingListener();
Log.d(TAG, "Downloading bitmap for seekbarPreview from '" + url + "'");
// Ensure that everything is running
ImageLoader.getInstance().resume();
// Load the image
// Impl-Note:
// Gets the bitmap within the timeout of 15 seconds imposed by default by OkHttpClient
// Ensure that your are not running on the main-Thread this will otherwise hang
ImageLoader.getInstance().loadImage(
url,
ImageDisplayConstants.DISPLAY_SEEKBAR_PREVIEW_OPTIONS,
syncImageLoadingListener);
// Get the bitmap within the timeout
final Bitmap bitmap =
syncImageLoadingListener.waitForBitmapOrThrow(30, TimeUnit.SECONDS);
final Bitmap bitmap = PicassoHelper.loadSeekbarThumbnailPreview(url).get();
if (sw != null) {
Log.d(TAG,

View file

@ -1,87 +0,0 @@
package org.schabi.newpipe.player.seekbarpreview;
import android.graphics.Bitmap;
import android.view.View;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Listener for synchronously downloading of an image/bitmap.
*/
public class SyncImageLoadingListener extends SimpleImageLoadingListener {
private final CountDownLatch countDownLatch = new CountDownLatch(1);
private Bitmap bitmap;
private boolean cancelled = false;
private FailReason failReason = null;
@SuppressWarnings("checkstyle:HiddenField")
@Override
public void onLoadingFailed(
final String imageUri,
final View view,
final FailReason failReason) {
this.failReason = failReason;
countDownLatch.countDown();
}
@Override
public void onLoadingComplete(
final String imageUri,
final View view,
final Bitmap loadedImage) {
bitmap = loadedImage;
countDownLatch.countDown();
}
@Override
public void onLoadingCancelled(final String imageUri, final View view) {
cancelled = true;
countDownLatch.countDown();
}
public Bitmap waitForBitmapOrThrow(final long timeout, final TimeUnit timeUnit)
throws InterruptedException, TimeoutException {
// Wait for the download to finish
if (!countDownLatch.await(timeout, timeUnit)) {
throw new TimeoutException("Couldn't get the image in time");
}
if (isCancelled()) {
throw new CancellationException("Download of image was cancelled");
}
if (getFailReason() != null) {
throw new RuntimeException("Failed to download image" + getFailReason().getType(),
getFailReason().getCause());
}
if (getBitmap() == null) {
throw new NullPointerException("Bitmap is null");
}
return getBitmap();
}
public Bitmap getBitmap() {
return bitmap;
}
public boolean isCancelled() {
return cancelled;
}
public FailReason getFailReason() {
return failReason;
}
}