From 56f199dc8c69d7e24d0e05613f9911c323cb46a6 Mon Sep 17 00:00:00 2001 From: daniel oeh Date: Sun, 24 Feb 2013 10:46:10 +0100 Subject: Added UserPreferences class, limit access to unreadItems and queue --- src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java | 3 ++- src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java | 1 - src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/de/danoeh/antennapod/asynctask') diff --git a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java index db9ae999c..5f26e900e 100644 --- a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java +++ b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java @@ -15,6 +15,7 @@ import de.danoeh.antennapod.PodcastApp; import de.danoeh.antennapod.R; import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.opml.OpmlWriter; +import de.danoeh.antennapod.preferences.UserPreferences; /** Writes an OPML file into the export directory in the background. */ public class OpmlExportWorker extends AsyncTask { @@ -40,7 +41,7 @@ public class OpmlExportWorker extends AsyncTask { OpmlWriter opmlWriter = new OpmlWriter(); if (output == null) { output = new File( - PodcastApp.getDataFolder(context, PodcastApp.EXPORT_DIR), + UserPreferences.getDataFolder(context, PodcastApp.EXPORT_DIR), DEFAULT_OUTPUT_NAME); if (output.exists()) { Log.w(TAG, "Overwriting previously exported file."); diff --git a/src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java b/src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java index a3652e05d..4d9c9867e 100644 --- a/src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java +++ b/src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java @@ -7,7 +7,6 @@ import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.OpmlImportFromPathActivity; import de.danoeh.antennapod.activity.OpmlImportHolder; import de.danoeh.antennapod.feed.Feed; import de.danoeh.antennapod.opml.OpmlElement; diff --git a/src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java b/src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java index 2c1d30bdb..5af06895f 100644 --- a/src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java +++ b/src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.asynctask; -import java.io.*; +import java.io.IOException; +import java.io.Reader; import java.util.ArrayList; import org.xmlpull.v1.XmlPullParserException; -- cgit v1.2.3 From f9e00f72a0dfeea3e5b9db8a522f7251e158dc7d Mon Sep 17 00:00:00 2001 From: daniel oeh Date: Sun, 24 Feb 2013 12:30:23 +0100 Subject: limited access to feed items, feeds, playback history and download log --- src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/de/danoeh/antennapod/asynctask') diff --git a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java index 5f26e900e..978f53ac6 100644 --- a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java +++ b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.asynctask; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.Arrays; import android.annotation.SuppressLint; import android.app.AlertDialog; @@ -50,7 +51,7 @@ public class OpmlExportWorker extends AsyncTask { } try { FileWriter writer = new FileWriter(output); - opmlWriter.writeDocument(FeedManager.getInstance().getFeeds(), + opmlWriter.writeDocument(Arrays.asList(FeedManager.getInstance().getFeedsArray()), writer); writer.close(); } catch (IOException e) { -- cgit v1.2.3 From 56db791e7d6c36d3f11a92422526f6ec8d516db2 Mon Sep 17 00:00:00 2001 From: daniel oeh Date: Mon, 25 Feb 2013 18:15:02 +0100 Subject: FeedImageLoader now works independently from FeedImages --- .../asynctask/BitmapDecodeWorkerTask.java | 31 +-- .../antennapod/asynctask/FeedImageLoader.java | 233 --------------------- .../danoeh/antennapod/asynctask/ImageLoader.java | 223 ++++++++++++++++++++ 3 files changed, 241 insertions(+), 246 deletions(-) delete mode 100644 src/de/danoeh/antennapod/asynctask/FeedImageLoader.java create mode 100644 src/de/danoeh/antennapod/asynctask/ImageLoader.java (limited to 'src/de/danoeh/antennapod/asynctask') diff --git a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java index c23c4c66a..810a17165 100644 --- a/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java +++ b/src/de/danoeh/antennapod/asynctask/BitmapDecodeWorkerTask.java @@ -11,10 +11,10 @@ import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.util.BitmapDecoder; -public abstract class BitmapDecodeWorkerTask extends Thread { +public class BitmapDecodeWorkerTask extends Thread { protected int PREFERRED_LENGTH; - + /** Can be thumbnail or cover */ protected int imageType; @@ -25,7 +25,7 @@ public abstract class BitmapDecodeWorkerTask extends Thread { protected String fileUrl; private Handler handler; - + private final int defaultCoverResource; public BitmapDecodeWorkerTask(Handler handler, ImageView target, @@ -36,7 +36,8 @@ public abstract class BitmapDecodeWorkerTask extends Thread { this.fileUrl = fileUrl; this.PREFERRED_LENGTH = length; this.imageType = imageType; - TypedArray res = target.getContext().obtainStyledAttributes(new int[] {R.attr.default_cover}); + TypedArray res = target.getContext().obtainStyledAttributes( + new int[] { R.attr.default_cover }); this.defaultCoverResource = res.getResourceId(0, 0); res.recycle(); } @@ -45,7 +46,9 @@ public abstract class BitmapDecodeWorkerTask extends Thread { * Should return true if tag of the imageview is still the same it was * before the bitmap was decoded */ - abstract protected boolean tagsMatching(ImageView target); + protected boolean tagsMatching(ImageView target) { + return target.getTag() == null || target.getTag() == fileUrl; + } protected void onPostExecute() { // check if imageview is still supposed to display this image @@ -64,13 +67,15 @@ public abstract class BitmapDecodeWorkerTask extends Thread { f = new File(fileUrl); } if (fileUrl != null && f.exists()) { - cBitmap = new CachedBitmap(BitmapDecoder.decodeBitmap(PREFERRED_LENGTH, fileUrl), PREFERRED_LENGTH); + 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); + cBitmap = new CachedBitmap(BitmapFactory.decodeResource( + target.getResources(), defaultCoverResource), + PREFERRED_LENGTH); } if (AppConfig.DEBUG) Log.d(TAG, "Finished loading bitmaps"); @@ -98,15 +103,15 @@ public abstract class BitmapDecodeWorkerTask extends Thread { protected void onInvalidFileUrl() { Log.e(TAG, "FeedImage has no valid file url. Using default image"); - cBitmap = new CachedBitmap(BitmapFactory.decodeResource(target.getResources(), - defaultCoverResource), PREFERRED_LENGTH); + cBitmap = new CachedBitmap(BitmapFactory.decodeResource( + target.getResources(), defaultCoverResource), PREFERRED_LENGTH); } protected void storeBitmapInCache(CachedBitmap cb) { - FeedImageLoader loader = FeedImageLoader.getInstance(); - if (imageType == FeedImageLoader.IMAGE_TYPE_COVER) { + ImageLoader loader = ImageLoader.getInstance(); + if (imageType == ImageLoader.IMAGE_TYPE_COVER) { loader.addBitmapToCoverCache(fileUrl, cb); - } else if (imageType == FeedImageLoader.IMAGE_TYPE_THUMBNAIL) { + } else if (imageType == ImageLoader.IMAGE_TYPE_THUMBNAIL) { loader.addBitmapToThumbnailCache(fileUrl, cb); } } diff --git a/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java b/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java deleted file mode 100644 index 5e1994adb..000000000 --- a/src/de/danoeh/antennapod/asynctask/FeedImageLoader.java +++ /dev/null @@ -1,233 +0,0 @@ -package de.danoeh.antennapod.asynctask; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; - -import android.annotation.SuppressLint; -import android.app.ActivityManager; -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Handler; -import android.support.v4.util.LruCache; -import android.util.Log; -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; -import de.danoeh.antennapod.feed.FeedManager; -import de.danoeh.antennapod.storage.DownloadRequester; - -/** Caches and loads FeedImage bitmaps in the background */ -public class FeedImageLoader { - private static final String TAG = "FeedImageLoader"; - private static FeedImageLoader singleton; - - public static final int IMAGE_TYPE_THUMBNAIL = 0; - public static final int IMAGE_TYPE_COVER = 1; - - 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 coverCache; - private LruCache thumbnailCache; - - private FeedImageLoader() { - handler = new Handler(); - executor = createExecutor(); - - coverCache = new LruCache(1); - - thumbnailCache = new LruCache(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() + 1, new ThreadFactory() { - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r); - t.setPriority(Thread.MIN_PRIORITY); - return t; - } - }); - } - - public static FeedImageLoader getInstance() { - if (singleton == null) { - singleton = new FeedImageLoader(); - } - 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(FeedImage image, ImageView target) { - loadCoverBitmap(image, 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(FeedImage image, ImageView target, int length) { - final int defaultCoverResource = getDefaultCoverResource(target.getContext()); - - if (image != null && image.getFile_url() != null) { - CachedBitmap cBitmap = getBitmapFromCoverCache(image.getFile_url()); - if (cBitmap != null && cBitmap.getLength() >= length) { - target.setImageBitmap(cBitmap.getBitmap()); - } else { - target.setImageResource(defaultCoverResource); - FeedImageDecodeWorkerTask worker = new FeedImageDecodeWorkerTask( - handler, target, image, length, IMAGE_TYPE_COVER); - executor.submit(worker); - } - } else { - target.setImageResource(defaultCoverResource); - } - } - - /** - * 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(FeedImage image, ImageView target) { - loadThumbnailBitmap(image, 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(FeedImage image, ImageView target, - int length) { - final int defaultCoverResource = getDefaultCoverResource(target.getContext()); - - if (image != null && image.getFile_url() != null) { - CachedBitmap cBitmap = getBitmapFromThumbnailCache(image.getFile_url()); - if (cBitmap != null && cBitmap.getLength() >= length) { - target.setImageBitmap(cBitmap.getBitmap()); - } else { - target.setImageResource(defaultCoverResource); - FeedImageDecodeWorkerTask worker = new FeedImageDecodeWorkerTask( - handler, target, image, length, IMAGE_TYPE_THUMBNAIL); - executor.submit(worker); - } - } else { - target.setImageResource(defaultCoverResource); - } - } - - public void clearExecutorQueue() { - executor.shutdownNow(); - if (AppConfig.DEBUG) - Log.d(TAG, "Executor was shut down."); - executor = createExecutor(); - - } - - public void wipeImageCache() { - coverCache.evictAll(); - thumbnailCache.evictAll(); - } - - public boolean isInThumbnailCache(FeedImage image) { - return thumbnailCache.get(image.getFile_url()) != null; - } - - private CachedBitmap getBitmapFromThumbnailCache(String key) { - return thumbnailCache.get(key); - } - - public void addBitmapToThumbnailCache(String key, CachedBitmap bitmap) { - thumbnailCache.put(key, bitmap); - } - - public boolean isInCoverCache(FeedImage image) { - return coverCache.get(image.getFile_url()) != 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) { - TypedArray res = context.obtainStyledAttributes(new int[] {R.attr.default_cover}); - final int defaultCoverResource = res.getResourceId(0, 0); - res.recycle(); - return defaultCoverResource; - } - - class FeedImageDecodeWorkerTask extends BitmapDecodeWorkerTask { - - private static final String TAG = "FeedImageDecodeWorkerTask"; - - protected FeedImage image; - - public FeedImageDecodeWorkerTask(Handler handler, ImageView target, - FeedImage image, int length, int imageType) { - super(handler, target, image.getFile_url(), length, imageType); - this.image = image; - } - - @Override - protected boolean tagsMatching(ImageView target) { - return target.getTag() == null || target.getTag() == image; - } - - @Override - protected void onInvalidFileUrl() { - super.onInvalidFileUrl(); - if (image.getFile_url() != null - && !DownloadRequester.getInstance() - .isDownloadingFile(image)) { - FeedManager.getInstance().notifyInvalidImageFile( - PodcastApp.getInstance(), image); - } - - } - - } - -} diff --git a/src/de/danoeh/antennapod/asynctask/ImageLoader.java b/src/de/danoeh/antennapod/asynctask/ImageLoader.java new file mode 100644 index 000000000..d0f20d621 --- /dev/null +++ b/src/de/danoeh/antennapod/asynctask/ImageLoader.java @@ -0,0 +1,223 @@ +package de.danoeh.antennapod.asynctask; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +import android.annotation.SuppressLint; +import android.app.ActivityManager; +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Handler; +import android.support.v4.util.LruCache; +import android.util.Log; +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 { + 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; + + 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 coverCache; + private LruCache thumbnailCache; + + private ImageLoader() { + handler = new Handler(); + executor = createExecutor(); + + coverCache = new LruCache(1); + + thumbnailCache = new LruCache(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() + 1, new ThreadFactory() { + + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setPriority(Thread.MIN_PRIORITY); + return t; + } + }); + } + + public static 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(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); + } + + /** + * 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(String fileUrl, ImageView target, int length) { + final int defaultCoverResource = getDefaultCoverResource(target + .getContext()); + + if (fileUrl != null) { + CachedBitmap cBitmap = getBitmapFromCoverCache(fileUrl); + 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); + executor.submit(worker); + } + } else { + target.setImageResource(defaultCoverResource); + } + } + + /** + * 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(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); + } + + /** + * 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(String fileUrl, ImageView target, int length) { + final int defaultCoverResource = getDefaultCoverResource(target + .getContext()); + + if (fileUrl != null) { + CachedBitmap cBitmap = getBitmapFromThumbnailCache(fileUrl); + 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); + executor.submit(worker); + } + } else { + target.setImageResource(defaultCoverResource); + } + } + + public void clearExecutorQueue() { + executor.shutdownNow(); + if (AppConfig.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) { + TypedArray res = context + .obtainStyledAttributes(new int[] { R.attr.default_cover }); + final int defaultCoverResource = res.getResourceId(0, 0); + res.recycle(); + return defaultCoverResource; + } + +} -- cgit v1.2.3