summaryrefslogtreecommitdiff
path: root/src/de/danoeh/antennapod/storage
diff options
context:
space:
mode:
authordaniel oeh <daniel.oeh@gmail.com>2013-08-03 13:58:31 +0200
committerdaniel oeh <daniel.oeh@gmail.com>2013-08-03 13:58:31 +0200
commit9ba3dc0d823b786700010a60d38f47c802101d27 (patch)
tree89b74eff993fdcb3b373c64695c72d534f1a80cd /src/de/danoeh/antennapod/storage
parent2071793e6aa1a106744078fcbcf7c0529ed315c4 (diff)
downloadAntennaPod-9ba3dc0d823b786700010a60d38f47c802101d27.zip
Improved DownloadService, several bugfixes
- DownloadService should now terminate properly as soon as all downloads have been completed. - Notification bug ("0 downloads left" notification) should be fixed
Diffstat (limited to 'src/de/danoeh/antennapod/storage')
-rw-r--r--src/de/danoeh/antennapod/storage/DBReader.java97
-rw-r--r--src/de/danoeh/antennapod/storage/DBTasks.java23
-rw-r--r--src/de/danoeh/antennapod/storage/DBWriter.java8
-rw-r--r--src/de/danoeh/antennapod/storage/DownloadRequester.java540
-rw-r--r--src/de/danoeh/antennapod/storage/PodDBAdapter.java41
5 files changed, 397 insertions, 312 deletions
diff --git a/src/de/danoeh/antennapod/storage/DBReader.java b/src/de/danoeh/antennapod/storage/DBReader.java
index c8135bea1..c69607473 100644
--- a/src/de/danoeh/antennapod/storage/DBReader.java
+++ b/src/de/danoeh/antennapod/storage/DBReader.java
@@ -188,41 +188,45 @@ public final class DBReader {
List<FeedItem> items, ArrayList<String> itemIds) {
List<FeedItem> itemsCopy = new ArrayList<FeedItem>(items);
- Cursor cursor = adapter.getFeedMediaCursor(itemIds
- .toArray(new String[itemIds.size()]));
+ Cursor cursor = adapter.getFeedMediaCursorByItemID(itemIds
+ .toArray(new String[itemIds.size()]));
if (cursor.moveToFirst()) {
do {
- long mediaId = cursor.getLong(PodDBAdapter.KEY_ID_INDEX);
long itemId = cursor.getLong(PodDBAdapter.KEY_MEDIA_FEEDITEM_INDEX);
// find matching feed item
FeedItem item = getMatchingItemForMedia(itemId, itemsCopy);
if (item != null) {
- Date playbackCompletionDate = null;
- long playbackCompletionTime = cursor
- .getLong(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE_INDEX);
- if (playbackCompletionTime > 0) {
- playbackCompletionDate = new Date(
- playbackCompletionTime);
- }
-
- item.setMedia(new FeedMedia(
- mediaId,
- item,
- cursor.getInt(PodDBAdapter.KEY_DURATION_INDEX),
- cursor.getInt(PodDBAdapter.KEY_POSITION_INDEX),
- cursor.getLong(PodDBAdapter.KEY_SIZE_INDEX),
- cursor.getString(PodDBAdapter.KEY_MIME_TYPE_INDEX),
- cursor.getString(PodDBAdapter.KEY_FILE_URL_INDEX),
- cursor.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX),
- cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0,
- playbackCompletionDate));
-
+ item.setMedia(extractFeedMediaFromCursorRow(cursor));
+ item.getMedia().setItem(item);
}
} while (cursor.moveToNext());
cursor.close();
}
}
+ private static FeedMedia extractFeedMediaFromCursorRow(final Cursor cursor) {
+ long mediaId = cursor.getLong(PodDBAdapter.KEY_ID_INDEX);
+ Date playbackCompletionDate = null;
+ long playbackCompletionTime = cursor
+ .getLong(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE_INDEX);
+ if (playbackCompletionTime > 0) {
+ playbackCompletionDate = new Date(
+ playbackCompletionTime);
+ }
+
+ return new FeedMedia(
+ mediaId,
+ null,
+ cursor.getInt(PodDBAdapter.KEY_DURATION_INDEX),
+ cursor.getInt(PodDBAdapter.KEY_POSITION_INDEX),
+ cursor.getLong(PodDBAdapter.KEY_SIZE_INDEX),
+ cursor.getString(PodDBAdapter.KEY_MIME_TYPE_INDEX),
+ cursor.getString(PodDBAdapter.KEY_FILE_URL_INDEX),
+ cursor.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX),
+ cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0,
+ playbackCompletionDate);
+ }
+
private static Feed extractFeedFromCursorRow(PodDBAdapter adapter,
Cursor cursor) {
Date lastUpdate = new Date(
@@ -481,6 +485,21 @@ public final class DBReader {
return result;
}
+ /**
+ * Searches the DB for a FeedImage of the given id.
+ *
+ * @param imageId
+ * The id of the object
+ * @return The found object
+ * */
+ public static FeedImage getFeedImage(final Context context, final long imageId) {
+ PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ FeedImage result = getFeedImage(adapter, imageId);
+ adapter.close();
+ return result;
+ }
+
/**
* Searches the DB for a FeedImage of the given id.
*
@@ -488,7 +507,7 @@ public final class DBReader {
* The id of the object
* @return The found object
* */
- public static FeedImage getFeedImage(PodDBAdapter adapter, final long id) {
+ static FeedImage getFeedImage(PodDBAdapter adapter, final long id) {
Cursor cursor = adapter.getImageOfFeedCursor(id);
if ((cursor.getCount() == 0) || !cursor.moveToFirst()) {
throw new SQLException("No FeedImage found at index: " + id);
@@ -504,4 +523,34 @@ public final class DBReader {
cursor.close();
return image;
}
+
+ /**
+ * Searches the DB for a FeedMedia of the given id.
+ *
+ * @param mediaId
+ * The id of the object
+ * @return The found object
+ * */
+ public static FeedMedia getFeedMedia(final Context context, final long mediaId) {
+ PodDBAdapter adapter = new PodDBAdapter(context);
+
+ adapter.open();
+ Cursor mediaCursor = adapter.getSingleFeedMediaCursor(mediaId);
+
+ FeedMedia media = null;
+ if (mediaCursor.moveToFirst()) {
+ final long itemId = mediaCursor.getLong(PodDBAdapter.KEY_MEDIA_FEEDITEM_INDEX);
+ media = extractFeedMediaFromCursorRow(mediaCursor);
+ FeedItem item = getFeedItem(context, itemId);
+ if (media != null && item != null) {
+ media.setItem(item);
+ item.setMedia(media);
+ }
+ }
+
+ mediaCursor.close();
+ adapter.close();
+
+ return media;
+ }
}
diff --git a/src/de/danoeh/antennapod/storage/DBTasks.java b/src/de/danoeh/antennapod/storage/DBTasks.java
index 39c30445e..45ce4298a 100644
--- a/src/de/danoeh/antennapod/storage/DBTasks.java
+++ b/src/de/danoeh/antennapod/storage/DBTasks.java
@@ -7,6 +7,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.ReentrantLock;
import android.content.Context;
@@ -25,6 +26,7 @@ import de.danoeh.antennapod.service.PlaybackService;
import de.danoeh.antennapod.service.download.DownloadStatus;
import de.danoeh.antennapod.util.DownloadError;
import de.danoeh.antennapod.util.NetworkUtils;
+import de.danoeh.antennapod.util.QueueAccess;
import de.danoeh.antennapod.util.exception.MediaFileNotFoundException;
public final class DBTasks {
@@ -397,6 +399,11 @@ public final class DBTasks {
return result;
}
+ public static boolean isInQueue(Context context, final long feedItemId) {
+ List<Long> queue = DBReader.getQueueIDList(context);
+ return QueueAccess.IDListAccess(queue).contains(feedItemId);
+ }
+
private static Feed searchFeedByIdentifyingValue(Context context,
String identifier) {
List<Feed> feeds = DBReader.getFeedList(context);
@@ -430,7 +437,13 @@ public final class DBTasks {
"Found no existing Feed with title "
+ newFeed.getTitle() + ". Adding as new one.");
// Add a new Feed
- DBWriter.addNewFeed(context, newFeed);
+ try {
+ DBWriter.addNewFeed(context, newFeed).get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
return newFeed;
} else {
if (AppConfig.DEBUG)
@@ -462,7 +475,13 @@ public final class DBTasks {
// update attributes
savedFeed.setLastUpdate(newFeed.getLastUpdate());
savedFeed.setType(newFeed.getType());
- DBWriter.setCompleteFeed(context, savedFeed);
+ try {
+ DBWriter.setCompleteFeed(context, savedFeed).get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
new Thread() {
@Override
public void run() {
diff --git a/src/de/danoeh/antennapod/storage/DBWriter.java b/src/de/danoeh/antennapod/storage/DBWriter.java
index 76f6306f8..a60694f35 100644
--- a/src/de/danoeh/antennapod/storage/DBWriter.java
+++ b/src/de/danoeh/antennapod/storage/DBWriter.java
@@ -488,8 +488,8 @@ public class DBWriter {
}
- static void addNewFeed(final Context context, final Feed feed) {
- dbExec.submit(new Runnable() {
+ static Future<?> addNewFeed(final Context context, final Feed feed) {
+ return dbExec.submit(new Runnable() {
@Override
public void run() {
@@ -503,8 +503,8 @@ public class DBWriter {
});
}
- static void setCompleteFeed(final Context context, final Feed feed) {
- dbExec.submit(new Runnable() {
+ static Future<?> setCompleteFeed(final Context context, final Feed feed) {
+ return dbExec.submit(new Runnable() {
@Override
public void run() {
diff --git a/src/de/danoeh/antennapod/storage/DownloadRequester.java b/src/de/danoeh/antennapod/storage/DownloadRequester.java
index a27fbf8e4..4e74d5e98 100644
--- a/src/de/danoeh/antennapod/storage/DownloadRequester.java
+++ b/src/de/danoeh/antennapod/storage/DownloadRequester.java
@@ -24,273 +24,277 @@ import de.danoeh.antennapod.util.FileNameGenerator;
import de.danoeh.antennapod.util.URLChecker;
public class DownloadRequester {
- private static final String TAG = "DownloadRequester";
-
- public static String IMAGE_DOWNLOADPATH = "images/";
- public static String FEED_DOWNLOADPATH = "cache/";
- public static String MEDIA_DOWNLOADPATH = "media/";
-
- private static DownloadRequester downloader;
-
- Map<String, DownloadRequest> downloads;
-
- private DownloadRequester() {
- downloads = new ConcurrentHashMap<String, DownloadRequest>();
- }
-
- public static DownloadRequester getInstance() {
- if (downloader == null) {
- downloader = new DownloadRequester();
- }
- return downloader;
- }
-
- private void download(Context context, FeedFile item, File dest,
- boolean overwriteIfExists) {
- if (!isDownloadingFile(item)) {
- if (!isFilenameAvailable(dest.toString()) || dest.exists()) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Filename already used.");
- if (isFilenameAvailable(dest.toString()) && overwriteIfExists) {
- boolean result = dest.delete();
- if (AppConfig.DEBUG)
- Log.d(TAG, "Deleting file. Result: " + result);
- } else {
- // find different name
- File newDest = null;
- for (int i = 1; i < Integer.MAX_VALUE; i++) {
- String newName = FilenameUtils.getBaseName(dest
- .getName())
- + "-"
- + i
- + "."
- + FilenameUtils.getExtension(dest.getName());
- if (AppConfig.DEBUG)
- Log.d(TAG, "Testing filename " + newName);
- newDest = new File(dest.getParent(), newName);
- if (!newDest.exists()
- && isFilenameAvailable(newDest.toString())) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "File doesn't exist yet. Using "
- + newName);
- break;
- }
- }
- if (newDest != null) {
- dest = newDest;
- }
- }
- }
- if (AppConfig.DEBUG)
- Log.d(TAG,
- "Requesting download of url " + item.getDownload_url());
- item.setDownload_url(URLChecker.prepareURL(item.getDownload_url()));
-
- DownloadRequest request = new DownloadRequest(dest.toString(),
- item.getDownload_url(), item.getHumanReadableIdentifier(),
- item.getId(), item.getTypeAsInt());
-
- downloads.put(request.getSource(), request);
-
-
- if (!DownloadService.isRunning) {
- Intent launchIntent = new Intent(context, DownloadService.class);
- launchIntent.putExtra(DownloadService.EXTRA_REQUEST, request);
- context.startService(launchIntent);
- } else {
- Intent queueIntent = new Intent(
- DownloadService.ACTION_ENQUEUE_DOWNLOAD);
- queueIntent.putExtra(DownloadService.EXTRA_REQUEST, request);
- context.sendBroadcast(queueIntent);
- }
- EventDistributor.getInstance().sendDownloadQueuedBroadcast();
- } else {
- Log.e(TAG, "URL " + item.getDownload_url()
- + " is already being downloaded");
- }
- }
-
- /**
- * Returns true if a filename is available and false if it has already been
- * taken by another requested download.
- */
- private boolean isFilenameAvailable(String path) {
- for (String key : downloads.keySet()) {
- DownloadRequest r = downloads.get(key);
- if (StringUtils.equals(r.getDestination(), path)) {
- if (AppConfig.DEBUG)
- Log.d(TAG, path
- + " is already used by another requested download");
- return false;
- }
- }
- if (AppConfig.DEBUG)
- Log.d(TAG, path + " is available as a download destination");
- return true;
- }
-
- public void downloadFeed(Context context, Feed feed)
- throws DownloadRequestException {
- if (feedFileValid(feed)) {
- download(context, feed, new File(getFeedfilePath(context),
- getFeedfileName(feed)), true);
- }
- }
-
- public void downloadImage(Context context, FeedImage image)
- throws DownloadRequestException {
- if (feedFileValid(image)) {
- download(context, image, new File(getImagefilePath(context),
- getImagefileName(image)), true);
- }
- }
-
- public void downloadMedia(Context context, FeedMedia feedmedia)
- throws DownloadRequestException {
- if (feedFileValid(feedmedia)) {
- download(context, feedmedia,
- new File(getMediafilePath(context, feedmedia),
- getMediafilename(feedmedia)), false);
- }
- }
-
- /**
- * Throws a DownloadRequestException if the feedfile or the download url of
- * the feedfile is null.
- *
- * @throws DownloadRequestException
- */
- private boolean feedFileValid(FeedFile f) throws DownloadRequestException {
- if (f == null) {
- throw new DownloadRequestException("Feedfile was null");
- } else if (f.getDownload_url() == null) {
- throw new DownloadRequestException("File has no download URL");
- } else {
- return true;
- }
- }
-
- /**
- * Cancels a running download.
- * */
- public void cancelDownload(final Context context, final FeedFile f) {
- cancelDownload(context, f.getDownload_url());
- }
-
- /**
- * Cancels a running download.
- * */
- public void cancelDownload(final Context context, final String downloadUrl) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Cancelling download with url " + downloadUrl);
- Intent cancelIntent = new Intent(DownloadService.ACTION_CANCEL_DOWNLOAD);
- cancelIntent.putExtra(DownloadService.EXTRA_DOWNLOAD_URL, downloadUrl);
- context.sendBroadcast(cancelIntent);
- }
-
- /** Cancels all running downloads */
- public void cancelAllDownloads(Context context) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Cancelling all running downloads");
- context.sendBroadcast(new Intent(
- DownloadService.ACTION_CANCEL_ALL_DOWNLOADS));
- }
-
- /** Returns true if there is at least one Feed in the downloads queue. */
- public boolean isDownloadingFeeds() {
- for (DownloadRequest r : downloads.values()) {
- if (r.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
- return true;
- }
- }
- return false;
- }
-
- /** Checks if feedfile is in the downloads list */
- public boolean isDownloadingFile(FeedFile item) {
- if (item.getDownload_url() != null) {
- return downloads.containsKey(item.getDownload_url());
- }
- return false;
- }
-
- public DownloadRequest getDownload(String downloadUrl) {
- return downloads.get(downloadUrl);
- }
-
- /** Checks if feedfile with the given download url is in the downloads list */
- public boolean isDownloadingFile(String downloadUrl) {
- return downloads.get(downloadUrl) != null;
- }
-
- public boolean hasNoDownloads() {
- return downloads.isEmpty();
- }
-
- /** Remove an object from the downloads-list of the requester. */
- public void removeDownload(DownloadRequest r) {
- if (downloads.remove(r.getSource()) == null) {
- Log.e(TAG,
- "Could not remove object with url " + r.getSource());
- }
- }
-
- /** Get the number of uncompleted Downloads */
- public int getNumberOfDownloads() {
- return downloads.size();
- }
-
- public String getFeedfilePath(Context context)
- throws DownloadRequestException {
- return getExternalFilesDirOrThrowException(context, FEED_DOWNLOADPATH)
- .toString() + "/";
- }
-
- public String getFeedfileName(Feed feed) {
- String filename = feed.getDownload_url();
- if (feed.getTitle() != null && !feed.getTitle().isEmpty()) {
- filename = feed.getTitle();
- }
- return "feed-" + FileNameGenerator.generateFileName(filename);
- }
-
- public String getImagefilePath(Context context)
- throws DownloadRequestException {
- return getExternalFilesDirOrThrowException(context, IMAGE_DOWNLOADPATH)
- .toString() + "/";
- }
-
- public String getImagefileName(FeedImage image) {
- String filename = image.getDownload_url();
- if (image.getFeed() != null && image.getFeed().getTitle() != null) {
- filename = image.getFeed().getTitle();
- }
- return "image-" + FileNameGenerator.generateFileName(filename);
- }
-
- public String getMediafilePath(Context context, FeedMedia media)
- throws DownloadRequestException {
- File externalStorage = getExternalFilesDirOrThrowException(
- context,
- MEDIA_DOWNLOADPATH
- + FileNameGenerator.generateFileName(media.getItem()
- .getFeed().getTitle()) + "/");
- return externalStorage.toString();
- }
-
- private File getExternalFilesDirOrThrowException(Context context,
- String type) throws DownloadRequestException {
- File result = UserPreferences.getDataFolder(context, type);
- if (result == null) {
- throw new DownloadRequestException(
- "Failed to access external storage");
- }
- return result;
- }
-
- public String getMediafilename(FeedMedia media) {
- return URLUtil.guessFileName(media.getDownload_url(), null,
- media.getMime_type());
- }
+ private static final String TAG = "DownloadRequester";
+
+ public static String IMAGE_DOWNLOADPATH = "images/";
+ public static String FEED_DOWNLOADPATH = "cache/";
+ public static String MEDIA_DOWNLOADPATH = "media/";
+
+ private static DownloadRequester downloader;
+
+ Map<String, DownloadRequest> downloads;
+
+ private DownloadRequester() {
+ downloads = new ConcurrentHashMap<String, DownloadRequest>();
+ }
+
+ public static DownloadRequester getInstance() {
+ if (downloader == null) {
+ downloader = new DownloadRequester();
+ }
+ return downloader;
+ }
+
+ private void download(Context context, FeedFile item, File dest,
+ boolean overwriteIfExists) {
+ if (!isDownloadingFile(item)) {
+ if (!isFilenameAvailable(dest.toString()) || dest.exists()) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Filename already used.");
+ if (isFilenameAvailable(dest.toString()) && overwriteIfExists) {
+ boolean result = dest.delete();
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Deleting file. Result: " + result);
+ } else {
+ // find different name
+ File newDest = null;
+ for (int i = 1; i < Integer.MAX_VALUE; i++) {
+ String newName = FilenameUtils.getBaseName(dest
+ .getName())
+ + "-"
+ + i
+ + "."
+ + FilenameUtils.getExtension(dest.getName());
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Testing filename " + newName);
+ newDest = new File(dest.getParent(), newName);
+ if (!newDest.exists()
+ && isFilenameAvailable(newDest.toString())) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "File doesn't exist yet. Using "
+ + newName);
+ break;
+ }
+ }
+ if (newDest != null) {
+ dest = newDest;
+ }
+ }
+ }
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "Requesting download of url " + item.getDownload_url());
+ item.setDownload_url(URLChecker.prepareURL(item.getDownload_url()));
+
+ DownloadRequest request = new DownloadRequest(dest.toString(),
+ item.getDownload_url(), item.getHumanReadableIdentifier(),
+ item.getId(), item.getTypeAsInt());
+
+ downloads.put(request.getSource(), request);
+
+ Intent launchIntent = new Intent(context, DownloadService.class);
+ launchIntent.putExtra(DownloadService.EXTRA_REQUEST, request);
+ context.startService(launchIntent);
+ EventDistributor.getInstance().sendDownloadQueuedBroadcast();
+ } else {
+ Log.e(TAG, "URL " + item.getDownload_url()
+ + " is already being downloaded");
+ }
+ }
+
+ /**
+ * Returns true if a filename is available and false if it has already been
+ * taken by another requested download.
+ */
+ private boolean isFilenameAvailable(String path) {
+ for (String key : downloads.keySet()) {
+ DownloadRequest r = downloads.get(key);
+ if (StringUtils.equals(r.getDestination(), path)) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, path
+ + " is already used by another requested download");
+ return false;
+ }
+ }
+ if (AppConfig.DEBUG)
+ Log.d(TAG, path + " is available as a download destination");
+ return true;
+ }
+
+ public void downloadFeed(Context context, Feed feed)
+ throws DownloadRequestException {
+ if (feedFileValid(feed)) {
+ download(context, feed, new File(getFeedfilePath(context),
+ getFeedfileName(feed)), true);
+ }
+ }
+
+ public void downloadImage(Context context, FeedImage image)
+ throws DownloadRequestException {
+ if (feedFileValid(image)) {
+ download(context, image, new File(getImagefilePath(context),
+ getImagefileName(image)), true);
+ }
+ }
+
+ public void downloadMedia(Context context, FeedMedia feedmedia)
+ throws DownloadRequestException {
+ if (feedFileValid(feedmedia)) {
+ download(context, feedmedia,
+ new File(getMediafilePath(context, feedmedia),
+ getMediafilename(feedmedia)), false);
+ }
+ }
+
+ /**
+ * Throws a DownloadRequestException if the feedfile or the download url of
+ * the feedfile is null.
+ *
+ * @throws DownloadRequestException
+ */
+ private boolean feedFileValid(FeedFile f) throws DownloadRequestException {
+ if (f == null) {
+ throw new DownloadRequestException("Feedfile was null");
+ } else if (f.getDownload_url() == null) {
+ throw new DownloadRequestException("File has no download URL");
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Cancels a running download.
+ */
+ public void cancelDownload(final Context context, final FeedFile f) {
+ cancelDownload(context, f.getDownload_url());
+ }
+
+ /**
+ * Cancels a running download.
+ */
+ public void cancelDownload(final Context context, final String downloadUrl) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Cancelling download with url " + downloadUrl);
+ Intent cancelIntent = new Intent(DownloadService.ACTION_CANCEL_DOWNLOAD);
+ cancelIntent.putExtra(DownloadService.EXTRA_DOWNLOAD_URL, downloadUrl);
+ context.sendBroadcast(cancelIntent);
+ }
+
+ /**
+ * Cancels all running downloads
+ */
+ public void cancelAllDownloads(Context context) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Cancelling all running downloads");
+ context.sendBroadcast(new Intent(
+ DownloadService.ACTION_CANCEL_ALL_DOWNLOADS));
+ }
+
+ /**
+ * Returns true if there is at least one Feed in the downloads queue.
+ */
+ public boolean isDownloadingFeeds() {
+ for (DownloadRequest r : downloads.values()) {
+ if (r.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if feedfile is in the downloads list
+ */
+ public boolean isDownloadingFile(FeedFile item) {
+ if (item.getDownload_url() != null) {
+ return downloads.containsKey(item.getDownload_url());
+ }
+ return false;
+ }
+
+ public DownloadRequest getDownload(String downloadUrl) {
+ return downloads.get(downloadUrl);
+ }
+
+ /**
+ * Checks if feedfile with the given download url is in the downloads list
+ */
+ public boolean isDownloadingFile(String downloadUrl) {
+ return downloads.get(downloadUrl) != null;
+ }
+
+ public boolean hasNoDownloads() {
+ return downloads.isEmpty();
+ }
+
+ /**
+ * Remove an object from the downloads-list of the requester.
+ */
+ public void removeDownload(DownloadRequest r) {
+ if (downloads.remove(r.getSource()) == null) {
+ Log.e(TAG,
+ "Could not remove object with url " + r.getSource());
+ }
+ }
+
+ /**
+ * Get the number of uncompleted Downloads
+ */
+ public int getNumberOfDownloads() {
+ return downloads.size();
+ }
+
+ public String getFeedfilePath(Context context)
+ throws DownloadRequestException {
+ return getExternalFilesDirOrThrowException(context, FEED_DOWNLOADPATH)
+ .toString() + "/";
+ }
+
+ public String getFeedfileName(Feed feed) {
+ String filename = feed.getDownload_url();
+ if (feed.getTitle() != null && !feed.getTitle().isEmpty()) {
+ filename = feed.getTitle();
+ }
+ return "feed-" + FileNameGenerator.generateFileName(filename);
+ }
+
+ public String getImagefilePath(Context context)
+ throws DownloadRequestException {
+ return getExternalFilesDirOrThrowException(context, IMAGE_DOWNLOADPATH)
+ .toString() + "/";
+ }
+
+ public String getImagefileName(FeedImage image) {
+ String filename = image.getDownload_url();
+ if (image.getFeed() != null && image.getFeed().getTitle() != null) {
+ filename = image.getFeed().getTitle();
+ }
+ return "image-" + FileNameGenerator.generateFileName(filename);
+ }
+
+ public String getMediafilePath(Context context, FeedMedia media)
+ throws DownloadRequestException {
+ File externalStorage = getExternalFilesDirOrThrowException(
+ context,
+ MEDIA_DOWNLOADPATH
+ + FileNameGenerator.generateFileName(media.getItem()
+ .getFeed().getTitle()) + "/");
+ return externalStorage.toString();
+ }
+
+ private File getExternalFilesDirOrThrowException(Context context,
+ String type) throws DownloadRequestException {
+ File result = UserPreferences.getDataFolder(context, type);
+ if (result == null) {
+ throw new DownloadRequestException(
+ "Failed to access external storage");
+ }
+ return result;
+ }
+
+ public String getMediafilename(FeedMedia media) {
+ return URLUtil.guessFileName(media.getDownload_url(), null,
+ media.getMime_type());
+ }
}
diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
index 1aa8c93d4..14ef07c34 100644
--- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java
+++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
@@ -201,6 +201,13 @@ public class PodDBAdapter {
TABLE_NAME_FEED_ITEMS + "." + KEY_HAS_CHAPTERS,
TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER };
+ /** Contains SEL_FI_SMALL as comma-separated list. Useful for raw queries. */
+ private static final String SEL_FI_SMALL_STR;
+ static {
+ String selFiSmall = Arrays.toString(SEL_FI_SMALL);
+ SEL_FI_SMALL_STR = selFiSmall.substring(1, selFiSmall.length() - 1);
+ }
+
// column indices for SEL_FI_SMALL
public static final int IDX_FI_SMALL_ID = 0;
@@ -601,7 +608,7 @@ public class PodDBAdapter {
public final Cursor getAllFeedsCursor() {
open();
Cursor c = db.query(TABLE_NAME_FEEDS, null, null, null, null, null,
- null);
+ KEY_TITLE + " ASC");
return c;
}
@@ -692,9 +699,8 @@ public class PodDBAdapter {
*/
public final Cursor getQueueCursor() {
open();
- String selFiSmall = Arrays.toString(SEL_FI_SMALL);
Object[] args = (Object[]) new String[] {
- selFiSmall.substring(1, selFiSmall.length() - 1) + "," + TABLE_NAME_QUEUE + "." + KEY_ID,
+ SEL_FI_SMALL_STR + "," + TABLE_NAME_QUEUE + "." + KEY_ID,
TABLE_NAME_FEED_ITEMS, TABLE_NAME_QUEUE,
TABLE_NAME_FEED_ITEMS + "." + KEY_ID,
TABLE_NAME_QUEUE + "." + KEY_FEEDITEM,
@@ -738,12 +744,12 @@ public class PodDBAdapter {
public Cursor getDownloadedItemsCursor() {
open();
- Cursor c = db.rawQuery("SELECT ? FROM " + TABLE_NAME_FEED_ITEMS
- + "FULL JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_ID + " WHERE "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0",
- SEL_FI_SMALL);
+ final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
+ + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
+ + TABLE_NAME_FEED_MEDIA + "." + KEY_ID + " WHERE "
+ + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0";
+ Cursor c = db.rawQuery(query, null);
return c;
}
@@ -768,7 +774,11 @@ public class PodDBAdapter {
return c;
}
- public final Cursor getFeedMediaCursor(String... mediaIds) {
+ public final Cursor getSingleFeedMediaCursor(long id) {
+ return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID + "=?", new String[] {Long.toString(id)}, null, null, null);
+ }
+
+ public final Cursor getFeedMediaCursorByItemID(String... mediaIds) {
int length = mediaIds.length;
if (length > IN_OPERATOR_MAXIMUM) {
Log.w(TAG, "Length of id array is larger than "
@@ -837,11 +847,14 @@ public class PodDBAdapter {
}
public final int getNumberOfDownloadedEpisodes() {
+ final String query = "SELECT COUNT(DISTINCT " + KEY_ID + ") AS count FROM " + TABLE_NAME_FEED_MEDIA +
+ " WHERE " + KEY_DOWNLOADED + " > 0";
- Cursor c = db.rawQuery(
- "SELECT COUNT(DISTINCT ?) AS count FROM ? WHERE ?>0",
- new String[] { KEY_ID, TABLE_NAME_FEED_MEDIA, KEY_DOWNLOADED });
- final int result = c.getInt(0);
+ Cursor c = db.rawQuery(query, null);
+ int result = 0;
+ if (c.moveToFirst()) {
+ result = c.getInt(0);
+ }
c.close();
return result;
}