diff options
27 files changed, 311 insertions, 179 deletions
diff --git a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java index adabb3bdb..2809d638f 100644 --- a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java +++ b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java @@ -1,7 +1,5 @@ package de.danoeh.antennapod.activity; -import java.io.File; - import android.content.Intent; import android.content.res.TypedArray; import android.os.Bundle; @@ -214,7 +212,7 @@ public class AudioplayerActivity extends MediaplayerActivity { @Override public void run() { ImageLoader.getInstance().loadThumbnailBitmap( - media.getImageFileUrl(), butNavLeft); + media, butNavLeft); } }); butNavRight.setImageDrawable(drawables.getDrawable(1)); @@ -226,7 +224,7 @@ public class AudioplayerActivity extends MediaplayerActivity { @Override public void run() { ImageLoader.getInstance().loadThumbnailBitmap( - media.getImageFileUrl(), butNavLeft); + media, butNavLeft); } }); butNavRight.setImageDrawable(drawables.getDrawable(0)); diff --git a/src/de/danoeh/antennapod/activity/MainActivity.java b/src/de/danoeh/antennapod/activity/MainActivity.java index 2bca3ac6b..410617b23 100644 --- a/src/de/danoeh/antennapod/activity/MainActivity.java +++ b/src/de/danoeh/antennapod/activity/MainActivity.java @@ -4,26 +4,20 @@ import java.util.ArrayList; import android.content.Context; import android.content.Intent; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; -import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import android.util.Log; -import android.view.View; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.ActionBar.Tab; -import com.actionbarsherlock.app.ActionBar.TabListener; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.Window; -import com.viewpagerindicator.TabPageIndicator; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; diff --git a/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java b/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java index 50780844d..65225a584 100644 --- a/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java +++ b/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java @@ -155,10 +155,9 @@ public class OrganizeQueueActivity extends SherlockListActivity { holder.title.setText(item.getTitle()); holder.feedTitle.setText(item.getFeed().getTitle()); - holder.feedImage.setTag((item.getFeed().getImage() != null) ? item - .getFeed().getImage().getFile_url() : null); + holder.feedImage.setTag(item.getImageLoaderCacheKey()); ImageLoader.getInstance().loadThumbnailBitmap( - item.getFeed().getImage(), + item, holder.feedImage, (int) convertView.getResources().getDimension( R.dimen.thumbnail_length)); diff --git a/src/de/danoeh/antennapod/activity/PreferenceActivity.java b/src/de/danoeh/antennapod/activity/PreferenceActivity.java index 6bad316a6..8b3f2539a 100644 --- a/src/de/danoeh/antennapod/activity/PreferenceActivity.java +++ b/src/de/danoeh/antennapod/activity/PreferenceActivity.java @@ -7,7 +7,6 @@ import java.util.List; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.content.res.Resources.Theme; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; diff --git a/src/de/danoeh/antennapod/adapter/DefaultFeedItemlistAdapter.java b/src/de/danoeh/antennapod/adapter/DefaultFeedItemlistAdapter.java index 5e8dca005..b603bb54f 100644 --- a/src/de/danoeh/antennapod/adapter/DefaultFeedItemlistAdapter.java +++ b/src/de/danoeh/antennapod/adapter/DefaultFeedItemlistAdapter.java @@ -8,20 +8,14 @@ import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.View.OnClickListener; import android.widget.Adapter; 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.adapter.InternalFeedItemlistAdapter.Holder; import de.danoeh.antennapod.feed.FeedItem; -import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.feed.MediaType; -import de.danoeh.antennapod.storage.DownloadRequester; import de.danoeh.antennapod.util.Converter; -import de.danoeh.antennapod.util.ThemeUtils; public class DefaultFeedItemlistAdapter extends BaseAdapter { diff --git a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java index 5005b25b4..0e5ef2435 100644 --- a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java +++ b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java @@ -166,11 +166,10 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter { holder.downloadStatus.setVisibility(View.INVISIBLE); holder.lenSize.setVisibility(View.INVISIBLE); } - - holder.feedImage.setTag((item.getFeed().getImage() != null) ? item - .getFeed().getImage().getFile_url() : null); + + holder.feedImage.setTag(item.getImageLoaderCacheKey()); ImageLoader.getInstance().loadThumbnailBitmap( - item.getFeed().getImage(), + item, holder.feedImage, (int) convertView.getResources().getDimension( R.dimen.thumbnail_length)); diff --git a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java index 810a17165..4380bc6ea 100644 --- a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java +++ b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java @@ -1,7 +1,5 @@ package de.danoeh.antennapod.asynctask; -import java.io.File; - import android.content.res.TypedArray; import android.graphics.BitmapFactory; import android.os.Handler; @@ -9,6 +7,7 @@ import android.util.Log; import android.widget.ImageView; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; +import de.danoeh.antennapod.asynctask.ImageLoader.ImageWorkerTaskResource; import de.danoeh.antennapod.util.BitmapDecoder; public class BitmapDecodeWorkerTask extends Thread { @@ -22,18 +21,18 @@ public class BitmapDecodeWorkerTask extends Thread { private ImageView target; protected CachedBitmap cBitmap; - protected String fileUrl; + protected ImageLoader.ImageWorkerTaskResource imageResource; private Handler handler; private final int defaultCoverResource; public BitmapDecodeWorkerTask(Handler handler, ImageView target, - String fileUrl, int length, int imageType) { + ImageWorkerTaskResource imageResource, int length, int imageType) { super(); this.handler = handler; this.target = target; - this.fileUrl = fileUrl; + this.imageResource = imageResource; this.PREFERRED_LENGTH = length; this.imageType = imageType; TypedArray res = target.getContext().obtainStyledAttributes( @@ -47,7 +46,8 @@ public class BitmapDecodeWorkerTask extends Thread { * before the bitmap was decoded */ protected boolean tagsMatching(ImageView target) { - return target.getTag() == null || target.getTag() == fileUrl; + return target.getTag() == null + || target.getTag() == imageResource.getImageLoaderCacheKey(); } protected void onPostExecute() { @@ -62,31 +62,19 @@ public class BitmapDecodeWorkerTask extends Thread { @Override public void run() { - File f = null; - if (fileUrl != null) { - f = new File(fileUrl); - } - if (fileUrl != null && f.exists()) { - cBitmap = new CachedBitmap(BitmapDecoder.decodeBitmap( - PREFERRED_LENGTH, fileUrl), 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 (AppConfig.DEBUG) - Log.d(TAG, "Finished loading bitmaps"); + cBitmap = new CachedBitmap(BitmapDecoder.decodeBitmapFromWorkerTaskResource( + PREFERRED_LENGTH, imageResource), PREFERRED_LENGTH); + if (cBitmap.getBitmap() != null) { + storeBitmapInCache(cBitmap); } else { - if (fileUrl == null) { - Log.w(TAG, "File URL is null"); - } else { - Log.w(TAG, "File does not exist anymore."); - } - onInvalidFileUrl(); + Log.w(TAG, "Could not load bitmap. Using default image."); + cBitmap = new CachedBitmap(BitmapFactory.decodeResource( + target.getResources(), defaultCoverResource), + PREFERRED_LENGTH); } + if (AppConfig.DEBUG) + Log.d(TAG, "Finished loading bitmaps"); + endBackgroundTask(); } @@ -101,8 +89,7 @@ public class BitmapDecodeWorkerTask extends Thread { }); } - protected void onInvalidFileUrl() { - Log.e(TAG, "FeedImage has no valid file url. Using default image"); + protected void onInvalidStream() { cBitmap = new CachedBitmap(BitmapFactory.decodeResource( target.getResources(), defaultCoverResource), PREFERRED_LENGTH); } @@ -110,9 +97,10 @@ public class BitmapDecodeWorkerTask extends Thread { protected void storeBitmapInCache(CachedBitmap cb) { ImageLoader loader = ImageLoader.getInstance(); if (imageType == ImageLoader.IMAGE_TYPE_COVER) { - loader.addBitmapToCoverCache(fileUrl, cb); + loader.addBitmapToCoverCache(imageResource.getImageLoaderCacheKey(), cb); } else if (imageType == ImageLoader.IMAGE_TYPE_THUMBNAIL) { - loader.addBitmapToThumbnailCache(fileUrl, cb); + loader.addBitmapToThumbnailCache(imageResource.getImageLoaderCacheKey(), cb); } } + } diff --git a/src/de/danoeh/antennapod/asynctask/ImageLoader.java b/src/de/danoeh/antennapod/asynctask/ImageLoader.java index d0f20d621..fb807f469 100644 --- a/src/de/danoeh/antennapod/asynctask/ImageLoader.java +++ b/src/de/danoeh/antennapod/asynctask/ImageLoader.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.asynctask; +import java.io.InputStream; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -15,7 +16,6 @@ import android.widget.ImageView; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.PodcastApp; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.feed.FeedImage; /** Caches and loads FeedImage bitmaps in the background */ public class ImageLoader { @@ -90,18 +90,8 @@ public class ImageLoader { * ImageView's size has already been set or inside a Runnable which is * posted to the ImageView's message queue. */ - public void loadCoverBitmap(String fileUrl, ImageView target) { - loadCoverBitmap(fileUrl, target, target.getHeight()); - } - - public void loadCoverBitmap(FeedImage image, ImageView target) { - loadCoverBitmap((image != null) ? image.getFile_url() : null, target, - target.getHeight()); - } - - public void loadCoverBitmap(FeedImage image, ImageView target, int length) { - loadCoverBitmap((image != null) ? image.getFile_url() : null, target, - length); + public void loadCoverBitmap(ImageWorkerTaskResource source, ImageView target) { + loadCoverBitmap(source, target, target.getHeight()); } /** @@ -110,18 +100,19 @@ public class ImageLoader { * ImageView's size has already been set or inside a Runnable which is * posted to the ImageView's message queue. */ - public void loadCoverBitmap(String fileUrl, ImageView target, int length) { + public void loadCoverBitmap(ImageWorkerTaskResource source, + ImageView target, int length) { final int defaultCoverResource = getDefaultCoverResource(target .getContext()); - if (fileUrl != null) { - CachedBitmap cBitmap = getBitmapFromCoverCache(fileUrl); + if (source != null && source.getImageLoaderCacheKey() != null) { + CachedBitmap cBitmap = getBitmapFromCoverCache(source.getImageLoaderCacheKey()); if (cBitmap != null && cBitmap.getLength() >= length) { target.setImageBitmap(cBitmap.getBitmap()); } else { target.setImageResource(defaultCoverResource); BitmapDecodeWorkerTask worker = new BitmapDecodeWorkerTask( - handler, target, fileUrl, length, IMAGE_TYPE_COVER); + handler, target, source, length, IMAGE_TYPE_COVER); executor.submit(worker); } } else { @@ -135,19 +126,9 @@ public class ImageLoader { * 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(String fileUrl, ImageView target) { - loadThumbnailBitmap(fileUrl, target, target.getHeight()); - } - - public void loadThumbnailBitmap(FeedImage image, ImageView target) { - loadThumbnailBitmap((image != null) ? image.getFile_url() : null, - target, target.getHeight()); - } - - public void loadThumbnailBitmap(FeedImage image, ImageView target, - int length) { - loadThumbnailBitmap((image != null) ? image.getFile_url() : null, - target, length); + public void loadThumbnailBitmap(ImageWorkerTaskResource source, + ImageView target) { + loadThumbnailBitmap(source, target, target.getHeight()); } /** @@ -156,18 +137,19 @@ public class ImageLoader { * 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(String fileUrl, ImageView target, int length) { + public void loadThumbnailBitmap(ImageWorkerTaskResource source, + ImageView target, int length) { final int defaultCoverResource = getDefaultCoverResource(target .getContext()); - if (fileUrl != null) { - CachedBitmap cBitmap = getBitmapFromThumbnailCache(fileUrl); + if (source != null && source.getImageLoaderCacheKey() != null) { + CachedBitmap cBitmap = getBitmapFromThumbnailCache(source.getImageLoaderCacheKey()); if (cBitmap != null && cBitmap.getLength() >= length) { target.setImageBitmap(cBitmap.getBitmap()); } else { target.setImageResource(defaultCoverResource); BitmapDecodeWorkerTask worker = new BitmapDecodeWorkerTask( - handler, target, fileUrl, length, IMAGE_TYPE_THUMBNAIL); + handler, target, source, length, IMAGE_TYPE_THUMBNAIL); executor.submit(worker); } } else { @@ -220,4 +202,31 @@ public class ImageLoader { return defaultCoverResource; } + /** + * 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/feed/FeedImage.java b/src/de/danoeh/antennapod/feed/FeedImage.java index 8e3824560..09595f5eb 100644 --- a/src/de/danoeh/antennapod/feed/FeedImage.java +++ b/src/de/danoeh/antennapod/feed/FeedImage.java @@ -1,6 +1,18 @@ package de.danoeh.antennapod.feed; -public class FeedImage extends FeedFile { +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; + +import de.danoeh.antennapod.asynctask.ImageLoader; + +; + +public class FeedImage extends FeedFile implements + ImageLoader.ImageWorkerTaskResource { public static final int FEEDFILETYPE_FEEDIMAGE = 1; protected String title; @@ -53,4 +65,30 @@ public class FeedImage extends FeedFile { this.feed = feed; } + @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(); + } + } diff --git a/src/de/danoeh/antennapod/feed/FeedItem.java b/src/de/danoeh/antennapod/feed/FeedItem.java index 87cea0a1e..0df384b60 100644 --- a/src/de/danoeh/antennapod/feed/FeedItem.java +++ b/src/de/danoeh/antennapod/feed/FeedItem.java @@ -1,10 +1,11 @@ package de.danoeh.antennapod.feed; +import java.io.InputStream; import java.lang.ref.SoftReference; import java.util.Date; import java.util.List; -import de.danoeh.antennapod.preferences.PlaybackPreferences; +import de.danoeh.antennapod.asynctask.ImageLoader; /** * Data Object for a XML message @@ -12,7 +13,8 @@ import de.danoeh.antennapod.preferences.PlaybackPreferences; * @author daniel * */ -public class FeedItem extends FeedComponent { +public class FeedItem extends FeedComponent implements + ImageLoader.ImageWorkerTaskResource { /** The id/guid that can be found in the rss/atom feed. Might not be set. */ private String itemIdentifier; @@ -241,4 +243,40 @@ public class FeedItem extends FeedComponent { } return (isRead() ? State.READ : State.NEW); } + + @Override + public InputStream openImageInputStream() { + InputStream out = null; + if (hasMedia()) { + out = media.openImageInputStream(); + } + if (out == null && feed.getImage() != null) { + out = feed.getImage().openImageInputStream(); + } + return out; + } + + @Override + public InputStream reopenImageInputStream(InputStream input) { + InputStream out = null; + if (hasMedia()) { + out = media.reopenImageInputStream(input); + } + if (out == null && feed.getImage() != null) { + out = feed.getImage().reopenImageInputStream(input); + } + return out; + } + + @Override + public String getImageLoaderCacheKey() { + String out = null; + if (hasMedia()) { + out = media.getImageLoaderCacheKey(); + } + if (out == null && feed.getImage() != null) { + out = feed.getImage().getImageLoaderCacheKey(); + } + return out; + } } diff --git a/src/de/danoeh/antennapod/feed/FeedMedia.java b/src/de/danoeh/antennapod/feed/FeedMedia.java index fd3d2ebb0..4096c6cca 100644 --- a/src/de/danoeh/antennapod/feed/FeedMedia.java +++ b/src/de/danoeh/antennapod/feed/FeedMedia.java @@ -1,5 +1,7 @@ package de.danoeh.antennapod.feed; +import java.io.FileInputStream; +import java.io.InputStream; import java.util.Date; import java.util.List; @@ -226,15 +228,6 @@ public class FeedMedia extends FeedFile implements Playable { } @Override - public String getImageFileUrl() { - if (getItem().getFeed().getImage() != null) { - return getItem().getFeed().getImage().getFile_url(); - } else { - return null; - } - } - - @Override public Object getIdentifier() { return id; } @@ -329,4 +322,37 @@ public class FeedMedia extends FeedFile implements Playable { return new FeedMedia[size]; } }; + + @Override + public InputStream openImageInputStream() { + InputStream 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 = 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) { + 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 c477ea2b8..6be76f515 100644 --- a/src/de/danoeh/antennapod/fragment/CoverFragment.java +++ b/src/de/danoeh/antennapod/fragment/CoverFragment.java @@ -65,7 +65,7 @@ public class CoverFragment extends SherlockFragment implements @Override public void run() { ImageLoader.getInstance().loadCoverBitmap( - media.getImageFileUrl(), imgvCover); + media, imgvCover); } }); } else { diff --git a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java index 1b7d77193..a50e820b6 100644 --- a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java +++ b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java @@ -209,7 +209,7 @@ public class ExternalPlayerFragment extends SherlockFragment { if (media != null) { txtvTitle.setText(media.getEpisodeTitle()); ImageLoader.getInstance().loadThumbnailBitmap( - media.getImageFileUrl(), + media, imgvCover, (int) getActivity().getResources().getDimension( R.dimen.external_player_height)); diff --git a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java index 484a1f9f6..6265694f6 100644 --- a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -17,8 +17,8 @@ import com.actionbarsherlock.app.SherlockListFragment; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.ItemviewActivity; -import de.danoeh.antennapod.adapter.DefaultFeedItemlistAdapter; import de.danoeh.antennapod.adapter.ActionButtonCallback; +import de.danoeh.antennapod.adapter.DefaultFeedItemlistAdapter; import de.danoeh.antennapod.adapter.InternalFeedItemlistAdapter; import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.feed.EventDistributor; diff --git a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index 637b6121b..b471d5303 100644 --- a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -4,7 +4,6 @@ import android.os.Bundle; import android.util.Log; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.adapter.DefaultFeedItemlistAdapter; -import de.danoeh.antennapod.adapter.InternalFeedItemlistAdapter; import de.danoeh.antennapod.feed.EventDistributor; import de.danoeh.antennapod.feed.FeedItem; import de.danoeh.antennapod.feed.FeedManager; diff --git a/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java b/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java index c6a431541..9ae0f8f2f 100644 --- a/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java +++ b/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java @@ -5,8 +5,6 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.util.Log; import de.danoeh.antennapod.AppConfig; -import de.danoeh.antennapod.feed.FeedManager; -import de.danoeh.antennapod.feed.FeedMedia; /** * Provides access to preferences set by the playback service. A private diff --git a/src/de/danoeh/antennapod/preferences/UserPreferences.java b/src/de/danoeh/antennapod/preferences/UserPreferences.java index 5b7c9d84f..489f9f02d 100644 --- a/src/de/danoeh/antennapod/preferences/UserPreferences.java +++ b/src/de/danoeh/antennapod/preferences/UserPreferences.java @@ -2,7 +2,6 @@ package de.danoeh.antennapod.preferences; import java.io.File; import java.io.IOException; -import java.util.Set; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.StringUtils; diff --git a/src/de/danoeh/antennapod/receiver/AlarmUpdateReceiver.java b/src/de/danoeh/antennapod/receiver/AlarmUpdateReceiver.java index 05914a0e1..63a03b9e6 100644 --- a/src/de/danoeh/antennapod/receiver/AlarmUpdateReceiver.java +++ b/src/de/danoeh/antennapod/receiver/AlarmUpdateReceiver.java @@ -1,11 +1,11 @@ package de.danoeh.antennapod.receiver; -import de.danoeh.antennapod.AppConfig; -import de.danoeh.antennapod.preferences.UserPreferences; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; +import de.danoeh.antennapod.AppConfig; +import de.danoeh.antennapod.preferences.UserPreferences; /** Listens for events that make it necessary to reset the update alarm. */ public class AlarmUpdateReceiver extends BroadcastReceiver { diff --git a/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java b/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java index 5c898384a..b58527130 100644 --- a/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java +++ b/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java @@ -1,15 +1,15 @@ package de.danoeh.antennapod.receiver; -import de.danoeh.antennapod.AppConfig; -import de.danoeh.antennapod.feed.FeedManager; -import de.danoeh.antennapod.storage.DownloadRequester; -import de.danoeh.antennapod.util.NetworkUtils; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.util.Log; +import de.danoeh.antennapod.AppConfig; +import de.danoeh.antennapod.feed.FeedManager; +import de.danoeh.antennapod.storage.DownloadRequester; +import de.danoeh.antennapod.util.NetworkUtils; public class ConnectivityActionReceiver extends BroadcastReceiver { private static final String TAG = "ConnectivityActionReceiver"; diff --git a/src/de/danoeh/antennapod/service/PlaybackService.java b/src/de/danoeh/antennapod/service/PlaybackService.java index 811b02535..8ff115077 100644 --- a/src/de/danoeh/antennapod/service/PlaybackService.java +++ b/src/de/danoeh/antennapod/service/PlaybackService.java @@ -41,7 +41,6 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.AudioplayerActivity; import de.danoeh.antennapod.activity.VideoplayerActivity; import de.danoeh.antennapod.feed.Chapter; -import de.danoeh.antennapod.feed.Feed; import de.danoeh.antennapod.feed.FeedComponent; import de.danoeh.antennapod.feed.FeedItem; import de.danoeh.antennapod.feed.FeedManager; @@ -730,8 +729,7 @@ public class PlaybackService extends Service { prepareImmediately = startWhenPrepared = true; } else { if (AppConfig.DEBUG) - Log.d(TAG, - "No more episodes available to play"); + Log.d(TAG, "No more episodes available to play"); media = null; prepareImmediately = startWhenPrepared = false; stopForeground(true); @@ -752,7 +750,8 @@ public class PlaybackService extends Service { if (media != null) { resetVideoSurface(); refreshRemoteControlClientState(); - sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, notificationCode); + sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, + notificationCode); } else { sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0); stopSelf(); @@ -958,12 +957,12 @@ public class PlaybackService extends Service { Bitmap icon = null; if (android.os.Build.VERSION.SDK_INT >= 11) { - if (media != null && media.getImageFileUrl() != null) { + if (media != null && media != null) { int iconSize = getResources().getDimensionPixelSize( android.R.dimen.notification_large_icon_width); - icon = BitmapDecoder.decodeBitmap(iconSize, - media.getImageFileUrl()); + icon = BitmapDecoder.decodeBitmapFromWorkerTaskResource(iconSize, media); } + } if (icon == null) { icon = BitmapFactory.decodeResource(getResources(), diff --git a/src/de/danoeh/antennapod/service/download/APRedirectHandler.java b/src/de/danoeh/antennapod/service/download/APRedirectHandler.java index 9416ef9d7..8a31c9390 100644 --- a/src/de/danoeh/antennapod/service/download/APRedirectHandler.java +++ b/src/de/danoeh/antennapod/service/download/APRedirectHandler.java @@ -7,8 +7,8 @@ import org.apache.http.HttpResponse; import org.apache.http.impl.client.DefaultRedirectHandler; import org.apache.http.protocol.HttpContext; -import de.danoeh.antennapod.AppConfig; import android.util.Log; +import de.danoeh.antennapod.AppConfig; public class APRedirectHandler extends DefaultRedirectHandler { // Identifier for logger diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java index 272b1bf59..e1230e170 100644 --- a/src/de/danoeh/antennapod/service/download/DownloadService.java +++ b/src/de/danoeh/antennapod/service/download/DownloadService.java @@ -58,7 +58,6 @@ import de.danoeh.antennapod.feed.FeedImage; import de.danoeh.antennapod.feed.FeedItem; import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.feed.FeedMedia; -import de.danoeh.antennapod.preferences.UserPreferences; import de.danoeh.antennapod.storage.DownloadRequestException; import de.danoeh.antennapod.storage.DownloadRequester; import de.danoeh.antennapod.syndication.handler.FeedHandler; diff --git a/src/de/danoeh/antennapod/service/download/HttpDownloader.java b/src/de/danoeh/antennapod/service/download/HttpDownloader.java index 07998be0b..f8f26f6fd 100644 --- a/src/de/danoeh/antennapod/service/download/HttpDownloader.java +++ b/src/de/danoeh/antennapod/service/download/HttpDownloader.java @@ -27,7 +27,6 @@ import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.PodcastApp; import de.danoeh.antennapod.R; import de.danoeh.antennapod.asynctask.DownloadStatus; -import de.danoeh.antennapod.service.download.APRedirectHandler; import de.danoeh.antennapod.util.DownloadError; import de.danoeh.antennapod.util.StorageUtils; diff --git a/src/de/danoeh/antennapod/util/BitmapDecoder.java b/src/de/danoeh/antennapod/util/BitmapDecoder.java index e9ef2ad01..e9423c3f7 100644 --- a/src/de/danoeh/antennapod/util/BitmapDecoder.java +++ b/src/de/danoeh/antennapod/util/BitmapDecoder.java @@ -1,11 +1,15 @@ package de.danoeh.antennapod.util; -import java.io.File; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Rect; import android.util.Log; import de.danoeh.antennapod.AppConfig; +import de.danoeh.antennapod.asynctask.ImageLoader; public class BitmapDecoder { private static final String TAG = "BitmapDecoder"; @@ -18,11 +22,13 @@ public class BitmapDecoder { return sampleSize; } - public static Bitmap decodeBitmap(int preferredLength, String fileUrl) { - if (fileUrl != null && new File(fileUrl).exists()) { + 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.decodeFile(fileUrl, options); + BitmapFactory.decodeStream(input, new Rect(), options); int srcWidth = options.outWidth; int srcHeight = options.outHeight; int length = Math.max(srcWidth, srcHeight); @@ -32,17 +38,14 @@ public class BitmapDecoder { options.inJustDecodeBounds = false; options.inSampleSize = sampleSize; options.inPreferredConfig = Bitmap.Config.ARGB_8888; - - Bitmap decodedBitmap = BitmapFactory.decodeFile(fileUrl, options); + Bitmap decodedBitmap = BitmapFactory.decodeStream(source.reopenImageInputStream(input), + null, options); if (decodedBitmap == null) { - Log.i(TAG, - "Bitmap could not be decoded in custom sample size. Trying default sample size (path was " - + fileUrl + ")"); - decodedBitmap = BitmapFactory.decodeFile(fileUrl); + decodedBitmap = BitmapFactory.decodeStream(source.reopenImageInputStream(input)); } + IOUtils.closeQuietly(input); return decodedBitmap; - } else { - return null; } + return null; } } diff --git a/src/de/danoeh/antennapod/util/NetworkUtils.java b/src/de/danoeh/antennapod/util/NetworkUtils.java index 6064f3f91..de7b854cc 100644 --- a/src/de/danoeh/antennapod/util/NetworkUtils.java +++ b/src/de/danoeh/antennapod/util/NetworkUtils.java @@ -3,14 +3,14 @@ package de.danoeh.antennapod.util; import java.util.Arrays; import java.util.List; -import de.danoeh.antennapod.AppConfig; -import de.danoeh.antennapod.preferences.UserPreferences; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.util.Log; +import de.danoeh.antennapod.AppConfig; +import de.danoeh.antennapod.preferences.UserPreferences; public class NetworkUtils { private static final String TAG = "NetworkUtils"; diff --git a/src/de/danoeh/antennapod/util/playback/ExternalMedia.java b/src/de/danoeh/antennapod/util/playback/ExternalMedia.java index 4574f088e..46f3dfcd8 100644 --- a/src/de/danoeh/antennapod/util/playback/ExternalMedia.java +++ b/src/de/danoeh/antennapod/util/playback/ExternalMedia.java @@ -1,24 +1,16 @@ package de.danoeh.antennapod.util.playback; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; +import java.io.InputStream; import java.util.List; -import org.apache.commons.io.IOUtils; - import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.media.MediaMetadataRetriever; import android.os.Parcel; import android.os.Parcelable; -import de.danoeh.antennapod.PodcastApp; import de.danoeh.antennapod.feed.Chapter; import de.danoeh.antennapod.feed.MediaType; import de.danoeh.antennapod.util.ChapterUtils; -import de.danoeh.antennapod.util.FileNameGenerator; /** Represents a media file that is stored on the local storage device. */ public class ExternalMedia implements Playable { @@ -35,7 +27,6 @@ public class ExternalMedia implements Playable { private String shownotes; private MediaType mediaType = MediaType.AUDIO; private List<Chapter> chapters; - private String imageUrl; private int duration; private int position; @@ -71,12 +62,15 @@ public class ExternalMedia implements Playable { @Override public void loadMetadata() throws PlayableException { + final String tmpFileName = "tmpExternalMediaimage"; + MediaMetadataRetriever mmr = new MediaMetadataRetriever(); try { - mmr.setDataSource(source); + mmr.setDataSource(source); } catch (IllegalArgumentException e) { e.printStackTrace(); - throw new PlayableException("IllegalArgumentException when setting up MediaMetadataReceiver"); + throw new PlayableException( + "IllegalArgumentException when setting up MediaMetadataReceiver"); } episodeTitle = mmr .extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE); @@ -85,24 +79,6 @@ public class ExternalMedia implements Playable { duration = Integer.parseInt(mmr .extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)); ChapterUtils.loadChaptersFromFileUrl(this); - byte[] imgData = mmr.getEmbeddedPicture(); - File cacheDir = PodcastApp.getInstance().getExternalCacheDir(); - if (cacheDir != null) { - OutputStream out = null; - try { - File tmpFile = File.createTempFile( - FileNameGenerator.generateFileName(source) + "-img", - null, cacheDir); - out = new BufferedOutputStream(new FileOutputStream(tmpFile)); - IOUtils.write(imgData, out); - imageUrl = tmpFile.getAbsolutePath(); - } catch (IOException e) { - e.printStackTrace(); - throw new PlayableException("IOException during loadMetadata()"); - } finally { - IOUtils.closeQuietly(out); - } - } } @Override @@ -136,11 +112,6 @@ public class ExternalMedia implements Playable { } @Override - public String getImageFileUrl() { - return imageUrl; - } - - @Override public Object getIdentifier() { return source; } @@ -235,4 +206,20 @@ 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); + } + } diff --git a/src/de/danoeh/antennapod/util/playback/Playable.java b/src/de/danoeh/antennapod/util/playback/Playable.java index bf38b9518..ae87d5903 100644 --- a/src/de/danoeh/antennapod/util/playback/Playable.java +++ b/src/de/danoeh/antennapod/util/playback/Playable.java @@ -1,10 +1,16 @@ package de.danoeh.antennapod.util.playback; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.util.List; +import org.apache.commons.io.IOUtils; + import android.content.SharedPreferences; +import android.media.MediaMetadataRetriever; import android.os.Parcelable; import android.util.Log; +import de.danoeh.antennapod.asynctask.ImageLoader; import de.danoeh.antennapod.feed.Chapter; import de.danoeh.antennapod.feed.Feed; import de.danoeh.antennapod.feed.FeedManager; @@ -12,7 +18,8 @@ import de.danoeh.antennapod.feed.FeedMedia; import de.danoeh.antennapod.feed.MediaType; /** Interface for objects that can be played by the PlaybackService. */ -public interface Playable extends Parcelable { +public interface Playable extends Parcelable, + ImageLoader.ImageWorkerTaskResource { /** * Save information about the playable in a preference so that it can be @@ -52,9 +59,6 @@ public interface Playable extends Parcelable { /** Returns the title of the feed this Playable belongs to. */ public String getFeedTitle(); - /** Returns a file url to an image or null if no such image exists. */ - public String getImageFileUrl(); - /** * Returns a unique identifier, for example a file url or an ID from a * database. @@ -194,4 +198,67 @@ public interface Playable extends Parcelable { public static interface ShownoteLoaderCallback { void onShownotesLoaded(String shownotes); } + + /** Uses local file as image resource if it is available. */ + public static class DefaultPlayableImageLoader implements + ImageLoader.ImageWorkerTaskResource { + private Playable playable; + + public DefaultPlayableImageLoader(Playable playable) { + if (playable == null) { + throw new IllegalArgumentException("Playable must not be null"); + } + 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; + } + } + } } |