summaryrefslogtreecommitdiff
path: root/src/de/danoeh/antennapod/service/download/DownloadService.java
diff options
context:
space:
mode:
authordaniel oeh <daniel.oeh@gmail.com>2012-08-16 15:09:49 +0200
committerdaniel oeh <daniel.oeh@gmail.com>2012-08-16 15:09:49 +0200
commit1dd128a46c8dfbcc57f66eb0b2d61386a7c83dac (patch)
treebd333470f65acbb9d9c3591ebfe8d04423ea637c /src/de/danoeh/antennapod/service/download/DownloadService.java
parent853ae9af79249507392dd8e036a7aff6effd330a (diff)
downloadAntennaPod-1dd128a46c8dfbcc57f66eb0b2d61386a7c83dac.zip
Created abstract downloader class
Diffstat (limited to 'src/de/danoeh/antennapod/service/download/DownloadService.java')
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadService.java714
1 files changed, 714 insertions, 0 deletions
diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java
new file mode 100644
index 000000000..fba955e59
--- /dev/null
+++ b/src/de/danoeh/antennapod/service/download/DownloadService.java
@@ -0,0 +1,714 @@
+/**
+ * Registers a DownloadReceiver and waits for all Downloads
+ * to complete, then stops
+ * */
+
+package de.danoeh.antennapod.service.download;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.xml.sax.SAXException;
+
+import de.danoeh.antennapod.AppConfig;
+import de.danoeh.antennapod.PodcastApp;
+import de.danoeh.antennapod.activity.DownloadActivity;
+import de.danoeh.antennapod.activity.AudioplayerActivity;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.asynctask.DownloadObserver;
+import de.danoeh.antennapod.asynctask.DownloadStatus;
+import de.danoeh.antennapod.feed.*;
+import de.danoeh.antennapod.service.PlaybackService.LocalBinder;
+import de.danoeh.antennapod.storage.DownloadRequester;
+import de.danoeh.antennapod.syndication.handler.FeedHandler;
+import de.danoeh.antennapod.syndication.handler.UnsupportedFeedtypeException;
+import de.danoeh.antennapod.util.DownloadError;
+import de.danoeh.antennapod.util.InvalidFeedException;
+import android.annotation.SuppressLint;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.app.DownloadManager;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.IBinder;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.support.v4.app.NotificationCompat;
+import android.util.Log;
+import android.os.AsyncTask;
+import android.os.Binder;
+import android.os.Debug;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.PreferenceManager;
+
+public class DownloadService extends Service {
+ private static final String TAG = "DownloadService";
+
+ public static String ACTION_ALL_FEED_DOWNLOADS_COMPLETED = "action.de.danoeh.antennapod.storage.all_feed_downloads_completed";
+
+ /**
+ * If the DownloadService receives this intent, it will execute
+ * queryDownloads()
+ */
+ public static final String ACTION_NOTIFY_DOWNLOADS_CHANGED = "action.de.danoeh.antennapod.service.notifyDownloadsChanged";
+
+ public static final String ACTION_DOWNLOAD_HANDLED = "action.de.danoeh.antennapod.service.download_handled";
+ /** True if handled feed has an image. */
+ public static final String EXTRA_FEED_HAS_IMAGE = "extra.de.danoeh.antennapod.service.feed_has_image";
+ public static final String EXTRA_DOWNLOAD_ID = "extra.de.danoeh.antennapod.service.download_id";
+ public static final String EXTRA_IMAGE_DOWNLOAD_ID = "extra.de.danoeh.antennapod.service.image_download_id";
+
+ // Download types for ACTION_DOWNLOAD_HANDLED
+ public static final String EXTRA_DOWNLOAD_TYPE = "extra.de.danoeh.antennapod.service.downloadType";
+ public static final int DOWNLOAD_TYPE_FEED = 1;
+ public static final int DOWNLOAD_TYPE_MEDIA = 2;
+ public static final int DOWNLOAD_TYPE_IMAGE = 3;
+
+ private ArrayList<DownloadStatus> completedDownloads;
+
+ private ExecutorService syncExecutor;
+ private DownloadRequester requester;
+ private FeedManager manager;
+ private NotificationCompat.Builder notificationBuilder;
+ private int NOTIFICATION_ID = 2;
+ private int REPORT_ID = 3;
+ /** Needed to determine the duration of a media file */
+ private MediaPlayer mediaplayer;
+ private DownloadManager downloadManager;
+
+ private DownloadObserver downloadObserver;
+
+ private List<DownloadStatus> downloads;
+
+ private volatile boolean shutdownInitiated = false;
+ /** True if service is running. */
+ public static boolean isRunning = false;
+
+ /** Is started when service waits for shutdown. */
+ private Thread waiter;
+
+ private final IBinder mBinder = new LocalBinder();
+
+ public class LocalBinder extends Binder {
+ public DownloadService getService() {
+ return DownloadService.this;
+ }
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (waiter != null) {
+ waiter.interrupt();
+ }
+ queryDownloads();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @SuppressLint("NewApi")
+ @Override
+ public void onCreate() {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Service started");
+ isRunning = true;
+ completedDownloads = new ArrayList<DownloadStatus>();
+ downloads = new ArrayList<DownloadStatus>();
+ registerReceiver(downloadReceiver, createIntentFilter());
+ registerReceiver(onDownloadsChanged, new IntentFilter(
+ ACTION_NOTIFY_DOWNLOADS_CHANGED));
+ syncExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
+
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+ t.setPriority(Thread.MIN_PRIORITY);
+ t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+
+ @Override
+ public void uncaughtException(Thread thread, Throwable ex) {
+ Log.e(TAG, "Thread exited with uncaught exception");
+ ex.printStackTrace();
+ queryDownloads();
+ }
+ });
+ return t;
+ }
+ });
+ manager = FeedManager.getInstance();
+ requester = DownloadRequester.getInstance();
+ mediaplayer = new MediaPlayer();
+ downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
+ downloadObserver = new DownloadObserver(this);
+ setupNotification();
+ if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+ downloadObserver.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else {
+ downloadObserver.execute();
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ @Override
+ public void onDestroy() {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Service shutting down");
+ isRunning = false;
+ mediaplayer.release();
+ unregisterReceiver(downloadReceiver);
+ unregisterReceiver(onDownloadsChanged);
+ downloadObserver.cancel(true);
+ createReport();
+ }
+
+ private IntentFilter createIntentFilter() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+ return filter;
+ }
+
+ /** Shuts down Executor service and prepares for shutdown */
+ private void initiateShutdown() {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Initiating shutdown");
+ // Wait until PoolExecutor is done
+ waiter = new Thread() {
+ @Override
+ public void run() {
+ syncExecutor.shutdown();
+ try {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Starting to wait for termination");
+ boolean b = syncExecutor.awaitTermination(20L,
+ TimeUnit.SECONDS);
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "Stopping waiting for termination; Result : "
+ + b);
+ stopForeground(true);
+ stopSelf();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ Log.i(TAG, "Service shutdown was interrupted.");
+ shutdownInitiated = false;
+ }
+ }
+ };
+ waiter.start();
+ }
+
+ private void setupNotification() {
+ PendingIntent pIntent = PendingIntent.getActivity(this, 0, new Intent(
+ this, DownloadActivity.class),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Bitmap icon = BitmapFactory.decodeResource(null,
+ android.R.drawable.stat_notify_sync_noanim);
+ notificationBuilder = new NotificationCompat.Builder(this)
+ .setContentTitle("Downloading Podcast data")
+ .setContentText(
+ requester.getNumberOfDownloads() + " Downloads left")
+ .setOngoing(true).setContentIntent(pIntent).setLargeIcon(icon)
+ .setSmallIcon(android.R.drawable.stat_notify_sync_noanim);
+
+ startForeground(NOTIFICATION_ID, notificationBuilder.getNotification());
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Notification set up");
+ }
+
+ private BroadcastReceiver onDownloadsChanged = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(ACTION_NOTIFY_DOWNLOADS_CHANGED)) {
+ queryDownloads();
+ }
+ }
+ };
+
+ private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
+ @SuppressLint("NewApi")
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ AsyncTask<Void, Void, Void> handler = new AsyncTask<Void, Void, Void>() {
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ int status = -1;
+ String file_url = null;
+ boolean successful = false;
+ int reason = 0;
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Received 'Download Complete' - message.");
+ long downloadId = intent.getLongExtra(
+ DownloadManager.EXTRA_DOWNLOAD_ID, 0);
+ // get status
+ DownloadManager.Query q = new DownloadManager.Query();
+ q.setFilterById(downloadId);
+ Cursor c = downloadManager.query(q);
+ if (c.moveToFirst()) {
+ status = c.getInt(c
+ .getColumnIndex(DownloadManager.COLUMN_STATUS));
+ String uriString = c
+ .getString(c
+ .getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
+ if (uriString != null) {
+ Uri file_uri = Uri.parse(uriString);
+ file_url = file_uri.getPath();
+ } else {
+ Log.w(TAG,
+ "DownloadManager didn't provide a destination URI for downloaded file");
+ }
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "File url given by download manager is "
+ + file_url);
+ }
+ if (downloadId == 0) {
+ Log.d(TAG, "Download ID was null");
+ }
+ FeedFile download = requester.getFeedFile(downloadId);
+ if (download != null) {
+ if (status == DownloadManager.STATUS_SUCCESSFUL) {
+ if (file_url != null) {
+ download.setFile_url(file_url);
+ }
+ if (download.getClass() == Feed.class) {
+ handleCompletedFeedDownload(context,
+ (Feed) download);
+ } else if (download.getClass() == FeedImage.class) {
+ handleCompletedImageDownload(context,
+ (FeedImage) download);
+ } else if (download.getClass() == FeedMedia.class) {
+ handleCompletedFeedMediaDownload(context,
+ (FeedMedia) download);
+ }
+ successful = true;
+
+ } else if (status == DownloadManager.STATUS_FAILED) {
+ reason = c
+ .getInt(c
+ .getColumnIndex(DownloadManager.COLUMN_REASON));
+ Log.e(TAG, "Download failed");
+ Log.e(TAG, "reason code is " + reason);
+ successful = false;
+ saveDownloadStatus(new DownloadStatus(download,
+ reason, successful));
+ requester.removeDownload(download);
+ sendDownloadHandledIntent(download.getDownloadId(),
+ false, 0, getDownloadType(download));
+ download.setDownloadId(0);
+
+ }
+ queryDownloads();
+ }
+ c.close();
+ return null;
+ }
+ };
+ if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+ handler.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } else {
+ handler.execute();
+ }
+ }
+
+ };
+
+ /**
+ * Adds a new DownloadStatus object to the list of completed downloads and
+ * saves it in the database
+ *
+ * @param status
+ * the download that is going to be saved
+ */
+ private void saveDownloadStatus(DownloadStatus status) {
+ completedDownloads.add(status);
+ manager.addDownloadStatus(this, status);
+ }
+
+ /** Returns correct value for EXTRA_DOWNLOAD_TYPE. */
+ private int getDownloadType(FeedFile f) {
+ if (f.getClass() == Feed.class) {
+ return DOWNLOAD_TYPE_FEED;
+ } else if (f.getClass() == FeedImage.class) {
+ return DOWNLOAD_TYPE_IMAGE;
+ } else if (f.getClass() == FeedMedia.class) {
+ return DOWNLOAD_TYPE_MEDIA;
+ } else {
+ return 0;
+ }
+ }
+
+ private void sendDownloadHandledIntent(long downloadId,
+ boolean feedHasImage, long imageDownloadId, int type) {
+ Intent intent = new Intent(ACTION_DOWNLOAD_HANDLED);
+ intent.putExtra(EXTRA_DOWNLOAD_ID, downloadId);
+ intent.putExtra(EXTRA_FEED_HAS_IMAGE, feedHasImage);
+ intent.putExtra(EXTRA_DOWNLOAD_TYPE, type);
+ if (feedHasImage) {
+ intent.putExtra(EXTRA_IMAGE_DOWNLOAD_ID, imageDownloadId);
+ }
+ sendBroadcast(intent);
+ }
+
+ /**
+ * Creates a notification at the end of the service lifecycle to notify the
+ * user about the number of completed downloads. A report will only be
+ * created if the number of feeds is > 1 or if at least one media file was
+ * downloaded.
+ */
+ private void createReport() {
+ // check if report should be created
+ boolean createReport = false;
+ int feedCount = 0;
+ for (DownloadStatus status : completedDownloads) {
+ if (status.getFeedFile().getClass() == Feed.class) {
+ feedCount++;
+ if (feedCount > 1) {
+ createReport = true;
+ break;
+ }
+ } else if (status.getFeedFile().getClass() == FeedMedia.class) {
+ createReport = true;
+ break;
+ }
+ }
+ if (createReport) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Creating report");
+ int successfulDownloads = 0;
+ int failedDownloads = 0;
+ for (DownloadStatus status : completedDownloads) {
+ if (status.isSuccessful()) {
+ successfulDownloads++;
+ } else {
+ failedDownloads++;
+ }
+ }
+ // create notification object
+ Notification notification = new NotificationCompat.Builder(this)
+ .setTicker(
+ getString(de.danoeh.antennapod.R.string.download_report_title))
+ .setContentTitle(
+ getString(de.danoeh.antennapod.R.string.download_report_title))
+ .setContentText(
+ successfulDownloads + " Downloads succeeded, "
+ + failedDownloads + " failed")
+ .setSmallIcon(android.R.drawable.stat_notify_sync)
+ .setLargeIcon(
+ BitmapFactory.decodeResource(null,
+ android.R.drawable.stat_notify_sync))
+ .setContentIntent(
+ PendingIntent.getActivity(this, 0, new Intent(this,
+ MainActivity.class), 0))
+ .setAutoCancel(true).getNotification();
+ NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.notify(REPORT_ID, notification);
+
+ } else {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "No report is created");
+ }
+ }
+
+ /** Check if there's something else to download, otherwise stop */
+ void queryDownloads() {
+ int numOfDownloads = requester.getNumberOfDownloads();
+ if (!shutdownInitiated && numOfDownloads == 0) {
+ shutdownInitiated = true;
+ initiateShutdown();
+ } else {
+ // update notification
+ notificationBuilder.setContentText(numOfDownloads
+ + " Downloads left");
+ NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.notify(NOTIFICATION_ID, notificationBuilder.getNotification());
+ }
+ }
+
+ /** Is called whenever a Feed is downloaded */
+ private void handleCompletedFeedDownload(Context context, Feed feed) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Handling completed Feed Download");
+ syncExecutor.execute(new FeedSyncThread(feed, this));
+
+ }
+
+ /** Is called whenever a Feed-Image is downloaded */
+ private void handleCompletedImageDownload(Context context, FeedImage image) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Handling completed Image Download");
+ syncExecutor.execute(new ImageHandlerThread(image, this));
+ }
+
+ /** Is called whenever a FeedMedia is downloaded. */
+ private void handleCompletedFeedMediaDownload(Context context,
+ FeedMedia media) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Handling completed FeedMedia Download");
+ syncExecutor.execute(new MediaHandlerThread(media, this));
+ }
+
+ /**
+ * Takes a single Feed, parses the corresponding file and refreshes
+ * information in the manager
+ */
+ class FeedSyncThread implements Runnable {
+ private static final String TAG = "FeedSyncThread";
+
+ private Feed feed;
+ private DownloadService service;
+
+ private int reason;
+ private boolean successful;
+
+ public FeedSyncThread(Feed feed, DownloadService service) {
+ this.feed = feed;
+ this.service = service;
+ }
+
+ public void run() {
+ Feed savedFeed = null;
+ long imageId = 0;
+ boolean hasImage = false;
+ long downloadId = feed.getDownloadId();
+ reason = 0;
+ successful = true;
+ FeedManager manager = FeedManager.getInstance();
+ FeedHandler handler = new FeedHandler();
+ feed.setDownloaded(true);
+
+ try {
+ feed = handler.parseFeed(feed);
+ if (AppConfig.DEBUG)
+ Log.d(TAG, feed.getTitle() + " parsed");
+ if (checkFeedData(feed) == false) {
+ throw new InvalidFeedException();
+ }
+ feed.setDownloadId(0);
+ // Save information of feed in DB
+ savedFeed = manager.updateFeed(service, feed);
+ // Download Feed Image if provided and not downloaded
+ if (savedFeed.getImage() != null
+ && savedFeed.getImage().isDownloaded() == false) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Feed has image; Downloading....");
+ savedFeed.getImage().setFeed(savedFeed);
+ imageId = requester.downloadImage(service,
+ savedFeed.getImage());
+ hasImage = true;
+ }
+
+ } catch (SAXException e) {
+ successful = false;
+ e.printStackTrace();
+ reason = DownloadError.ERROR_PARSER_EXCEPTION;
+ } catch (IOException e) {
+ successful = false;
+ e.printStackTrace();
+ reason = DownloadError.ERROR_PARSER_EXCEPTION;
+ } catch (ParserConfigurationException e) {
+ successful = false;
+ e.printStackTrace();
+ reason = DownloadError.ERROR_PARSER_EXCEPTION;
+ } catch (UnsupportedFeedtypeException e) {
+ e.printStackTrace();
+ successful = false;
+ reason = DownloadError.ERROR_UNSUPPORTED_TYPE;
+ } catch (InvalidFeedException e) {
+ e.printStackTrace();
+ successful = false;
+ reason = DownloadError.ERROR_PARSER_EXCEPTION;
+ }
+
+ requester.removeDownload(feed);
+ // cleanup();
+ if (savedFeed == null) {
+ savedFeed = feed;
+ }
+ saveDownloadStatus(new DownloadStatus(savedFeed, reason, successful));
+ sendDownloadHandledIntent(downloadId, hasImage, imageId,
+ DOWNLOAD_TYPE_FEED);
+ queryDownloads();
+ }
+
+ /** Checks if the feed was parsed correctly. */
+ private boolean checkFeedData(Feed feed) {
+ if (feed.getTitle() == null) {
+ Log.e(TAG, "Feed has no title.");
+ return false;
+ } else {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Feed appears to be valid.");
+ return true;
+ }
+ }
+
+ /** Delete files that aren't needed anymore */
+ private void cleanup() {
+ if (feed.getFile_url() != null) {
+ if (new File(feed.getFile_url()).delete())
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Successfully deleted cache file.");
+ else
+ Log.e(TAG, "Failed to delete cache file.");
+ feed.setFile_url(null);
+ } else if (AppConfig.DEBUG) {
+ Log.d(TAG, "Didn't delete cache file: File url is not set.");
+ }
+ }
+
+ }
+
+ /** Handles a completed image download. */
+ class ImageHandlerThread implements Runnable {
+ private FeedImage image;
+ private DownloadService service;
+
+ public ImageHandlerThread(FeedImage image, DownloadService service) {
+ this.image = image;
+ this.service = service;
+ }
+
+ @Override
+ public void run() {
+ image.setDownloaded(true);
+ requester.removeDownload(image);
+
+ saveDownloadStatus(new DownloadStatus(image, 0, true));
+ sendDownloadHandledIntent(image.getDownloadId(), false, 0,
+ DOWNLOAD_TYPE_IMAGE);
+ image.setDownloadId(0);
+ manager.setFeedImage(service, image);
+ if (image.getFeed() != null) {
+ manager.setFeed(service, image.getFeed());
+ } else {
+ Log.e(TAG,
+ "Image has no feed, image might not be saved correctly!");
+ }
+ queryDownloads();
+ }
+ }
+
+ /** Handles a completed media download. */
+ class MediaHandlerThread implements Runnable {
+ private FeedMedia media;
+ private DownloadService service;
+
+ public MediaHandlerThread(FeedMedia media, DownloadService service) {
+ super();
+ this.media = media;
+ this.service = service;
+ }
+
+ @Override
+ public void run() {
+ requester.removeDownload(media);
+ media.setDownloaded(true);
+ // Get duration
+ try {
+ mediaplayer.setDataSource(media.getFile_url());
+ mediaplayer.prepare();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ media.setDuration(mediaplayer.getDuration());
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Duration of file is " + media.getDuration());
+ mediaplayer.reset();
+ saveDownloadStatus(new DownloadStatus(media, 0, true));
+ sendDownloadHandledIntent(media.getDownloadId(), false, 0,
+ DOWNLOAD_TYPE_MEDIA);
+ media.setDownloadId(0);
+ manager.setFeedMedia(service, media);
+ boolean autoQueue = PreferenceManager.getDefaultSharedPreferences(
+ getApplicationContext()).getBoolean(
+ PodcastApp.PREF_AUTO_QUEUE, true);
+
+ if (!manager.isInQueue(media.getItem())) {
+ // Auto-queue
+ if (autoQueue) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Autoqueue is enabled. Adding item to queue");
+ manager.addQueueItem(DownloadService.this, media.getItem());
+ } else {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Autoqueue is disabled");
+ }
+ } else {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Item is already in queue");
+ }
+
+ queryDownloads();
+ }
+ }
+
+ /** Is used to request a new download. */
+ public static class Request implements Parcelable {
+ private String destination;
+ private String source;
+
+ public Request(String destination, String source) {
+ super();
+ this.destination = destination;
+ this.source = source;
+ }
+
+ private Request(Parcel in) {
+ destination = in.readString();
+ source = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(destination);
+ dest.writeString(source);
+ }
+
+ public static final Parcelable.Creator<Request> CREATOR = new Parcelable.Creator<Request>() {
+ public Request createFromParcel(Parcel in) {
+ return new Request(in);
+ }
+
+ public Request[] newArray(int size) {
+ return new Request[size];
+ }
+ };
+
+ }
+
+
+
+ public DownloadObserver getDownloadObserver() {
+ return downloadObserver;
+ }
+
+}