Added support for episode images
This commit is contained in:
parent
d0bfd7c02d
commit
60f7dd332d
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -225,15 +227,6 @@ public class FeedMedia extends FeedFile implements Playable {
|
|||
return getItem().getFeed().getTitle();
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public class CoverFragment extends SherlockFragment implements
|
|||
@Override
|
||||
public void run() {
|
||||
ImageLoader.getInstance().loadCoverBitmap(
|
||||
media.getImageFileUrl(), imgvCover);
|
||||
media, imgvCover);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
@ -135,11 +111,6 @@ public class ExternalMedia implements Playable {
|
|||
return feedTitle;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue