summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authordaniel oeh <daniel.oeh@gmail.com>2014-11-10 22:00:49 +0100
committerdaniel oeh <daniel.oeh@gmail.com>2014-11-10 22:00:49 +0100
commit99068c82ccf1ac03153e5eb6e79ff2c610caf3cf (patch)
treec067d370a9b3d11d1b69632c37300bb2a0c3d55a /core
parentad04a80ae7b2091c94b0d007c2a78d97e7af871d (diff)
downloadAntennaPod-99068c82ccf1ac03153e5eb6e79ff2c610caf3cf.zip
Updated picasso library
Use RequestHandler instead of Downloader for extracting bitmaps from media files
Diffstat (limited to 'core')
-rw-r--r--core/build.gradle2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java241
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java53
3 files changed, 175 insertions, 121 deletions
diff --git a/core/build.gradle b/core/build.gradle
index be0fb109c..6949fd4ad 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -38,7 +38,7 @@ dependencies {
compile 'com.nineoldandroids:library:2.4.0'
compile 'com.jayway.android.robotium:robotium-solo:5.2.1'
compile 'org.jsoup:jsoup:1.7.3'
- compile 'com.squareup.picasso:picasso:2.3.4'
+ compile 'com.squareup.picasso:picasso:2.4.0'
compile 'com.squareup.okhttp:okhttp:2.0.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
compile 'com.squareup.okio:okio:1.0.0'
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java
index 6ace92800..6d9353a93 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java
@@ -1,26 +1,26 @@
package de.danoeh.antennapod.core.asynctask;
+import android.content.ContentResolver;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.util.Log;
-import android.webkit.MimeTypeMap;
import com.squareup.picasso.Cache;
-import com.squareup.picasso.Downloader;
import com.squareup.picasso.LruCache;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
+import com.squareup.picasso.Request;
+import com.squareup.picasso.RequestHandler;
-import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -35,9 +35,6 @@ public class PicassoProvider {
private static ExecutorService executorService;
private static Cache memoryCache;
- private static Picasso defaultPicassoInstance;
- private static Picasso mediaMetadataPicassoInstance;
-
private static synchronized ExecutorService getExecutorService() {
if (executorService == null) {
executorService = Executors.newFixedThreadPool(3);
@@ -52,101 +49,161 @@ public class PicassoProvider {
return memoryCache;
}
- /**
- * Returns a Picasso instance that uses an OkHttpDownloader. This instance can only load images
- * from image files.
- * <p/>
- * This instance should be used as long as no images from media files are loaded.
- */
- public static synchronized Picasso getDefaultPicassoInstance(Context context) {
- Validate.notNull(context);
- if (defaultPicassoInstance == null) {
- defaultPicassoInstance = new Picasso.Builder(context)
- .indicatorsEnabled(DEBUG)
- .loggingEnabled(DEBUG)
- .downloader(new OkHttpDownloader(context))
- .executor(getExecutorService())
- .memoryCache(getMemoryCache(context))
- .listener(new Picasso.Listener() {
- @Override
- public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) {
- Log.e(TAG, "Failed to load Uri:" + uri.toString());
- e.printStackTrace();
- }
- })
- .build();
- }
- return defaultPicassoInstance;
- }
+ private static volatile boolean picassoSetup = false;
- /**
- * Returns a Picasso instance that uses a MediaMetadataRetriever if the given Uri is a media file
- * and a default OkHttpDownloader otherwise.
- */
- public static synchronized Picasso getMediaMetadataPicassoInstance(Context context) {
- Validate.notNull(context);
- if (mediaMetadataPicassoInstance == null) {
- mediaMetadataPicassoInstance = new Picasso.Builder(context)
- .indicatorsEnabled(DEBUG)
- .loggingEnabled(DEBUG)
- .downloader(new MediaMetadataDownloader(context))
- .executor(getExecutorService())
- .memoryCache(getMemoryCache(context))
- .listener(new Picasso.Listener() {
- @Override
- public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) {
- Log.e(TAG, "Failed to load Uri:" + uri.toString());
- e.printStackTrace();
- }
- })
- .build();
+ public static synchronized void setupPicassoInstance(Context appContext) {
+ if (picassoSetup) {
+ return;
}
- return mediaMetadataPicassoInstance;
+ Picasso picasso = new Picasso.Builder(appContext)
+ .indicatorsEnabled(DEBUG)
+ .loggingEnabled(DEBUG)
+ .downloader(new OkHttpDownloader(appContext))
+ .addRequestHandler(new MediaRequestHandler(appContext))
+ .executor(getExecutorService())
+ .memoryCache(getMemoryCache(appContext))
+ .listener(new Picasso.Listener() {
+ @Override
+ public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) {
+ Log.e(TAG, "Failed to load Uri:" + uri.toString());
+ e.printStackTrace();
+ }
+ })
+ .build();
+ Picasso.setSingletonInstance(picasso);
+ picassoSetup = true;
}
- private static class MediaMetadataDownloader implements Downloader {
+ private static class MediaRequestHandler extends RequestHandler {
+
+ final MediaMetadataRetriever mmr;
+ final Context context;
- private static final String TAG = "MediaMetadataDownloader";
+ public MediaRequestHandler(Context context) {
+ super();
+ this.context = context;
+ mmr = new MediaMetadataRetriever();
+ }
- private final OkHttpDownloader okHttpDownloader;
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ mmr.release();
+ }
- public MediaMetadataDownloader(Context context) {
- Validate.notNull(context);
- okHttpDownloader = new OkHttpDownloader(context);
+ @Override
+ public boolean canHandleRequest(Request data) {
+ return StringUtils.equals(data.uri.getScheme(), PicassoImageResource.SCHEME_MEDIA);
}
@Override
- public Response load(Uri uri, boolean b) throws IOException {
- if (StringUtils.equals(uri.getScheme(), PicassoImageResource.SCHEME_MEDIA)) {
- String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(FilenameUtils.getExtension(uri.getLastPathSegment()));
- if (StringUtils.startsWith(type, "image")) {
- File imageFile = new File(uri.toString());
- return new Response(new BufferedInputStream(new FileInputStream(imageFile)), true, imageFile.length());
+ public Result load(Request data) throws IOException {
+ Bitmap bitmap = null;
+ mmr.setDataSource(data.uri.getPath());
+ byte[] image = mmr.getEmbeddedPicture();
+ if (image != null) {
+ bitmap = decodeStreamFromByteArray(data, image);
+ }
+ if (bitmap == null) {
+ // check for fallback Uri
+ String fallbackParam = data.uri.getQueryParameter(PicassoImageResource.PARAM_FALLBACK);
+
+ if (fallbackParam != null) {
+ Uri fallback = Uri.parse(fallbackParam);
+ bitmap = decodeStreamFromFile(data, fallback);
+ }
+ }
+ return new Result(bitmap, Picasso.LoadedFrom.DISK);
+
+ }
+
+ /* Copied/Adapted from Picasso RequestHandler classes */
+
+ private Bitmap decodeStreamFromByteArray(Request data, byte[] bytes) throws IOException {
+
+ final BitmapFactory.Options options = createBitmapOptions(data);
+ final ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+ in.mark(0);
+ if (requiresInSampleSize(options)) {
+ try {
+ BitmapFactory.decodeStream(in, null, options);
+ } finally {
+ in.reset();
+ }
+ calculateInSampleSize(data.targetWidth, data.targetHeight, options, data);
+ }
+ try {
+ return BitmapFactory.decodeStream(in, null, options);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ private Bitmap decodeStreamFromFile(Request data, Uri uri) throws IOException {
+ ContentResolver contentResolver = context.getContentResolver();
+ final BitmapFactory.Options options = createBitmapOptions(data);
+ if (requiresInSampleSize(options)) {
+ InputStream is = null;
+ try {
+ is = contentResolver.openInputStream(uri);
+ BitmapFactory.decodeStream(is, null, options);
+ } finally {
+ IOUtils.closeQuietly(is);
+ }
+ calculateInSampleSize(data.targetWidth, data.targetHeight, options, data);
+ }
+ InputStream is = contentResolver.openInputStream(uri);
+ try {
+ return BitmapFactory.decodeStream(is, null, options);
+ } finally {
+ IOUtils.closeQuietly(is);
+ }
+ }
+
+ private BitmapFactory.Options createBitmapOptions(Request data) {
+ final boolean justBounds = data.hasSize();
+ final boolean hasConfig = data.config != null;
+ BitmapFactory.Options options = null;
+ if (justBounds || hasConfig) {
+ options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = justBounds;
+ if (hasConfig) {
+ options.inPreferredConfig = data.config;
+ }
+ }
+ return options;
+ }
+
+ private static boolean requiresInSampleSize(BitmapFactory.Options options) {
+ return options != null && options.inJustDecodeBounds;
+ }
+
+ private static void calculateInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options,
+ Request request) {
+ calculateInSampleSize(reqWidth, reqHeight, options.outWidth, options.outHeight, options,
+ request);
+ }
+
+ private static void calculateInSampleSize(int reqWidth, int reqHeight, int width, int height,
+ BitmapFactory.Options options, Request request) {
+ int sampleSize = 1;
+ if (height > reqHeight || width > reqWidth) {
+ final int heightRatio;
+ final int widthRatio;
+ if (reqHeight == 0) {
+ sampleSize = (int) Math.floor((float) width / (float) reqWidth);
+ } else if (reqWidth == 0) {
+ sampleSize = (int) Math.floor((float) height / (float) reqHeight);
} else {
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- mmr.setDataSource(uri.getPath());
- byte[] data = mmr.getEmbeddedPicture();
- mmr.release();
-
- if (data != null) {
- return new Response(new ByteArrayInputStream(data), true, data.length);
- } else {
-
- // check for fallback Uri
- String fallbackParam = uri.getQueryParameter(PicassoImageResource.PARAM_FALLBACK);
-
- if (fallbackParam != null) {
- String fallback = Uri.decode(Uri.parse(fallbackParam).getPath());
- if (fallback != null) {
- File imageFile = new File(fallback);
- return new Response(new BufferedInputStream(new FileInputStream(imageFile)), true, imageFile.length());
- }
- }
- return null;
- }
+ heightRatio = (int) Math.floor((float) height / (float) reqHeight);
+ widthRatio = (int) Math.floor((float) width / (float) reqWidth);
+ sampleSize = request.centerInside
+ ? Math.max(heightRatio, widthRatio)
+ : Math.min(heightRatio, widthRatio);
}
}
- return okHttpDownloader.load(uri, b);
+ options.inSampleSize = sampleSize;
+ options.inJustDecodeBounds = false;
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index 1261c21fe..a5560e3fb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -29,6 +29,8 @@ import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.widget.Toast;
+import com.squareup.picasso.Picasso;
+
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
@@ -37,7 +39,6 @@ import java.util.List;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.asynctask.PicassoProvider;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
@@ -291,10 +292,9 @@ public class PlaybackService extends Service {
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
if (status == PlayerStatus.PLAYING) {
if (UserPreferences.isPersistNotify()) {
- mediaPlayer.pause(false, true);
- }
- else {
- mediaPlayer.pause(true, true);
+ mediaPlayer.pause(false, true);
+ } else {
+ mediaPlayer.pause(true, true);
}
} else if (status == PlayerStatus.PAUSED || status == PlayerStatus.PREPARED) {
mediaPlayer.resume();
@@ -315,12 +315,11 @@ public class PlaybackService extends Service {
break;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
if (status == PlayerStatus.PLAYING) {
- if (UserPreferences.isPersistNotify()) {
- mediaPlayer.pause(false, true);
- }
- else {
- mediaPlayer.pause(true, true);
- }
+ if (UserPreferences.isPersistNotify()) {
+ mediaPlayer.pause(false, true);
+ } else {
+ mediaPlayer.pause(true, true);
+ }
}
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
@@ -332,11 +331,11 @@ public class PlaybackService extends Service {
mediaPlayer.seekDelta(-UserPreferences.getSeekDeltaMs());
break;
case KeyEvent.KEYCODE_MEDIA_STOP:
- if (status == PlayerStatus.PLAYING) {
- mediaPlayer.pause(true, true);
- }
- stopForeground(true); // gets rid of persistent notification
- break;
+ if (status == PlayerStatus.PLAYING) {
+ mediaPlayer.pause(true, true);
+ }
+ stopForeground(true); // gets rid of persistent notification
+ break;
default:
if (info.playable != null && info.playerStatus == PlayerStatus.PLAYING) { // only notify the user about an unknown key event if it is actually doing something
String message = String.format(getResources().getString(R.string.unknown_media_key), keycode);
@@ -411,11 +410,10 @@ public class PlaybackService extends Service {
saveCurrentPosition(false, 0);
taskManager.cancelWidgetUpdater();
if (UserPreferences.isPersistNotify() && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- // do not remove notification on pause based on user pref and whether android version supports expanded notifications
- }
- else {
- // remove notifcation on pause
- stopForeground(true);
+ // do not remove notification on pause based on user pref and whether android version supports expanded notifications
+ } else {
+ // remove notifcation on pause
+ stopForeground(true);
}
break;
@@ -709,7 +707,7 @@ public class PlaybackService extends Service {
try {
int iconSize = getResources().getDimensionPixelSize(
android.R.dimen.notification_large_icon_width);
- icon = PicassoProvider.getMediaMetadataPicassoInstance(PlaybackService.this)
+ icon = Picasso.with(PlaybackService.this)
.load(info.playable.getImageUri())
.resize(iconSize, iconSize)
.get();
@@ -1005,12 +1003,11 @@ public class PlaybackService extends Service {
*/
private void pauseIfPauseOnDisconnect() {
if (UserPreferences.isPauseOnHeadsetDisconnect()) {
- if (UserPreferences.isPersistNotify()) {
- mediaPlayer.pause(false, true);
- }
- else {
- mediaPlayer.pause(true, true);
- }
+ if (UserPreferences.isPersistNotify()) {
+ mediaPlayer.pause(false, true);
+ } else {
+ mediaPlayer.pause(true, true);
+ }
}
}