summaryrefslogtreecommitdiff
path: root/src/de
diff options
context:
space:
mode:
Diffstat (limited to 'src/de')
-rw-r--r--src/de/danoeh/antennapod/PodcastApp.java8
-rw-r--r--src/de/danoeh/antennapod/activity/AudioplayerActivity.java13
-rw-r--r--src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java38
-rw-r--r--src/de/danoeh/antennapod/activity/FeedInfoActivity.java7
-rw-r--r--src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java17
-rw-r--r--src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java527
-rw-r--r--src/de/danoeh/antennapod/adapter/NavListAdapter.java11
-rw-r--r--src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java21
-rw-r--r--src/de/danoeh/antennapod/adapter/QueueListAdapter.java15
-rw-r--r--src/de/danoeh/antennapod/adapter/SearchlistAdapter.java123
-rw-r--r--src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java15
-rw-r--r--src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java115
-rw-r--r--src/de/danoeh/antennapod/asynctask/CachedBitmap.java27
-rw-r--r--src/de/danoeh/antennapod/asynctask/ImageDiskCache.java397
-rw-r--r--src/de/danoeh/antennapod/asynctask/ImageLoader.java246
-rw-r--r--src/de/danoeh/antennapod/asynctask/PicassoImageResource.java25
-rw-r--r--src/de/danoeh/antennapod/asynctask/PicassoProvider.java137
-rw-r--r--src/de/danoeh/antennapod/feed/Feed.java14
-rw-r--r--src/de/danoeh/antennapod/feed/FeedImage.java42
-rw-r--r--src/de/danoeh/antennapod/feed/FeedItem.java57
-rw-r--r--src/de/danoeh/antennapod/feed/FeedMedia.java64
-rw-r--r--src/de/danoeh/antennapod/fragment/CoverFragment.java146
-rw-r--r--src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java408
-rw-r--r--src/de/danoeh/antennapod/fragment/ItemlistFragment.java11
-rw-r--r--src/de/danoeh/antennapod/service/playback/PlaybackService.java41
-rw-r--r--src/de/danoeh/antennapod/util/BitmapDecoder.java50
-rw-r--r--src/de/danoeh/antennapod/util/playback/ExternalMedia.java28
-rw-r--r--src/de/danoeh/antennapod/util/playback/Playable.java79
28 files changed, 968 insertions, 1714 deletions
diff --git a/src/de/danoeh/antennapod/PodcastApp.java b/src/de/danoeh/antennapod/PodcastApp.java
index 4c4766327..74628f3d6 100644
--- a/src/de/danoeh/antennapod/PodcastApp.java
+++ b/src/de/danoeh/antennapod/PodcastApp.java
@@ -3,7 +3,6 @@ package de.danoeh.antennapod;
import android.app.Application;
import android.content.res.Configuration;
import android.util.Log;
-import de.danoeh.antennapod.asynctask.ImageLoader;
import de.danoeh.antennapod.feed.EventDistributor;
import de.danoeh.antennapod.preferences.PlaybackPreferences;
import de.danoeh.antennapod.preferences.UserPreferences;
@@ -36,13 +35,6 @@ public class PodcastApp extends Application {
SPAUtil.sendSPAppsQueryFeedsIntent(this);
}
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- Log.w(TAG, "Received onLowOnMemory warning. Cleaning image cache...");
- ImageLoader.getInstance().wipeImageCache();
- }
-
public static float getLogicalDensity() {
return LOGICAL_DENSITY;
}
diff --git a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
index 6373ff240..50f5d8f2e 100644
--- a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -31,7 +31,7 @@ import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.ChapterListAdapter;
import de.danoeh.antennapod.adapter.NavListAdapter;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
import de.danoeh.antennapod.feed.Chapter;
import de.danoeh.antennapod.feed.EventDistributor;
@@ -381,8 +381,9 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
@Override
public void run() {
- ImageLoader.getInstance().loadThumbnailBitmap(media,
- butNavLeft);
+ PicassoProvider.getMediaMetadataPicassoInstance(AudioplayerActivity.this)
+ .load(media.getImageUri())
+ .into(butNavLeft);
}
});
butNavLeft.setContentDescription(getString(buttonTexts[2]));
@@ -396,9 +397,11 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
@Override
public void run() {
- ImageLoader.getInstance().loadThumbnailBitmap(media,
- butNavLeft);
+ PicassoProvider.getMediaMetadataPicassoInstance(AudioplayerActivity.this)
+ .load(media.getImageUri())
+ .into(butNavLeft);
}
+
});
butNavLeft.setContentDescription(getString(buttonTexts[2]));
diff --git a/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java b/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java
index e89f8d05c..86b278bf0 100644
--- a/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java
+++ b/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java
@@ -9,11 +9,28 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
-import android.widget.*;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.examples.HtmlToPlainText;
+import org.jsoup.nodes.Document;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.FeedItemlistDescriptionAdapter;
-import de.danoeh.antennapod.asynctask.ImageDiskCache;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.feed.EventDistributor;
import de.danoeh.antennapod.feed.Feed;
@@ -21,15 +38,6 @@ import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.storage.DBReader;
import de.danoeh.antennapod.storage.DownloadRequestException;
import de.danoeh.antennapod.storage.DownloadRequester;
-import org.apache.commons.lang3.StringUtils;
-import org.jsoup.Jsoup;
-import org.jsoup.examples.HtmlToPlainText;
-import org.jsoup.nodes.Document;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
/**
* Default implementation of OnlineFeedViewActivity. Shows the downloaded feed's items with their descriptions,
@@ -115,9 +123,13 @@ public class DefaultOnlineFeedViewActivity extends OnlineFeedViewActivity {
subscribeButton = (Button) header.findViewById(R.id.butSubscribe);
if (feed.getImage() != null) {
- ImageDiskCache.getDefaultInstance().loadThumbnailBitmap(feed.getImage().getDownload_url(), cover, (int) getResources().getDimension(
- R.dimen.thumbnail_length));
+ int imageSize = (int) getResources().getDimension(R.dimen.thumbnail_length);
+ PicassoProvider.getDefaultPicassoInstance(this)
+ .load(feed.getImage().getDownload_url())
+ .resize(imageSize, imageSize)
+ .into(cover);
}
+
title.setText(feed.getTitle());
author.setText(feed.getAuthor());
description.setText(feed.getDescription());
diff --git a/src/de/danoeh/antennapod/activity/FeedInfoActivity.java b/src/de/danoeh/antennapod/activity/FeedInfoActivity.java
index 7f60d0b10..b46bc7546 100644
--- a/src/de/danoeh/antennapod/activity/FeedInfoActivity.java
+++ b/src/de/danoeh/antennapod/activity/FeedInfoActivity.java
@@ -12,7 +12,7 @@ import android.view.MenuItem;
import android.widget.*;
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.feed.Feed;
import de.danoeh.antennapod.feed.FeedPreferences;
@@ -78,8 +78,9 @@ public class FeedInfoActivity extends ActionBarActivity {
@Override
public void run() {
- ImageLoader.getInstance().loadThumbnailBitmap(
- feed.getImage(), imgvCover);
+ PicassoProvider.getDefaultPicassoInstance(FeedInfoActivity.this)
+ .load(feed.getImageUri())
+ .into(imgvCover);
}
});
diff --git a/src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
index 33b11774f..641a1368d 100644
--- a/src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
@@ -9,8 +9,9 @@ import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
+
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.util.Converter;
@@ -22,10 +23,13 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
private final Context context;
private final ItemAccess itemAccess;
+ private final int imageSize;
+
public DownloadedEpisodesListAdapter(Context context, ItemAccess itemAccess) {
super();
this.context = context;
this.itemAccess = itemAccess;
+ this.imageSize = (int) context.getResources().getDimension(R.dimen.thumbnail_length_downloaded_item);
}
@Override
@@ -83,12 +87,11 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
holder.butSecondary.setOnClickListener(secondaryActionListener);
- ImageLoader.getInstance().loadThumbnailBitmap(
- item,
- holder.imageView,
- (int) convertView.getResources().getDimension(
- R.dimen.thumbnail_length)
- );
+ PicassoProvider.getMediaMetadataPicassoInstance(context)
+ .load(item.getImageUri())
+ .resize(imageSize, imageSize)
+ .into(holder.imageView);
+
return convertView;
}
diff --git a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
index 5e857c131..56c3e1ca6 100644
--- a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
@@ -6,9 +6,14 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.*;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.storage.DownloadRequester;
@@ -19,276 +24,282 @@ import de.danoeh.antennapod.util.Converter;
* structure of this list is: [header] [queueItems] [header] [unreadItems].
*/
public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
- private static final String TAG = "ExternalEpisodesListAdapter";
+ private static final String TAG = "ExternalEpisodesListAdapter";
- public static final int GROUP_POS_QUEUE = 0;
- public static final int GROUP_POS_UNREAD = 1;
+ public static final int GROUP_POS_QUEUE = 0;
+ public static final int GROUP_POS_UNREAD = 1;
- private Context context;
+ private Context context;
private ItemAccess itemAccess;
- private ActionButtonCallback feedItemActionCallback;
- private OnGroupActionClicked groupActionCallback;
+ private ActionButtonCallback feedItemActionCallback;
+ private OnGroupActionClicked groupActionCallback;
+
+ private final int imageSize;
- public ExternalEpisodesListAdapter(Context context,
- ActionButtonCallback callback,
- OnGroupActionClicked groupActionCallback,
- ItemAccess itemAccess) {
- super();
- this.context = context;
+ public ExternalEpisodesListAdapter(Context context,
+ ActionButtonCallback callback,
+ OnGroupActionClicked groupActionCallback,
+ ItemAccess itemAccess) {
+ super();
+ this.context = context;
this.itemAccess = itemAccess;
- this.feedItemActionCallback = callback;
- this.groupActionCallback = groupActionCallback;
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- @Override
- public FeedItem getChild(int groupPosition, int childPosition) {
- if (groupPosition == GROUP_POS_QUEUE) {
- return itemAccess.getQueueItemAt(childPosition);
- } else if (groupPosition == GROUP_POS_UNREAD) {
+ this.feedItemActionCallback = callback;
+ this.groupActionCallback = groupActionCallback;
+ this.imageSize = (int) context.getResources().getDimension(R.dimen.thumbnail_length);
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return true;
+ }
+
+ @Override
+ public FeedItem getChild(int groupPosition, int childPosition) {
+ if (groupPosition == GROUP_POS_QUEUE) {
+ return itemAccess.getQueueItemAt(childPosition);
+ } else if (groupPosition == GROUP_POS_UNREAD) {
return itemAccess.getUnreadItemAt(childPosition);
- }
- return null;
- }
-
- @Override
- public long getChildId(int groupPosition, int childPosition) {
- return childPosition;
- }
-
- @Override
- public View getChildView(int groupPosition, final int childPosition,
- boolean isLastChild, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = getChild(groupPosition, childPosition);
-
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.external_itemlist_item,
- parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.feedTitle = (TextView) convertView
- .findViewById(R.id.txtvFeedname);
- holder.lenSize = (TextView) convertView
- .findViewById(R.id.txtvLenSize);
- holder.downloadStatus = (ImageView) convertView
- .findViewById(R.id.imgvDownloadStatus);
- holder.feedImage = (ImageView) convertView
- .findViewById(R.id.imgvFeedimage);
- holder.butAction = (ImageButton) convertView
- .findViewById(R.id.butAction);
- holder.statusPlaying = (View) convertView
- .findViewById(R.id.statusPlaying);
- holder.episodeProgress = (ProgressBar) convertView
- .findViewById(R.id.pbar_episode_progress);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- holder.title.setText(item.getTitle());
- holder.feedTitle.setText(item.getFeed().getTitle());
- FeedItem.State state = item.getState();
-
- if (groupPosition == GROUP_POS_QUEUE) {
- switch (state) {
- case PLAYING:
- holder.statusPlaying.setVisibility(View.VISIBLE);
- holder.episodeProgress.setVisibility(View.VISIBLE);
- break;
- case IN_PROGRESS:
- holder.statusPlaying.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.VISIBLE);
- break;
- case NEW:
- holder.statusPlaying.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.GONE);
- break;
- default:
- holder.statusPlaying.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.GONE);
- break;
- }
- } else {
- holder.statusPlaying.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.GONE);
- }
-
- FeedMedia media = item.getMedia();
- if (media != null) {
-
- if (state == FeedItem.State.PLAYING
- || state == FeedItem.State.IN_PROGRESS) {
- if (media.getDuration() > 0) {
- holder.episodeProgress.setProgress((int) (((double) media
- .getPosition()) / media.getDuration() * 100));
- holder.lenSize.setText(Converter
- .getDurationStringLong(media.getDuration()
- - media.getPosition()));
- }
- } else if (!media.isDownloaded()) {
- holder.lenSize.setText(context.getString(R.string.size_prefix)
- + Converter.byteToString(media.getSize()));
- } else {
- holder.lenSize.setText(context
- .getString(R.string.length_prefix)
- + Converter.getDurationStringLong(media.getDuration()));
- }
-
- TypedArray drawables = context.obtainStyledAttributes(new int[] {
- R.attr.av_download, R.attr.navigation_refresh });
- final int[] labels = new int[] {R.string.status_downloaded_label, R.string.downloading_label};
- holder.lenSize.setVisibility(View.VISIBLE);
- if (!media.isDownloaded()) {
- if (DownloadRequester.getInstance().isDownloadingFile(media)) {
- holder.downloadStatus.setVisibility(View.VISIBLE);
- holder.downloadStatus.setImageDrawable(drawables
- .getDrawable(1));
+ }
+ return null;
+ }
+
+ @Override
+ public long getChildId(int groupPosition, int childPosition) {
+ return childPosition;
+ }
+
+ @Override
+ public View getChildView(int groupPosition, final int childPosition,
+ boolean isLastChild, View convertView, ViewGroup parent) {
+ Holder holder;
+ final FeedItem item = getChild(groupPosition, childPosition);
+
+ if (convertView == null) {
+ holder = new Holder();
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ convertView = inflater.inflate(R.layout.external_itemlist_item,
+ parent, false);
+ holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ holder.feedTitle = (TextView) convertView
+ .findViewById(R.id.txtvFeedname);
+ holder.lenSize = (TextView) convertView
+ .findViewById(R.id.txtvLenSize);
+ holder.downloadStatus = (ImageView) convertView
+ .findViewById(R.id.imgvDownloadStatus);
+ holder.feedImage = (ImageView) convertView
+ .findViewById(R.id.imgvFeedimage);
+ holder.butAction = (ImageButton) convertView
+ .findViewById(R.id.butAction);
+ holder.statusPlaying = (View) convertView
+ .findViewById(R.id.statusPlaying);
+ holder.episodeProgress = (ProgressBar) convertView
+ .findViewById(R.id.pbar_episode_progress);
+ convertView.setTag(holder);
+ } else {
+ holder = (Holder) convertView.getTag();
+ }
+
+ holder.title.setText(item.getTitle());
+ holder.feedTitle.setText(item.getFeed().getTitle());
+ FeedItem.State state = item.getState();
+
+ if (groupPosition == GROUP_POS_QUEUE) {
+ switch (state) {
+ case PLAYING:
+ holder.statusPlaying.setVisibility(View.VISIBLE);
+ holder.episodeProgress.setVisibility(View.VISIBLE);
+ break;
+ case IN_PROGRESS:
+ holder.statusPlaying.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.VISIBLE);
+ break;
+ case NEW:
+ holder.statusPlaying.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.GONE);
+ break;
+ default:
+ holder.statusPlaying.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.GONE);
+ break;
+ }
+ } else {
+ holder.statusPlaying.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.GONE);
+ }
+
+ FeedMedia media = item.getMedia();
+ if (media != null) {
+
+ if (state == FeedItem.State.PLAYING
+ || state == FeedItem.State.IN_PROGRESS) {
+ if (media.getDuration() > 0) {
+ holder.episodeProgress.setProgress((int) (((double) media
+ .getPosition()) / media.getDuration() * 100));
+ holder.lenSize.setText(Converter
+ .getDurationStringLong(media.getDuration()
+ - media.getPosition()));
+ }
+ } else if (!media.isDownloaded()) {
+ holder.lenSize.setText(context.getString(R.string.size_prefix)
+ + Converter.byteToString(media.getSize()));
+ } else {
+ holder.lenSize.setText(context
+ .getString(R.string.length_prefix)
+ + Converter.getDurationStringLong(media.getDuration()));
+ }
+
+ TypedArray drawables = context.obtainStyledAttributes(new int[]{
+ R.attr.av_download, R.attr.navigation_refresh});
+ final int[] labels = new int[]{R.string.status_downloaded_label, R.string.downloading_label};
+ holder.lenSize.setVisibility(View.VISIBLE);
+ if (!media.isDownloaded()) {
+ if (DownloadRequester.getInstance().isDownloadingFile(media)) {
+ holder.downloadStatus.setVisibility(View.VISIBLE);
+ holder.downloadStatus.setImageDrawable(drawables
+ .getDrawable(1));
holder.downloadStatus.setContentDescription(context.getString(labels[1]));
- } else {
- holder.downloadStatus.setVisibility(View.INVISIBLE);
- }
- } else {
- holder.downloadStatus.setVisibility(View.VISIBLE);
- holder.downloadStatus
- .setImageDrawable(drawables.getDrawable(0));
+ } else {
+ holder.downloadStatus.setVisibility(View.INVISIBLE);
+ }
+ } else {
+ holder.downloadStatus.setVisibility(View.VISIBLE);
+ holder.downloadStatus
+ .setImageDrawable(drawables.getDrawable(0));
holder.downloadStatus.setContentDescription(context.getString(labels[0]));
- }
- } else {
- holder.downloadStatus.setVisibility(View.INVISIBLE);
- holder.lenSize.setVisibility(View.INVISIBLE);
- }
-
- ImageLoader.getInstance().loadThumbnailBitmap(
- item,
- holder.feedImage,
- (int) convertView.getResources().getDimension(
- R.dimen.thumbnail_length));
- holder.butAction.setFocusable(false);
- holder.butAction.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- feedItemActionCallback.onActionButtonPressed(item);
- }
- });
-
- return convertView;
-
- }
-
- static class Holder {
- TextView title;
- TextView feedTitle;
- TextView lenSize;
- ImageView downloadStatus;
- ImageView feedImage;
- ImageButton butAction;
- View statusPlaying;
- ProgressBar episodeProgress;
- }
-
- @Override
- public int getChildrenCount(int groupPosition) {
- if (groupPosition == GROUP_POS_QUEUE) {
- return itemAccess.getQueueSize();
- } else if (groupPosition == GROUP_POS_UNREAD) {
- return itemAccess.getUnreadItemsSize();
- }
- return 0;
- }
-
- @Override
- public int getGroupCount() {
- // Hide 'unread items' group if empty
- if (itemAccess.getUnreadItemsSize() > 0) {
- return 2;
- } else {
- return 1;
- }
- }
-
- @Override
- public long getGroupId(int groupPosition) {
- return groupPosition;
- }
-
- @Override
- public View getGroupView(final int groupPosition, boolean isExpanded,
- View convertView, ViewGroup parent) {
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.feeditemlist_header, parent, false);
- TextView headerTitle = (TextView) convertView
- .findViewById(0);
- ImageButton actionButton = (ImageButton) convertView
- .findViewById(R.id.butAction);
- TextView numItems = (TextView) convertView.findViewById(0);
-
- String headerString = null;
- int childrenCount = 0;
-
- if (groupPosition == 0) {
- headerString = context.getString(R.string.queue_label);
- childrenCount = getChildrenCount(GROUP_POS_QUEUE);
- } else {
- headerString = context.getString(R.string.waiting_list_label);
- childrenCount = getChildrenCount(GROUP_POS_UNREAD);
- }
- headerTitle.setText(headerString);
- if (childrenCount <= 0) {
- numItems.setVisibility(View.INVISIBLE);
- } else {
- numItems.setVisibility(View.VISIBLE);
- numItems.setText(Integer.toString(childrenCount));
- }
- actionButton.setFocusable(false);
- actionButton.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- groupActionCallback.onClick(getGroupId(groupPosition));
- }
- });
- return convertView;
- }
-
- @Override
- public boolean isEmpty() {
- return itemAccess.getUnreadItemsSize() == 0
- && itemAccess.getQueueSize() == 0;
- }
-
- @Override
- public Object getGroup(int groupPosition) {
- return null;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return true;
- }
-
- public interface OnGroupActionClicked {
- public void onClick(long groupId);
- }
+ }
+ } else {
+ holder.downloadStatus.setVisibility(View.INVISIBLE);
+ holder.lenSize.setVisibility(View.INVISIBLE);
+ }
+
+ PicassoProvider.getMediaMetadataPicassoInstance(context)
+ .load(item.getImageUri())
+ .resize(imageSize, imageSize)
+ .into(holder.feedImage);
+
+ holder.butAction.setFocusable(false);
+ holder.butAction.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ feedItemActionCallback.onActionButtonPressed(item);
+ }
+ });
+
+ return convertView;
+
+ }
+
+ static class Holder {
+ TextView title;
+ TextView feedTitle;
+ TextView lenSize;
+ ImageView downloadStatus;
+ ImageView feedImage;
+ ImageButton butAction;
+ View statusPlaying;
+ ProgressBar episodeProgress;
+ }
+
+ @Override
+ public int getChildrenCount(int groupPosition) {
+ if (groupPosition == GROUP_POS_QUEUE) {
+ return itemAccess.getQueueSize();
+ } else if (groupPosition == GROUP_POS_UNREAD) {
+ return itemAccess.getUnreadItemsSize();
+ }
+ return 0;
+ }
+
+ @Override
+ public int getGroupCount() {
+ // Hide 'unread items' group if empty
+ if (itemAccess.getUnreadItemsSize() > 0) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+
+ @Override
+ public long getGroupId(int groupPosition) {
+ return groupPosition;
+ }
+
+ @Override
+ public View getGroupView(final int groupPosition, boolean isExpanded,
+ View convertView, ViewGroup parent) {
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ convertView = inflater.inflate(R.layout.feeditemlist_header, parent, false);
+ TextView headerTitle = (TextView) convertView
+ .findViewById(0);
+ ImageButton actionButton = (ImageButton) convertView
+ .findViewById(R.id.butAction);
+ TextView numItems = (TextView) convertView.findViewById(0);
+
+ String headerString = null;
+ int childrenCount = 0;
+
+ if (groupPosition == 0) {
+ headerString = context.getString(R.string.queue_label);
+ childrenCount = getChildrenCount(GROUP_POS_QUEUE);
+ } else {
+ headerString = context.getString(R.string.waiting_list_label);
+ childrenCount = getChildrenCount(GROUP_POS_UNREAD);
+ }
+ headerTitle.setText(headerString);
+ if (childrenCount <= 0) {
+ numItems.setVisibility(View.INVISIBLE);
+ } else {
+ numItems.setVisibility(View.VISIBLE);
+ numItems.setText(Integer.toString(childrenCount));
+ }
+ actionButton.setFocusable(false);
+ actionButton.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ groupActionCallback.onClick(getGroupId(groupPosition));
+ }
+ });
+ return convertView;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return itemAccess.getUnreadItemsSize() == 0
+ && itemAccess.getQueueSize() == 0;
+ }
+
+ @Override
+ public Object getGroup(int groupPosition) {
+ return null;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return true;
+ }
+
+ public interface OnGroupActionClicked {
+ public void onClick(long groupId);
+ }
public static interface ItemAccess {
public int getQueueSize();
+
public int getUnreadItemsSize();
+
public FeedItem getQueueItemAt(int position);
+
public FeedItem getUnreadItemAt(int position);
}
diff --git a/src/de/danoeh/antennapod/adapter/NavListAdapter.java b/src/de/danoeh/antennapod/adapter/NavListAdapter.java
index 9676372fb..ed85c8836 100644
--- a/src/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/NavListAdapter.java
@@ -11,7 +11,7 @@ import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.feed.Feed;
/**
@@ -32,6 +32,8 @@ public class NavListAdapter extends BaseAdapter {
private ItemAccess itemAccess;
private Context context;
+ private final int imageSize;
+
public NavListAdapter(ItemAccess itemAccess, Context context) {
this.itemAccess = itemAccess;
this.context = context;
@@ -41,6 +43,7 @@ public class NavListAdapter extends BaseAdapter {
drawables = new Drawable[]{ta.getDrawable(0), ta.getDrawable(1), ta.getDrawable(2),
ta.getDrawable(3), ta.getDrawable(4)};
ta.recycle();
+ this.imageSize = (int) context.getResources().getDimension(R.dimen.thumbnail_length_navlist);
}
@Override
@@ -189,7 +192,11 @@ public class NavListAdapter extends BaseAdapter {
}
holder.title.setText(feed.getTitle());
- ImageLoader.getInstance().loadThumbnailBitmap(feed.getImage(), holder.image, (int) context.getResources().getDimension(R.dimen.thumbnail_length_navlist));
+
+ PicassoProvider.getDefaultPicassoInstance(context)
+ .load(feed.getImageUri())
+ .resize(imageSize, imageSize)
+ .into(holder.image);
return convertView;
}
diff --git a/src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java
index 07fd3e6b1..4370de14d 100644
--- a/src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java
@@ -5,9 +5,14 @@ import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.*;
+import android.widget.BaseAdapter;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.storage.DownloadRequester;
@@ -22,6 +27,7 @@ public class NewEpisodesListAdapter extends BaseAdapter {
private final ItemAccess itemAccess;
private final ActionButtonCallback actionButtonCallback;
private final ActionButtonUtils actionButtonUtils;
+ private final int imageSize;
public NewEpisodesListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback) {
super();
@@ -29,6 +35,7 @@ public class NewEpisodesListAdapter extends BaseAdapter {
this.itemAccess = itemAccess;
this.actionButtonUtils = new ActionButtonUtils(context);
this.actionButtonCallback = actionButtonCallback;
+ this.imageSize = (int) context.getResources().getDimension(R.dimen.thumbnail_length_itemlist);
}
@Override
@@ -124,13 +131,11 @@ public class NewEpisodesListAdapter extends BaseAdapter {
holder.butSecondary.setTag(item);
holder.butSecondary.setOnClickListener(secondaryActionListener);
+ PicassoProvider.getMediaMetadataPicassoInstance(context)
+ .load(item.getImageUri())
+ .resize(imageSize, imageSize)
+ .into(holder.imageView);
- ImageLoader.getInstance().loadThumbnailBitmap(
- item,
- holder.imageView,
- (int) convertView.getResources().getDimension(
- R.dimen.thumbnail_length)
- );
return convertView;
}
diff --git a/src/de/danoeh/antennapod/adapter/QueueListAdapter.java b/src/de/danoeh/antennapod/adapter/QueueListAdapter.java
index f671ba5c6..c670089b9 100644
--- a/src/de/danoeh/antennapod/adapter/QueueListAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/QueueListAdapter.java
@@ -6,7 +6,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.storage.DownloadRequester;
@@ -22,12 +22,15 @@ public class QueueListAdapter extends BaseAdapter {
private final ActionButtonCallback actionButtonCallback;
private final ActionButtonUtils actionButtonUtils;
+ private final int imageSize;
+
public QueueListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback) {
super();
this.context = context;
this.itemAccess = itemAccess;
this.actionButtonUtils = new ActionButtonUtils(context);
this.actionButtonCallback = actionButtonCallback;
+ this.imageSize = (int) context.getResources().getDimension(R.dimen.thumbnail_length_queue_item);
}
@@ -92,13 +95,11 @@ public class QueueListAdapter extends BaseAdapter {
holder.butSecondary.setTag(item);
holder.butSecondary.setOnClickListener(secondaryActionListener);
+ PicassoProvider.getMediaMetadataPicassoInstance(context)
+ .load(item.getImageUri())
+ .resize(imageSize, imageSize)
+ .into(holder.imageView);
- ImageLoader.getInstance().loadThumbnailBitmap(
- item,
- holder.imageView,
- (int) convertView.getResources().getDimension(
- R.dimen.thumbnail_length)
- );
return convertView;
}
diff --git a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java
index ecfbb4660..6b1fefaad 100644
--- a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java
@@ -4,28 +4,31 @@ import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
+
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.feed.Feed;
import de.danoeh.antennapod.feed.FeedComponent;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.SearchResult;
-import java.util.List;
-
-/** List adapter for search activity. */
+/**
+ * List adapter for search activity.
+ */
public class SearchlistAdapter extends BaseAdapter {
- private final Context context;
+ private final Context context;
private final ItemAccess itemAccess;
+ private final int imageSize;
+
public SearchlistAdapter(Context context, ItemAccess itemAccess) {
this.context = context;
this.itemAccess = itemAccess;
+ this.imageSize = (int) context.getResources().getDimension(R.dimen.thumbnail_length);
}
@Override
@@ -44,61 +47,65 @@ public class SearchlistAdapter extends BaseAdapter {
}
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final Holder holder;
- SearchResult result = getItem(position);
- FeedComponent component = result.getComponent();
-
- // Inflate Layout
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.searchlist_item, parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.cover = (ImageView) convertView
- .findViewById(R.id.imgvFeedimage);
- holder.subtitle = (TextView) convertView
- .findViewById(R.id.txtvSubtitle);
-
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
- if (component.getClass() == Feed.class) {
- final Feed feed = (Feed) component;
- holder.title.setText(feed.getTitle());
- holder.subtitle.setVisibility(View.GONE);
- ImageLoader.getInstance().loadThumbnailBitmap(feed.getImage(),
- holder.cover, (int) convertView.getResources().getDimension(R.dimen.thumbnail_length));
- } else if (component.getClass() == FeedItem.class) {
- final FeedItem item = (FeedItem) component;
- holder.title.setText(item.getTitle());
- if (result.getSubtitle() != null) {
- holder.subtitle.setVisibility(View.VISIBLE);
- holder.subtitle.setText(result.getSubtitle());
- }
-
- ImageLoader.getInstance().loadThumbnailBitmap(
- item.getFeed().getImage(),
- holder.cover,
- (int) convertView.getResources().getDimension(
- R.dimen.thumbnail_length));
-
- }
-
- return convertView;
- }
-
- static class Holder {
- ImageView cover;
- TextView title;
- TextView subtitle;
- }
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final Holder holder;
+ SearchResult result = getItem(position);
+ FeedComponent component = result.getComponent();
+
+ // Inflate Layout
+ if (convertView == null) {
+ holder = new Holder();
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ convertView = inflater.inflate(R.layout.searchlist_item, parent, false);
+ holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ holder.cover = (ImageView) convertView
+ .findViewById(R.id.imgvFeedimage);
+ holder.subtitle = (TextView) convertView
+ .findViewById(R.id.txtvSubtitle);
+
+ convertView.setTag(holder);
+ } else {
+ holder = (Holder) convertView.getTag();
+ }
+ if (component.getClass() == Feed.class) {
+ final Feed feed = (Feed) component;
+ holder.title.setText(feed.getTitle());
+ holder.subtitle.setVisibility(View.GONE);
+
+ PicassoProvider.getDefaultPicassoInstance(context)
+ .load(feed.getImageUri())
+ .resize(imageSize, imageSize)
+ .into(holder.cover);
+
+ } else if (component.getClass() == FeedItem.class) {
+ final FeedItem item = (FeedItem) component;
+ holder.title.setText(item.getTitle());
+ if (result.getSubtitle() != null) {
+ holder.subtitle.setVisibility(View.VISIBLE);
+ holder.subtitle.setText(result.getSubtitle());
+ }
+
+ PicassoProvider.getDefaultPicassoInstance(context)
+ .load(item.getFeed().getImageUri())
+ .resize(imageSize, imageSize)
+ .into(holder.cover);
+
+ }
+
+ return convertView;
+ }
+
+ static class Holder {
+ ImageView cover;
+ TextView title;
+ TextView subtitle;
+ }
public static interface ItemAccess {
int getCount();
+
SearchResult getItem(int position);
}
diff --git a/src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java b/src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java
index f20232a6f..dcad2d524 100644
--- a/src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java
@@ -7,22 +7,21 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageDiskCache;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
import java.util.List;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
+import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
+
/**
* Adapter for displaying a list of GPodnetPodcast-Objects.
*/
public class PodcastListAdapter extends ArrayAdapter<GpodnetPodcast> {
- private final ImageDiskCache diskCache;
private final int thumbnailLength;
public PodcastListAdapter(Context context, int resource, List<GpodnetPodcast> objects) {
super(context, resource, objects);
- diskCache = ImageDiskCache.getDefaultInstance();
thumbnailLength = (int) context.getResources().getDimension(R.dimen.thumbnail_length);
}
@@ -50,7 +49,11 @@ public class PodcastListAdapter extends ArrayAdapter<GpodnetPodcast> {
holder.title.setText(podcast.getTitle());
holder.description.setText(podcast.getDescription());
- diskCache.loadThumbnailBitmap(podcast.getLogoUrl(), holder.image, thumbnailLength);
+
+ PicassoProvider.getDefaultPicassoInstance(convertView.getContext())
+ .load(podcast.getLogoUrl())
+ .resize(thumbnailLength, thumbnailLength)
+ .into(holder.image);
return convertView;
}
diff --git a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java
deleted file mode 100644
index 43118c3af..000000000
--- a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.TransitionDrawable;
-import android.os.Handler;
-import android.util.Log;
-import android.widget.ImageView;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader.ImageWorkerTaskResource;
-import de.danoeh.antennapod.util.BitmapDecoder;
-
-public class BitmapDecodeWorkerTask extends Thread {
-
- protected int PREFERRED_LENGTH;
- public static final int FADE_DURATION = 500;
-
- /**
- * Can be thumbnail or cover
- */
- protected int imageType;
-
- private static final String TAG = "BitmapDecodeWorkerTask";
- private ImageView target;
- protected CachedBitmap cBitmap;
-
- protected ImageLoader.ImageWorkerTaskResource imageResource;
-
- private Handler handler;
-
- private final int defaultCoverResource;
-
- public BitmapDecodeWorkerTask(Handler handler, ImageView target,
- ImageWorkerTaskResource imageResource, int length, int imageType) {
- super();
- this.handler = handler;
- this.target = target;
- this.imageResource = imageResource;
- this.PREFERRED_LENGTH = length;
- this.imageType = imageType;
- this.defaultCoverResource = android.R.color.transparent;
- }
-
- /**
- * Should return true if tag of the imageview is still the same it was
- * before the bitmap was decoded
- */
- protected boolean tagsMatching(ImageView target) {
- Object tag = target.getTag(R.id.imageloader_key);
- return tag != null && tag.equals(imageResource.getImageLoaderCacheKey());
- }
-
- protected void onPostExecute() {
- // check if imageview is still supposed to display this image
- if (tagsMatching(target) && cBitmap.getBitmap() != null) {
- Drawable[] drawables = new Drawable[]{
- PodcastApp.getInstance().getResources().getDrawable(android.R.color.transparent),
- new BitmapDrawable(PodcastApp.getInstance().getResources(), cBitmap.getBitmap())
- };
- TransitionDrawable transitionDrawable = new TransitionDrawable(drawables);
- target.setImageDrawable(transitionDrawable);
- transitionDrawable.startTransition(FADE_DURATION);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Not displaying image");
- }
- }
-
- @Override
- public void run() {
- cBitmap = new CachedBitmap(BitmapDecoder.decodeBitmapFromWorkerTaskResource(
- PREFERRED_LENGTH, imageResource), PREFERRED_LENGTH);
- if (cBitmap.getBitmap() != null) {
- storeBitmapInCache(cBitmap);
- } else {
- Log.w(TAG, "Could not load bitmap. Using default image.");
- cBitmap = new CachedBitmap(BitmapFactory.decodeResource(
- target.getResources(), defaultCoverResource),
- PREFERRED_LENGTH);
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Finished loading bitmaps");
-
- endBackgroundTask();
- }
-
- protected final void endBackgroundTask() {
- handler.post(new Runnable() {
-
- @Override
- public void run() {
- onPostExecute();
- }
-
- });
- }
-
- protected void onInvalidStream() {
- cBitmap = new CachedBitmap(BitmapFactory.decodeResource(
- target.getResources(), defaultCoverResource), PREFERRED_LENGTH);
- }
-
- protected void storeBitmapInCache(CachedBitmap cb) {
- ImageLoader loader = ImageLoader.getInstance();
- if (imageType == ImageLoader.IMAGE_TYPE_COVER) {
- loader.addBitmapToCoverCache(imageResource.getImageLoaderCacheKey(), cb);
- } else if (imageType == ImageLoader.IMAGE_TYPE_THUMBNAIL) {
- loader.addBitmapToThumbnailCache(imageResource.getImageLoaderCacheKey(), cb);
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/asynctask/CachedBitmap.java b/src/de/danoeh/antennapod/asynctask/CachedBitmap.java
deleted file mode 100644
index 5a89b7b53..000000000
--- a/src/de/danoeh/antennapod/asynctask/CachedBitmap.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.graphics.Bitmap;
-
-/** Stores a bitmap and the length it was decoded with. */
-public class CachedBitmap {
-
- private Bitmap bitmap;
- private int length;
-
- public CachedBitmap(Bitmap bitmap, int length) {
- super();
- this.bitmap = bitmap;
- this.length = length;
- }
-
- public Bitmap getBitmap() {
- return bitmap;
- }
- public int getLength() {
- return length;
- }
-
-
-
-
-}
diff --git a/src/de/danoeh/antennapod/asynctask/ImageDiskCache.java b/src/de/danoeh/antennapod/asynctask/ImageDiskCache.java
deleted file mode 100644
index 77609f28b..000000000
--- a/src/de/danoeh/antennapod/asynctask/ImageDiskCache.java
+++ /dev/null
@@ -1,397 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.os.Handler;
-import android.util.Log;
-import android.util.Pair;
-import android.widget.ImageView;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.service.download.DownloadRequest;
-import de.danoeh.antennapod.service.download.HttpDownloader;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-
-import java.io.*;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * Provides local cache for storing downloaded image. An image disk cache downloads images and stores them as long
- * as the cache is not full. Once the cache is full, the image disk cache will delete older images.
- */
-public class ImageDiskCache {
- private static final String TAG = "ImageDiskCache";
-
- private static HashMap<String, ImageDiskCache> cacheSingletons = new HashMap<String, ImageDiskCache>();
-
- /**
- * Return a default instance of an ImageDiskCache. This cache will store data in the external cache folder.
- */
- public static synchronized ImageDiskCache getDefaultInstance() {
- final String DEFAULT_PATH = "imagecache";
- final long DEFAULT_MAX_CACHE_SIZE = 10 * 1024 * 1024;
-
- File cacheDir = PodcastApp.getInstance().getExternalCacheDir();
- if (cacheDir == null) {
- return null;
- }
- return getInstance(new File(cacheDir, DEFAULT_PATH).getAbsolutePath(), DEFAULT_MAX_CACHE_SIZE);
- }
-
- /**
- * Return an instance of an ImageDiskCache that stores images in the specified folder.
- */
- public static synchronized ImageDiskCache getInstance(String path, long maxCacheSize) {
- Validate.notNull(path);
-
- if (cacheSingletons.containsKey(path)) {
- return cacheSingletons.get(path);
- }
-
- ImageDiskCache cache = cacheSingletons.get(path);
- if (cache == null) {
- cache = new ImageDiskCache(path, maxCacheSize);
- cacheSingletons.put(new File(path).getAbsolutePath(), cache);
- }
- cacheSingletons.put(path, cache);
- return cache;
- }
-
- /**
- * Filename - cache object mapping
- */
- private static final String CACHE_FILE_NAME = "cachefile";
- private ExecutorService executor;
- private ConcurrentHashMap<String, DiskCacheObject> diskCache;
- private final long maxCacheSize;
- private int cacheSize;
- private final File cacheFolder;
- private Handler handler;
-
- private ImageDiskCache(String path, long maxCacheSize) {
- this.maxCacheSize = maxCacheSize;
- this.cacheFolder = new File(path);
- if (!cacheFolder.exists() && !cacheFolder.mkdir()) {
- throw new IllegalArgumentException("Image disk cache could not create cache folder in: " + path);
- }
-
- executor = Executors.newFixedThreadPool(Runtime.getRuntime()
- .availableProcessors());
- handler = new Handler();
- }
-
- private synchronized void initCacheFolder() {
- if (diskCache == null) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Initializing cache folder");
- File cacheFile = new File(cacheFolder, CACHE_FILE_NAME);
- if (cacheFile.exists()) {
- try {
- InputStream in = new FileInputStream(cacheFile);
- BufferedInputStream buffer = new BufferedInputStream(in);
- ObjectInputStream objectInput = new ObjectInputStream(buffer);
- diskCache = (ConcurrentHashMap<String, DiskCacheObject>) objectInput.readObject();
- // calculate cache size
- for (DiskCacheObject dco : diskCache.values()) {
- cacheSize += dco.size;
- }
- deleteInvalidFiles();
- } catch (IOException e) {
- e.printStackTrace();
- diskCache = new ConcurrentHashMap<String, DiskCacheObject>();
- } catch (ClassCastException e) {
- e.printStackTrace();
- diskCache = new ConcurrentHashMap<String, DiskCacheObject>();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- diskCache = new ConcurrentHashMap<String, DiskCacheObject>();
- }
- } else {
- diskCache = new ConcurrentHashMap<String, DiskCacheObject>();
- }
- }
- }
-
- private List<File> getCacheFileList() {
- Collection<DiskCacheObject> values = diskCache.values();
- List<File> files = new ArrayList<File>();
- for (DiskCacheObject dco : values) {
- files.add(dco.getFile());
- }
- files.add(new File(cacheFolder, CACHE_FILE_NAME));
- return files;
- }
-
- private Pair<String, DiskCacheObject> getOldestCacheObject() {
- Collection<String> keys = diskCache.keySet();
- DiskCacheObject oldest = null;
- String oldestKey = null;
-
- for (String key : keys) {
-
- if (oldestKey == null) {
- oldestKey = key;
- oldest = diskCache.get(key);
- } else {
- DiskCacheObject dco = diskCache.get(key);
- if (oldest.timestamp > dco.timestamp) {
- oldestKey = key;
- oldest = diskCache.get(key);
- }
- }
- }
- return new Pair<String, DiskCacheObject>(oldestKey, oldest);
- }
-
- private synchronized void deleteCacheObject(String key, DiskCacheObject value) {
- Log.i(TAG, "Deleting cached object: " + key);
- diskCache.remove(key);
- boolean result = value.getFile().delete();
- if (!result) {
- Log.w(TAG, "Could not delete file " + value.fileUrl);
- }
- cacheSize -= value.size;
- }
-
- private synchronized void deleteInvalidFiles() {
- // delete files that are not stored inside the cache
- File[] files = cacheFolder.listFiles();
- List<File> cacheFiles = getCacheFileList();
- for (File file : files) {
- if (!cacheFiles.contains(file)) {
- Log.i(TAG, "Deleting unused file: " + file.getAbsolutePath());
- boolean result = file.delete();
- if (!result) {
- Log.w(TAG, "Could not delete file: " + file.getAbsolutePath());
- }
- }
- }
- }
-
- private synchronized void cleanup() {
- if (cacheSize > maxCacheSize) {
- while (cacheSize > maxCacheSize) {
- Pair<String, DiskCacheObject> oldest = getOldestCacheObject();
- deleteCacheObject(oldest.first, oldest.second);
- }
- }
- }
-
- /**
- * Loads a new image from the disk cache. If the image that the url points to has already been downloaded, the image will
- * be loaded from the disk. Otherwise, the image will be downloaded first.
- * The image will be stored in the thumbnail cache.
- */
- public void loadThumbnailBitmap(final String url, final ImageView target, final int length) {
- if (url == null) {
- Log.w(TAG, "loadThumbnailBitmap: Call was ignored because url = null");
- return;
- }
- final ImageLoader il = ImageLoader.getInstance();
- target.setTag(R.id.image_disk_cache_key, url);
- if (diskCache != null) {
- DiskCacheObject dco = getFromCacheIfAvailable(url);
- if (dco != null) {
- il.loadThumbnailBitmap(dco.loadImage(), target, length);
- return;
- }
- }
- target.setImageResource(android.R.color.transparent);
- executor.submit(new ImageDownloader(url) {
- @Override
- protected void onImageLoaded(DiskCacheObject diskCacheObject) {
- final Object tag = target.getTag(R.id.image_disk_cache_key);
- if (tag != null && StringUtils.equals((String) tag, url)) {
- il.loadThumbnailBitmap(diskCacheObject.loadImage(), target, length);
- }
- }
- });
-
- }
-
- /**
- * Loads a new image from the disk cache. If the image that the url points to has already been downloaded, the image will
- * be loaded from the disk. Otherwise, the image will be downloaded first.
- * The image will be stored in the cover cache.
- */
- public void loadCoverBitmap(final String url, final ImageView target, final int length) {
- if (url == null) {
- Log.w(TAG, "loadCoverBitmap: Call was ignored because url = null");
- return;
- }
- final ImageLoader il = ImageLoader.getInstance();
- target.setTag(R.id.image_disk_cache_key, url);
- if (diskCache != null) {
- DiskCacheObject dco = getFromCacheIfAvailable(url);
- if (dco != null) {
- il.loadThumbnailBitmap(dco.loadImage(), target, length);
- return;
- }
- }
- target.setImageResource(android.R.color.transparent);
- executor.submit(new ImageDownloader(url) {
- @Override
- protected void onImageLoaded(DiskCacheObject diskCacheObject) {
- final Object tag = target.getTag(R.id.image_disk_cache_key);
- if (tag != null && StringUtils.equals((String) tag, url)) {
- il.loadCoverBitmap(diskCacheObject.loadImage(), target, length);
- }
- }
- });
- }
-
- private synchronized void addToDiskCache(String url, DiskCacheObject obj) {
- if (diskCache == null) {
- initCacheFolder();
- }
- if (BuildConfig.DEBUG) Log.d(TAG, "Adding new image to disk cache: " + url);
- diskCache.put(url, obj);
- cacheSize += obj.size;
- if (cacheSize > maxCacheSize) {
- cleanup();
- }
- saveCacheInfoFile();
- }
-
- private synchronized void saveCacheInfoFile() {
- OutputStream out = null;
- try {
- out = new BufferedOutputStream(new FileOutputStream(new File(cacheFolder, CACHE_FILE_NAME)));
- ObjectOutputStream objOut = new ObjectOutputStream(out);
- objOut.writeObject(diskCache);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- IOUtils.closeQuietly(out);
- }
- }
-
- private synchronized DiskCacheObject getFromCacheIfAvailable(String key) {
- if (diskCache == null) {
- initCacheFolder();
- }
- DiskCacheObject dco = diskCache.get(key);
- if (dco != null) {
- dco.timestamp = System.currentTimeMillis();
- }
- return dco;
- }
-
- ConcurrentHashMap<String, File> runningDownloads = new ConcurrentHashMap<String, File>();
-
- private abstract class ImageDownloader implements Runnable {
- private String downloadUrl;
-
- public ImageDownloader(String downloadUrl) {
- this.downloadUrl = downloadUrl;
- }
-
- protected abstract void onImageLoaded(DiskCacheObject diskCacheObject);
-
- public void run() {
- DiskCacheObject tmp = getFromCacheIfAvailable(downloadUrl);
- if (tmp != null) {
- onImageLoaded(tmp);
- return;
- }
-
- DiskCacheObject dco = null;
- File newFile = new File(cacheFolder, Integer.toString(downloadUrl.hashCode()));
- synchronized (ImageDiskCache.this) {
- if (runningDownloads.containsKey(newFile.getAbsolutePath())) {
- Log.d(TAG, "Download is already running: " + newFile.getAbsolutePath());
- return;
- } else {
- runningDownloads.put(newFile.getAbsolutePath(), newFile);
- }
- }
- if (newFile.exists()) {
- newFile.delete();
- }
-
- HttpDownloader result = downloadFile(newFile.getAbsolutePath(), downloadUrl);
- if (result.getResult().isSuccessful()) {
- long size = result.getDownloadRequest().getSoFar();
-
- dco = new DiskCacheObject(newFile.getAbsolutePath(), size);
- addToDiskCache(downloadUrl, dco);
- if (BuildConfig.DEBUG) Log.d(TAG, "Image was downloaded");
- } else {
- Log.w(TAG, "Download of url " + downloadUrl + " failed. Reason: " + result.getResult().getReasonDetailed() + "(" + result.getResult().getReason() + ")");
- }
-
- if (dco != null) {
- final DiskCacheObject dcoRef = dco;
- handler.post(new Runnable() {
- @Override
- public void run() {
- onImageLoaded(dcoRef);
- }
- });
-
- }
- runningDownloads.remove(newFile.getAbsolutePath());
-
- }
-
- private HttpDownloader downloadFile(String destination, String source) {
- DownloadRequest request = new DownloadRequest(destination, source, "", 0, 0);
- HttpDownloader downloader = new HttpDownloader(request);
- downloader.call();
- return downloader;
- }
- }
-
- private static class DiskCacheObject implements Serializable {
- private final String fileUrl;
-
- /**
- * Last usage of this image cache object.
- */
- private long timestamp;
- private final long size;
-
- public DiskCacheObject(String fileUrl, long size) {
- Validate.notNull(fileUrl);
- this.fileUrl = fileUrl;
- this.timestamp = System.currentTimeMillis();
- this.size = size;
- }
-
- public File getFile() {
- return new File(fileUrl);
- }
-
- public ImageLoader.ImageWorkerTaskResource loadImage() {
- return new ImageLoader.ImageWorkerTaskResource() {
-
- @Override
- public InputStream openImageInputStream() {
- try {
- return new FileInputStream(getFile());
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- @Override
- public InputStream reopenImageInputStream(InputStream input) {
- IOUtils.closeQuietly(input);
- return openImageInputStream();
- }
-
- @Override
- public String getImageLoaderCacheKey() {
- return fileUrl;
- }
- };
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/asynctask/ImageLoader.java b/src/de/danoeh/antennapod/asynctask/ImageLoader.java
deleted file mode 100644
index 6c60b7b1f..000000000
--- a/src/de/danoeh/antennapod/asynctask/ImageLoader.java
+++ /dev/null
@@ -1,246 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.os.Handler;
-import android.support.v4.util.LruCache;
-import android.util.Log;
-import android.widget.ImageView;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.R;
-
-import java.io.InputStream;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-
-/**
- * Caches and loads FeedImage bitmaps in the background
- */
-public class ImageLoader {
- private static final String TAG = "ImageLoader";
- private static ImageLoader singleton;
-
- public static final int IMAGE_TYPE_THUMBNAIL = 0;
- public static final int IMAGE_TYPE_COVER = 1;
-
- /**
- * Used by loadThumbnailBitmap and loadCoverBitmap to denote an ImageView that displays the default image resource.
- * This is the case if the given source to load the image from was null or did not return any image data.
- */
- private static final Object DEFAULT_IMAGE_RESOURCE_TAG = new Object();
-
- private Handler handler;
- private ExecutorService executor;
-
- /**
- * Stores references to loaded bitmaps. Bitmaps can be accessed by the id of
- * the FeedImage the bitmap belongs to.
- */
-
- final int memClass = ((ActivityManager) PodcastApp.getInstance()
- .getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
-
- // Use 1/8th of the available memory for this memory cache.
- final int thumbnailCacheSize = 1024 * 1024 * memClass / 8;
-
- private LruCache<String, CachedBitmap> coverCache;
- private LruCache<String, CachedBitmap> thumbnailCache;
-
- private ImageLoader() {
- handler = new Handler();
- executor = createExecutor();
-
- coverCache = new LruCache<String, CachedBitmap>(1);
-
- thumbnailCache = new LruCache<String, CachedBitmap>(thumbnailCacheSize) {
-
- @SuppressLint("NewApi")
- @Override
- protected int sizeOf(String key, CachedBitmap value) {
- if (Integer.valueOf(android.os.Build.VERSION.SDK_INT) >= 12)
- return value.getBitmap().getByteCount();
- else
- return (value.getBitmap().getRowBytes() * value.getBitmap()
- .getHeight());
-
- }
-
- };
- }
-
- private ExecutorService createExecutor() {
- return Executors.newFixedThreadPool(Runtime.getRuntime()
- .availableProcessors(), new ThreadFactory() {
-
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setPriority(Thread.MIN_PRIORITY);
- return t;
- }
- });
- }
-
- public static synchronized ImageLoader getInstance() {
- if (singleton == null) {
- singleton = new ImageLoader();
- }
- return singleton;
- }
-
- /**
- * Load a bitmap from the cover cache. If the bitmap is not in the cache, it
- * will be loaded from the disk. This method should either be called if the
- * ImageView's size has already been set or inside a Runnable which is
- * posted to the ImageView's message queue.
- */
- public void loadCoverBitmap(ImageWorkerTaskResource source, ImageView target) {
- loadCoverBitmap(source, target, target.getHeight());
- }
-
- /**
- * Load a bitmap from the cover cache. If the bitmap is not in the cache, it
- * will be loaded from the disk. This method should either be called if the
- * ImageView's size has already been set or inside a Runnable which is
- * posted to the ImageView's message queue.
- */
- public void loadCoverBitmap(ImageWorkerTaskResource source,
- ImageView target, int length) {
- final int defaultCoverResource = getDefaultCoverResource(target
- .getContext());
- final String cacheKey;
- if (source != null && (cacheKey = source.getImageLoaderCacheKey()) != null) {
- final Object currentTag = target.getTag(R.id.imageloader_key);
- if (currentTag == null || !cacheKey.equals(currentTag)) {
- target.setTag(R.id.imageloader_key, cacheKey);
- CachedBitmap cBitmap = getBitmapFromCoverCache(cacheKey);
- if (cBitmap != null && cBitmap.getLength() >= length) {
- target.setImageBitmap(cBitmap.getBitmap());
- } else {
- target.setImageResource(defaultCoverResource);
- BitmapDecodeWorkerTask worker = new BitmapDecodeWorkerTask(
- handler, target, source, length, IMAGE_TYPE_COVER);
- executor.submit(worker);
- }
- }
- } else {
- target.setImageResource(defaultCoverResource);
- target.setTag(R.id.imageloader_key, DEFAULT_IMAGE_RESOURCE_TAG);
- }
- }
-
- /**
- * Load a bitmap from the thumbnail cache. If the bitmap is not in the
- * cache, it will be loaded from the disk. This method should either be
- * called if the ImageView's size has already been set or inside a Runnable
- * which is posted to the ImageView's message queue.
- */
- public void loadThumbnailBitmap(ImageWorkerTaskResource source,
- ImageView target) {
- loadThumbnailBitmap(source, target, target.getHeight());
- }
-
- /**
- * Load a bitmap from the thumbnail cache. If the bitmap is not in the
- * cache, it will be loaded from the disk. This method should either be
- * called if the ImageView's size has already been set or inside a Runnable
- * which is posted to the ImageView's message queue.
- */
- public void loadThumbnailBitmap(ImageWorkerTaskResource source,
- ImageView target, int length) {
- final int defaultCoverResource = getDefaultCoverResource(target
- .getContext());
- final String cacheKey;
- if (source != null && (cacheKey = source.getImageLoaderCacheKey()) != null) {
- final Object currentTag = target.getTag(R.id.imageloader_key);
- if (currentTag == null || !cacheKey.equals(currentTag)) {
- target.setTag(R.id.imageloader_key, cacheKey);
- CachedBitmap cBitmap = getBitmapFromThumbnailCache(cacheKey);
- if (cBitmap != null && cBitmap.getLength() >= length) {
- target.setImageBitmap(cBitmap.getBitmap());
- } else {
- target.setImageResource(defaultCoverResource);
- BitmapDecodeWorkerTask worker = new BitmapDecodeWorkerTask(
- handler, target, source, length, IMAGE_TYPE_THUMBNAIL);
- executor.submit(worker);
- }
- }
- } else {
- target.setImageResource(defaultCoverResource);
- target.setTag(R.id.imageloader_key, DEFAULT_IMAGE_RESOURCE_TAG);
- }
- }
-
- public void clearExecutorQueue() {
- executor.shutdownNow();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Executor was shut down.");
- executor = createExecutor();
-
- }
-
- public void wipeImageCache() {
- coverCache.evictAll();
- thumbnailCache.evictAll();
- }
-
- public boolean isInThumbnailCache(String fileUrl) {
- return thumbnailCache.get(fileUrl) != null;
- }
-
- private CachedBitmap getBitmapFromThumbnailCache(String key) {
- return thumbnailCache.get(key);
- }
-
- public void addBitmapToThumbnailCache(String key, CachedBitmap bitmap) {
- thumbnailCache.put(key, bitmap);
- }
-
- public boolean isInCoverCache(String fileUrl) {
- return coverCache.get(fileUrl) != null;
- }
-
- private CachedBitmap getBitmapFromCoverCache(String key) {
- return coverCache.get(key);
- }
-
- public void addBitmapToCoverCache(String key, CachedBitmap bitmap) {
- coverCache.put(key, bitmap);
- }
-
- private int getDefaultCoverResource(Context context) {
- return android.R.color.transparent;
- }
-
- /**
- * Used by the BitmapDecodeWorker task to retrieve the source of the bitmap.
- */
- public interface ImageWorkerTaskResource {
- /**
- * Opens a new InputStream that can be decoded as a bitmap by the
- * BitmapFactory.
- */
- public InputStream openImageInputStream();
-
- /**
- * Returns an InputStream that points to the beginning of the image
- * resource. Implementations can either create a new InputStream or
- * reset the existing one, depending on their implementation of
- * openInputStream. If a new InputStream is returned, the one given as a
- * parameter MUST be closed.
- *
- * @param input The input stream that was returned by openImageInputStream()
- */
- public InputStream reopenImageInputStream(InputStream input);
-
- /**
- * Returns a string that identifies the image resource. Example: file
- * path of an image
- */
- public String getImageLoaderCacheKey();
- }
-
-}
diff --git a/src/de/danoeh/antennapod/asynctask/PicassoImageResource.java b/src/de/danoeh/antennapod/asynctask/PicassoImageResource.java
new file mode 100644
index 000000000..84179cfcb
--- /dev/null
+++ b/src/de/danoeh/antennapod/asynctask/PicassoImageResource.java
@@ -0,0 +1,25 @@
+package de.danoeh.antennapod.asynctask;
+
+import android.net.Uri;
+
+/**
+ * Classes that implement this interface provide access to an image resource that can
+ * be loaded by the Picasso library.
+ */
+public interface PicassoImageResource {
+
+ /**
+ * This scheme should be used by PicassoImageResources to
+ * indicate that the image Uri points to a file that is not an image
+ * (e.g. a media file). This workaround is needed so that the Picasso library
+ * loads these Uri with a Downloader instead of trying to load it directly.
+ * <p/>
+ * For example implementations, see FeedMedia or ExternalMedia.
+ */
+ public static final String SCHEME_MEDIA = "media";
+
+ /**
+ * Returns a Uri to the image or null if no image is available.
+ */
+ public Uri getImageUri();
+}
diff --git a/src/de/danoeh/antennapod/asynctask/PicassoProvider.java b/src/de/danoeh/antennapod/asynctask/PicassoProvider.java
new file mode 100644
index 000000000..fe70a9343
--- /dev/null
+++ b/src/de/danoeh/antennapod/asynctask/PicassoProvider.java
@@ -0,0 +1,137 @@
+package de.danoeh.antennapod.asynctask;
+
+import android.content.Context;
+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 org.apache.commons.io.FilenameUtils;
+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.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Provides access to Picasso instances.
+ */
+public class PicassoProvider {
+ private static final String TAG = "PicassoProvider";
+
+ private static final boolean DEBUG = false;
+
+ 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);
+ }
+ return executorService;
+ }
+
+ private static synchronized Cache getMemoryCache(Context context) {
+ if (memoryCache == null) {
+ memoryCache = new LruCache(context);
+ }
+ 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;
+ }
+
+ /**
+ * 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();
+ }
+ return mediaMetadataPicassoInstance;
+ }
+
+ private static class MediaMetadataDownloader implements Downloader {
+
+ private static final String TAG = "MediaMetadataDownloader";
+
+ private final OkHttpDownloader okHttpDownloader;
+
+ public MediaMetadataDownloader(Context context) {
+ Validate.notNull(context);
+ okHttpDownloader = new OkHttpDownloader(context);
+ }
+
+ @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());
+ } else {
+ MediaMetadataRetriever mmr = new MediaMetadataRetriever();
+ mmr.setDataSource(uri.getPath());
+ byte[] data = mmr.getEmbeddedPicture();
+ mmr.release();
+ return new Response(new ByteArrayInputStream(data), true, data.length);
+ }
+ }
+
+ return okHttpDownloader.load(uri, b);
+ }
+ }
+}
diff --git a/src/de/danoeh/antennapod/feed/Feed.java b/src/de/danoeh/antennapod/feed/Feed.java
index f9da65e03..b5415c69c 100644
--- a/src/de/danoeh/antennapod/feed/Feed.java
+++ b/src/de/danoeh/antennapod/feed/Feed.java
@@ -1,6 +1,9 @@
package de.danoeh.antennapod.feed;
import android.content.Context;
+import android.net.Uri;
+
+import de.danoeh.antennapod.asynctask.PicassoImageResource;
import de.danoeh.antennapod.preferences.UserPreferences;
import de.danoeh.antennapod.storage.DBWriter;
import de.danoeh.antennapod.util.EpisodeFilter;
@@ -16,7 +19,7 @@ import java.util.List;
*
* @author daniel
*/
-public class Feed extends FeedFile implements FlattrThing {
+public class Feed extends FeedFile implements FlattrThing, PicassoImageResource {
public static final int FEEDFILETYPE_FEED = 0;
public static final String TYPE_RSS2 = "rss";
public static final String TYPE_RSS091 = "rss";
@@ -430,4 +433,13 @@ public class Feed extends FeedFile implements FlattrThing {
preferences.setFeedID(id);
}
}
+
+ @Override
+ public Uri getImageUri() {
+ if (image != null) {
+ return image.getImageUri();
+ } else {
+ return null;
+ }
+ }
}
diff --git a/src/de/danoeh/antennapod/feed/FeedImage.java b/src/de/danoeh/antennapod/feed/FeedImage.java
index 9c9170294..c588f5e71 100644
--- a/src/de/danoeh/antennapod/feed/FeedImage.java
+++ b/src/de/danoeh/antennapod/feed/FeedImage.java
@@ -1,6 +1,9 @@
package de.danoeh.antennapod.feed;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import android.net.Uri;
+
+import de.danoeh.antennapod.asynctask.PicassoImageResource;
+
import org.apache.commons.io.IOUtils;
import java.io.File;
@@ -10,8 +13,7 @@ import java.io.InputStream;
-public class FeedImage extends FeedFile implements
- ImageLoader.ImageWorkerTaskResource {
+public class FeedImage extends FeedFile implements PicassoImageResource {
public static final int FEEDFILETYPE_FEEDIMAGE = 1;
protected String title;
@@ -64,30 +66,12 @@ public class FeedImage extends FeedFile implements
this.owner = owner;
}
- @Override
- public InputStream openImageInputStream() {
- if (file_url != null) {
- File file = new File(file_url);
- if (file.exists()) {
- try {
- return new FileInputStream(file_url);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- }
- }
- return null;
- }
-
- @Override
- public String getImageLoaderCacheKey() {
- return file_url;
- }
-
- @Override
- public InputStream reopenImageInputStream(InputStream input) {
- IOUtils.closeQuietly(input);
- return openImageInputStream();
- }
-
+ @Override
+ public Uri getImageUri() {
+ if (file_url != null && downloaded) {
+ return Uri.fromFile(new File(file_url));
+ } else {
+ return null;
+ }
+ }
}
diff --git a/src/de/danoeh/antennapod/feed/FeedItem.java b/src/de/danoeh/antennapod/feed/FeedItem.java
index 956131ab2..78091ea33 100644
--- a/src/de/danoeh/antennapod/feed/FeedItem.java
+++ b/src/de/danoeh/antennapod/feed/FeedItem.java
@@ -1,7 +1,9 @@
package de.danoeh.antennapod.feed;
+import android.net.Uri;
+
import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoImageResource;
import de.danoeh.antennapod.storage.DBReader;
import de.danoeh.antennapod.util.ShownotesProvider;
import de.danoeh.antennapod.util.flattr.FlattrStatus;
@@ -17,8 +19,7 @@ import java.util.concurrent.Callable;
*
* @author daniel
*/
-public class FeedItem extends FeedComponent implements
- ImageLoader.ImageWorkerTaskResource, ShownotesProvider, FlattrThing {
+public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, PicassoImageResource {
/**
* The id/guid that can be found in the rss/atom feed. Might not be set.
@@ -261,6 +262,17 @@ public class FeedItem extends FeedComponent implements
};
}
+ @Override
+ public Uri getImageUri() {
+ if (hasMedia()) {
+ return media.getImageUri();
+ } else if (feed != null) {
+ return feed.getImageUri();
+ } else {
+ return null;
+ }
+ }
+
public enum State {
NEW, IN_PROGRESS, READ, PLAYING
}
@@ -277,45 +289,6 @@ public class FeedItem extends FeedComponent implements
return (isRead() ? State.READ : State.NEW);
}
- @Override
- public InputStream openImageInputStream() {
- InputStream out = null;
- if (hasItemImageDownloaded()) {
- out = image.openImageInputStream();
- } else if (hasMedia()) {
- out = media.openImageInputStream();
- } else if (feed.getImage() != null) {
- out = feed.getImage().openImageInputStream();
- }
- return out;
- }
-
- @Override
- public InputStream reopenImageInputStream(InputStream input) {
- InputStream out = null;
- if (hasItemImageDownloaded()) {
- out = image.reopenImageInputStream(input);
- } else if (hasMedia()) {
- out = media.reopenImageInputStream(input);
- } else if (feed.getImage() != null) {
- out = feed.getImage().reopenImageInputStream(input);
- }
- return out;
- }
-
- @Override
- public String getImageLoaderCacheKey() {
- String out = null;
- if (hasItemImageDownloaded()) {
- out = image.getImageLoaderCacheKey();
- } else if (hasMedia()) {
- out = media.getImageLoaderCacheKey();
- } else if (feed.getImage() != null) {
- out = feed.getImage().getImageLoaderCacheKey();
- }
- return out;
- }
-
public long getFeedId() {
return feedId;
}
diff --git a/src/de/danoeh/antennapod/feed/FeedMedia.java b/src/de/danoeh/antennapod/feed/FeedMedia.java
index dc941cb48..f555654d0 100644
--- a/src/de/danoeh/antennapod/feed/FeedMedia.java
+++ b/src/de/danoeh/antennapod/feed/FeedMedia.java
@@ -2,21 +2,24 @@ package de.danoeh.antennapod.feed;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.ChapterUtils;
-import de.danoeh.antennapod.util.playback.Playable;
+import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
+import de.danoeh.antennapod.PodcastApp;
+import de.danoeh.antennapod.preferences.PlaybackPreferences;
+import de.danoeh.antennapod.storage.DBReader;
+import de.danoeh.antennapod.storage.DBWriter;
+import de.danoeh.antennapod.util.ChapterUtils;
+import de.danoeh.antennapod.util.playback.Playable;
+
public class FeedMedia extends FeedFile implements Playable {
private static final String TAG = "FeedMedia";
@@ -382,52 +385,13 @@ public class FeedMedia extends FeedFile implements Playable {
};
@Override
- public InputStream openImageInputStream() {
- InputStream out;
- if (item.hasItemImageDownloaded()) {
- out = item.openImageInputStream();
+ public Uri getImageUri() {
+ if (localFileAvailable()) {
+ return new Uri.Builder().scheme(SCHEME_MEDIA).encodedPath(getLocalMediaUrl()).build();
+ } else if (item != null && item.getFeed() != null) {
+ return item.getFeed().getImageUri();
} else {
- out = new Playable.DefaultPlayableImageLoader(this)
- .openImageInputStream();
- }
- if (out == null) {
- if (item.getFeed().getImage() != null) {
- return item.getFeed().getImage().openImageInputStream();
- }
- }
- return out;
- }
-
- @Override
- public String getImageLoaderCacheKey() {
- String out;
- if (item == null) {
return null;
- } else if (item.hasItemImageDownloaded()) {
- out = item.getImageLoaderCacheKey();
- } else {
- out = new Playable.DefaultPlayableImageLoader(this)
- .getImageLoaderCacheKey();
- }
- if (out == null) {
- if (item.getFeed().getImage() != null) {
- return item.getFeed().getImage().getImageLoaderCacheKey();
- }
- }
- return out;
- }
-
- @Override
- public InputStream reopenImageInputStream(InputStream input) {
- if (input instanceof FileInputStream) {
- if (item.hasItemImageDownloaded()) {
- return item.getImage().reopenImageInputStream(input);
- } else {
- return item.getFeed().getImage().reopenImageInputStream(input);
- }
- } else {
- return new Playable.DefaultPlayableImageLoader(this)
- .reopenImageInputStream(input);
}
}
}
diff --git a/src/de/danoeh/antennapod/fragment/CoverFragment.java b/src/de/danoeh/antennapod/fragment/CoverFragment.java
index 0e1fe35e0..ffce518bf 100644
--- a/src/de/danoeh/antennapod/fragment/CoverFragment.java
+++ b/src/de/danoeh/antennapod/fragment/CoverFragment.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.fragment;
+import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
@@ -7,91 +8,98 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
+
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.util.playback.Playable;
-/** Displays the cover and the title of a FeedItem. */
+/**
+ * Displays the cover and the title of a FeedItem.
+ */
public class CoverFragment extends Fragment implements
- AudioplayerContentFragment {
- private static final String TAG = "CoverFragment";
- private static final String ARG_PLAYABLE = "arg.playable";
+ AudioplayerContentFragment {
+ private static final String TAG = "CoverFragment";
+ private static final String ARG_PLAYABLE = "arg.playable";
- private Playable media;
+ private Playable media;
- private ImageView imgvCover;
+ private ImageView imgvCover;
- private boolean viewCreated = false;
+ private boolean viewCreated = false;
- public static CoverFragment newInstance(Playable item) {
- CoverFragment f = new CoverFragment();
- if (item != null) {
- Bundle args = new Bundle();
- args.putParcelable(ARG_PLAYABLE, item);
- f.setArguments(args);
- }
- return f;
- }
+ public static CoverFragment newInstance(Playable item) {
+ CoverFragment f = new CoverFragment();
+ if (item != null) {
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_PLAYABLE, item);
+ f.setArguments(args);
+ }
+ return f;
+ }
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setRetainInstance(true);
- Bundle args = getArguments();
- if (args != null) {
- media = args.getParcelable(ARG_PLAYABLE);
- } else {
- Log.e(TAG, TAG + " was called with invalid arguments");
- }
- }
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setRetainInstance(true);
+ Bundle args = getArguments();
+ if (args != null) {
+ media = args.getParcelable(ARG_PLAYABLE);
+ } else {
+ Log.e(TAG, TAG + " was called with invalid arguments");
+ }
+ }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View root = inflater.inflate(R.layout.cover_fragment, container, false);
- imgvCover = (ImageView) root.findViewById(R.id.imgvCover);
- viewCreated = true;
- return root;
- }
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.cover_fragment, container, false);
+ imgvCover = (ImageView) root.findViewById(R.id.imgvCover);
+ viewCreated = true;
+ return root;
+ }
- private void loadMediaInfo() {
- if (media != null) {
- imgvCover.post(new Runnable() {
+ private void loadMediaInfo() {
+ if (media != null) {
+ imgvCover.post(new Runnable() {
- @Override
- public void run() {
- ImageLoader.getInstance().loadCoverBitmap(
- media, imgvCover);
- }
- });
- } else {
- Log.w(TAG, "loadMediaInfo was called while media was null");
- }
- }
+ @Override
+ public void run() {
+ Context c = getActivity();
+ if (c != null) {
+ PicassoProvider.getMediaMetadataPicassoInstance(c)
+ .load(media.getImageUri())
+ .into(imgvCover);
+ }
+ }
+ });
+ } else {
+ Log.w(TAG, "loadMediaInfo was called while media was null");
+ }
+ }
- @Override
- public void onStart() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "On Start");
- super.onStart();
- if (media != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading media info");
- loadMediaInfo();
- } else {
- Log.w(TAG, "Unable to load media info: media was null");
- }
- }
+ @Override
+ public void onStart() {
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "On Start");
+ super.onStart();
+ if (media != null) {
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "Loading media info");
+ loadMediaInfo();
+ } else {
+ Log.w(TAG, "Unable to load media info: media was null");
+ }
+ }
- @Override
- public void onDataSetChanged(Playable media) {
- this.media = media;
- if (viewCreated) {
- loadMediaInfo();
- }
+ @Override
+ public void onDataSetChanged(Playable media) {
+ this.media = media;
+ if (viewCreated) {
+ loadMediaInfo();
+ }
- }
+ }
}
diff --git a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
index db47cd8a4..77587194b 100644
--- a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
+++ b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
@@ -10,9 +10,10 @@ import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
+
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.service.playback.PlaybackService;
import de.danoeh.antennapod.util.Converter;
import de.danoeh.antennapod.util.playback.Playable;
@@ -23,215 +24,216 @@ import de.danoeh.antennapod.util.playback.PlaybackController;
* if the PlaybackService is running
*/
public class ExternalPlayerFragment extends Fragment {
- private static final String TAG = "ExternalPlayerFragment";
-
- private ViewGroup fragmentLayout;
- private ImageView imgvCover;
- private ViewGroup layoutInfo;
- private TextView txtvTitle;
- private ImageButton butPlay;
-
- private PlaybackController controller;
-
- public ExternalPlayerFragment() {
- super();
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View root = inflater.inflate(R.layout.external_player_fragment,
- container, false);
- fragmentLayout = (ViewGroup) root.findViewById(R.id.fragmentLayout);
- imgvCover = (ImageView) root.findViewById(R.id.imgvCover);
- layoutInfo = (ViewGroup) root.findViewById(R.id.layoutInfo);
- txtvTitle = (TextView) root.findViewById(R.id.txtvTitle);
- butPlay = (ImageButton) root.findViewById(R.id.butPlay);
-
- layoutInfo.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "layoutInfo was clicked");
-
- if (controller.getMedia() != null) {
- startActivity(PlaybackService.getPlayerActivityIntent(
- getActivity(), controller.getMedia()));
- }
- }
- });
- return root;
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- controller = setupPlaybackController();
- butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
- }
-
- private PlaybackController setupPlaybackController() {
- return new PlaybackController(getActivity(), true) {
-
- @Override
- public void setupGUI() {
- }
-
- @Override
- public void onPositionObserverUpdate() {
- }
-
- @Override
- public void onReloadNotification(int code) {
- }
-
- @Override
- public void onBufferStart() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onBufferEnd() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onBufferUpdate(float progress) {
- }
-
- @Override
- public void onSleepTimerUpdate() {
- }
-
- @Override
- public void handleError(int code) {
- }
-
- @Override
- public ImageButton getPlayButton() {
- return butPlay;
- }
-
- @Override
- public void postStatusMsg(int msg) {
- }
-
- @Override
- public void clearStatusMsg() {
- }
-
- @Override
- public boolean loadMediaInfo() {
+ private static final String TAG = "ExternalPlayerFragment";
+
+ private ViewGroup fragmentLayout;
+ private ImageView imgvCover;
+ private ViewGroup layoutInfo;
+ private TextView txtvTitle;
+ private ImageButton butPlay;
+
+ private PlaybackController controller;
+
+ public ExternalPlayerFragment() {
+ super();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.external_player_fragment,
+ container, false);
+ fragmentLayout = (ViewGroup) root.findViewById(R.id.fragmentLayout);
+ imgvCover = (ImageView) root.findViewById(R.id.imgvCover);
+ layoutInfo = (ViewGroup) root.findViewById(R.id.layoutInfo);
+ txtvTitle = (TextView) root.findViewById(R.id.txtvTitle);
+ butPlay = (ImageButton) root.findViewById(R.id.butPlay);
+
+ layoutInfo.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "layoutInfo was clicked");
+
+ if (controller.getMedia() != null) {
+ startActivity(PlaybackService.getPlayerActivityIntent(
+ getActivity(), controller.getMedia()));
+ }
+ }
+ });
+ return root;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ controller = setupPlaybackController();
+ butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
+ }
+
+ private PlaybackController setupPlaybackController() {
+ return new PlaybackController(getActivity(), true) {
+
+ @Override
+ public void setupGUI() {
+ }
+
+ @Override
+ public void onPositionObserverUpdate() {
+ }
+
+ @Override
+ public void onReloadNotification(int code) {
+ }
+
+ @Override
+ public void onBufferStart() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onBufferEnd() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onBufferUpdate(float progress) {
+ }
+
+ @Override
+ public void onSleepTimerUpdate() {
+ }
+
+ @Override
+ public void handleError(int code) {
+ }
+
+ @Override
+ public ImageButton getPlayButton() {
+ return butPlay;
+ }
+
+ @Override
+ public void postStatusMsg(int msg) {
+ }
+
+ @Override
+ public void clearStatusMsg() {
+ }
+
+ @Override
+ public boolean loadMediaInfo() {
ExternalPlayerFragment fragment = ExternalPlayerFragment.this;
if (fragment != null) {
- return fragment.loadMediaInfo();
+ return fragment.loadMediaInfo();
} else {
return false;
}
- }
-
- @Override
- public void onAwaitingVideoSurface() {
- }
-
- @Override
- public void onServiceQueried() {
- }
-
- @Override
- public void onShutdownNotification() {
- if (fragmentLayout != null) {
- fragmentLayout.setVisibility(View.GONE);
- }
- controller = setupPlaybackController();
- if (butPlay != null) {
- butPlay.setOnClickListener(controller
- .newOnPlayButtonClickListener());
- }
-
- }
-
- @Override
- public void onPlaybackEnd() {
- if (fragmentLayout != null) {
- fragmentLayout.setVisibility(View.GONE);
- }
- controller = setupPlaybackController();
- if (butPlay != null) {
- butPlay.setOnClickListener(controller
- .newOnPlayButtonClickListener());
- }
- }
-
- @Override
- public void onPlaybackSpeedChange() {
- // TODO Auto-generated method stub
-
- }
- };
- }
-
- @Override
- public void onResume() {
- super.onResume();
- controller.init();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Fragment is about to be destroyed");
- if (controller != null) {
- controller.release();
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- if (controller != null) {
- controller.pause();
- }
- }
-
- private boolean loadMediaInfo() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading media info");
- if (controller.serviceAvailable()) {
- Playable media = controller.getMedia();
- if (media != null) {
- txtvTitle.setText(media.getEpisodeTitle());
- ImageLoader.getInstance().loadThumbnailBitmap(
- media,
- imgvCover,
- (int) getActivity().getResources().getDimension(
- R.dimen.external_player_height));
-
- fragmentLayout.setVisibility(View.VISIBLE);
- if (controller.isPlayingVideo()) {
- butPlay.setVisibility(View.GONE);
- } else {
- butPlay.setVisibility(View.VISIBLE);
- }
+ }
+
+ @Override
+ public void onAwaitingVideoSurface() {
+ }
+
+ @Override
+ public void onServiceQueried() {
+ }
+
+ @Override
+ public void onShutdownNotification() {
+ if (fragmentLayout != null) {
+ fragmentLayout.setVisibility(View.GONE);
+ }
+ controller = setupPlaybackController();
+ if (butPlay != null) {
+ butPlay.setOnClickListener(controller
+ .newOnPlayButtonClickListener());
+ }
+
+ }
+
+ @Override
+ public void onPlaybackEnd() {
+ if (fragmentLayout != null) {
+ fragmentLayout.setVisibility(View.GONE);
+ }
+ controller = setupPlaybackController();
+ if (butPlay != null) {
+ butPlay.setOnClickListener(controller
+ .newOnPlayButtonClickListener());
+ }
+ }
+
+ @Override
+ public void onPlaybackSpeedChange() {
+ // TODO Auto-generated method stub
+
+ }
+ };
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ controller.init();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "Fragment is about to be destroyed");
+ if (controller != null) {
+ controller.release();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (controller != null) {
+ controller.pause();
+ }
+ }
+
+ private boolean loadMediaInfo() {
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "Loading media info");
+ if (controller.serviceAvailable()) {
+ Playable media = controller.getMedia();
+ if (media != null) {
+ txtvTitle.setText(media.getEpisodeTitle());
+
+ int imageSize = (int) getResources().getDimension(R.dimen.external_player_height);
+ PicassoProvider.getMediaMetadataPicassoInstance(getActivity())
+ .load(media.getImageUri())
+ .resize(imageSize, imageSize)
+ .into(imgvCover);
+
+ fragmentLayout.setVisibility(View.VISIBLE);
+ if (controller.isPlayingVideo()) {
+ butPlay.setVisibility(View.GONE);
+ } else {
+ butPlay.setVisibility(View.VISIBLE);
+ }
return true;
- } else {
- Log.w(TAG,
- "loadMediaInfo was called while the media object of playbackService was null!");
+ } else {
+ Log.w(TAG,
+ "loadMediaInfo was called while the media object of playbackService was null!");
return false;
- }
- } else {
- Log.w(TAG,
- "loadMediaInfo was called while playbackService was null!");
+ }
+ } else {
+ Log.w(TAG,
+ "loadMediaInfo was called while playbackService was null!");
return false;
- }
- }
+ }
+ }
- private String getPositionString(int position, int duration) {
- return Converter.getDurationStringLong(position) + " / "
- + Converter.getDurationStringLong(duration);
- }
+ private String getPositionString(int position, int duration) {
+ return Converter.getDurationStringLong(position) + " / "
+ + Converter.getDurationStringLong(duration);
+ }
}
diff --git a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java
index d37f17b6d..5ef914f6c 100644
--- a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -34,7 +34,7 @@ import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
import de.danoeh.antennapod.asynctask.DownloadObserver;
import de.danoeh.antennapod.asynctask.FeedRemover;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.dialog.ConfirmationDialog;
import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.dialog.FeedItemDialog;
@@ -349,8 +349,13 @@ public class ItemlistFragment extends ListFragment {
txtvTitle.setText(feed.getTitle());
txtvAuthor.setText(feed.getAuthor());
- ImageLoader.getInstance().loadThumbnailBitmap(feed.getImage(), imgvCover,
- (int) getResources().getDimension(R.dimen.thumbnail_length_onlinefeedview));
+
+ int imageSize = (int) getResources().getDimension(R.dimen.thumbnail_length_onlinefeedview);
+ PicassoProvider.getDefaultPicassoInstance(getActivity())
+ .load(feed.getImageUri())
+ .resize(imageSize, imageSize)
+ .into(imgvCover);
+
if (feed.getLink() == null) {
butVisitWebsite.setVisibility(View.INVISIBLE);
} else {
diff --git a/src/de/danoeh/antennapod/service/playback/PlaybackService.java b/src/de/danoeh/antennapod/service/playback/PlaybackService.java
index 163a57ed2..59d7ddbb9 100644
--- a/src/de/danoeh/antennapod/service/playback/PlaybackService.java
+++ b/src/de/danoeh/antennapod/service/playback/PlaybackService.java
@@ -4,7 +4,12 @@ import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
-import android.content.*;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
@@ -26,11 +31,14 @@ import android.widget.Toast;
import org.apache.commons.lang3.StringUtils;
+import java.io.IOException;
+import java.util.List;
+
import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AudioplayerActivity;
import de.danoeh.antennapod.activity.VideoplayerActivity;
+import de.danoeh.antennapod.asynctask.PicassoProvider;
import de.danoeh.antennapod.feed.Chapter;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedMedia;
@@ -41,14 +49,10 @@ import de.danoeh.antennapod.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.receiver.PlayerWidget;
import de.danoeh.antennapod.storage.DBTasks;
import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.BitmapDecoder;
import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.flattr.FlattrThing;
import de.danoeh.antennapod.util.flattr.FlattrUtils;
import de.danoeh.antennapod.util.playback.Playable;
-import java.util.List;
-
/**
* Controls the MediaPlayer that plays a FeedMedia-file
*/
@@ -257,7 +261,8 @@ public class PlaybackService extends Service {
}
if ((flags & Service.START_FLAG_REDELIVERY) != 0) {
- if (BuildConfig.DEBUG) Log.d(TAG, "onStartCommand is a redelivered intent, calling stopForeground now.");
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "onStartCommand is a redelivered intent, calling stopForeground now.");
stopForeground(true);
} else {
@@ -678,11 +683,16 @@ public class PlaybackService extends Service {
Log.d(TAG, "Starting background work");
if (android.os.Build.VERSION.SDK_INT >= 11) {
if (info.playable != null) {
- int iconSize = getResources().getDimensionPixelSize(
- android.R.dimen.notification_large_icon_width);
- icon = BitmapDecoder
- .decodeBitmapFromWorkerTaskResource(iconSize,
- info.playable);
+ try {
+ int iconSize = getResources().getDimensionPixelSize(
+ android.R.dimen.notification_large_icon_width);
+ icon = PicassoProvider.getMediaMetadataPicassoInstance(PlaybackService.this)
+ .load(info.playable.getImageUri())
+ .resize(iconSize, iconSize)
+ .get();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
@@ -766,7 +776,7 @@ public class PlaybackService extends Service {
if (updatePlayedDuration && playable instanceof FeedMedia) {
FeedMedia m = (FeedMedia) playable;
FeedItem item = m.getItem();
- m.setPlayedDuration(m.getPlayedDuration() + ((int)(deltaPlayedDuration * playbackSpeed)));
+ m.setPlayedDuration(m.getPlayedDuration() + ((int) (deltaPlayedDuration * playbackSpeed)));
// Auto flattr
if (isAutoFlattrable(m) &&
(m.getPlayedDuration() > UserPreferences.getAutoFlattrPlayedDurationThreshold() * duration)) {
@@ -778,8 +788,9 @@ public class PlaybackService extends Service {
}
}
playable.saveCurrentPosition(PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext()),
- position);
+ .getDefaultSharedPreferences(getApplicationContext()),
+ position
+ );
}
}
diff --git a/src/de/danoeh/antennapod/util/BitmapDecoder.java b/src/de/danoeh/antennapod/util/BitmapDecoder.java
deleted file mode 100644
index 5296d675a..000000000
--- a/src/de/danoeh/antennapod/util/BitmapDecoder.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Rect;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.asynctask.ImageLoader;
-import org.apache.commons.io.IOUtils;
-
-import java.io.InputStream;
-
-public class BitmapDecoder {
- private static final String TAG = "BitmapDecoder";
-
- private static int calculateSampleSize(int preferredLength, int length) {
- int sampleSize = 1;
- if (length > preferredLength) {
- sampleSize = Math.round(((float) length / (float) preferredLength));
- }
- return sampleSize;
- }
-
- public static Bitmap decodeBitmapFromWorkerTaskResource(int preferredLength,
- ImageLoader.ImageWorkerTaskResource source) {
- InputStream input = source.openImageInputStream();
- if (input != null) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(input, new Rect(), options);
- int srcWidth = options.outWidth;
- int srcHeight = options.outHeight;
- int length = Math.max(srcWidth, srcHeight);
- int sampleSize = calculateSampleSize(preferredLength, length);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Using samplesize " + sampleSize);
- options.inJustDecodeBounds = false;
- options.inSampleSize = sampleSize;
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
- Bitmap decodedBitmap = BitmapFactory.decodeStream(source.reopenImageInputStream(input),
- null, options);
- if (decodedBitmap == null) {
- decodedBitmap = BitmapFactory.decodeStream(source.reopenImageInputStream(input));
- }
- IOUtils.closeQuietly(input);
- return decodedBitmap;
- }
- return null;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/playback/ExternalMedia.java b/src/de/danoeh/antennapod/util/playback/ExternalMedia.java
index 390498cea..3f6e6ae0a 100644
--- a/src/de/danoeh/antennapod/util/playback/ExternalMedia.java
+++ b/src/de/danoeh/antennapod/util/playback/ExternalMedia.java
@@ -3,12 +3,14 @@ package de.danoeh.antennapod.util.playback;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.media.MediaMetadataRetriever;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import de.danoeh.antennapod.feed.Chapter;
import de.danoeh.antennapod.feed.MediaType;
import de.danoeh.antennapod.util.ChapterUtils;
+import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.Callable;
@@ -224,22 +226,12 @@ public class ExternalMedia implements Playable {
}
};
- @Override
- public InputStream openImageInputStream() {
- return new Playable.DefaultPlayableImageLoader(this)
- .openImageInputStream();
- }
-
- @Override
- public String getImageLoaderCacheKey() {
- return new Playable.DefaultPlayableImageLoader(this)
- .getImageLoaderCacheKey();
- }
-
- @Override
- public InputStream reopenImageInputStream(InputStream input) {
- return new Playable.DefaultPlayableImageLoader(this)
- .reopenImageInputStream(input);
- }
-
+ @Override
+ public Uri getImageUri() {
+ if (localFileAvailable()) {
+ return new Uri.Builder().scheme(SCHEME_MEDIA).encodedPath(getLocalMediaUrl()).build();
+ } else {
+ return null;
+ }
+ }
}
diff --git a/src/de/danoeh/antennapod/util/playback/Playable.java b/src/de/danoeh/antennapod/util/playback/Playable.java
index 9ed45abfc..004ae56bb 100644
--- a/src/de/danoeh/antennapod/util/playback/Playable.java
+++ b/src/de/danoeh/antennapod/util/playback/Playable.java
@@ -2,27 +2,23 @@ package de.danoeh.antennapod.util.playback;
import android.content.Context;
import android.content.SharedPreferences;
-import android.media.MediaMetadataRetriever;
import android.os.Parcelable;
import android.util.Log;
-import de.danoeh.antennapod.asynctask.ImageLoader;
+
+import java.util.List;
+
+import de.danoeh.antennapod.asynctask.PicassoImageResource;
import de.danoeh.antennapod.feed.Chapter;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.feed.MediaType;
import de.danoeh.antennapod.storage.DBReader;
import de.danoeh.antennapod.util.ShownotesProvider;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.Validate;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.List;
/**
* Interface for objects that can be played by the PlaybackService.
*/
public interface Playable extends Parcelable,
- ImageLoader.ImageWorkerTaskResource, ShownotesProvider {
+ ShownotesProvider, PicassoImageResource {
/**
* Save information about the playable in a preference so that it can be
@@ -208,69 +204,4 @@ public interface Playable extends Parcelable,
}
}
-
- /**
- * Uses local file as image resource if it is available.
- */
- public static class DefaultPlayableImageLoader implements
- ImageLoader.ImageWorkerTaskResource {
- private Playable playable;
-
- public DefaultPlayableImageLoader(Playable playable) {
- Validate.notNull(playable);
-
- this.playable = playable;
- }
-
- @Override
- public InputStream openImageInputStream() {
- if (playable.localFileAvailable()
- && playable.getLocalMediaUrl() != null) {
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- try {
- mmr.setDataSource(playable.getLocalMediaUrl());
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- return null;
- }
- byte[] imgData = mmr.getEmbeddedPicture();
- if (imgData != null) {
- return new PublicByteArrayInputStream(imgData);
-
- }
- }
- return null;
- }
-
- @Override
- public String getImageLoaderCacheKey() {
- return playable.getLocalMediaUrl();
- }
-
- @Override
- public InputStream reopenImageInputStream(InputStream input) {
- if (input instanceof PublicByteArrayInputStream) {
- IOUtils.closeQuietly(input);
- byte[] imgData = ((PublicByteArrayInputStream) input)
- .getByteArray();
- if (imgData != null) {
- ByteArrayInputStream out = new ByteArrayInputStream(imgData);
- return out;
- }
-
- }
- return null;
- }
-
- private static class PublicByteArrayInputStream extends
- ByteArrayInputStream {
- public PublicByteArrayInputStream(byte[] buf) {
- super(buf);
- }
-
- public byte[] getByteArray() {
- return buf;
- }
- }
- }
}