Implemented refresh, auto-download, auto-cleanup methods
This commit is contained in:
parent
a704a33e2b
commit
c6545a5643
|
@ -48,6 +48,26 @@ public final class DBReader {
|
||||||
return feeds;
|
return feeds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<Feed> getExpiredFeedsList(final Context context, final long expirationTime) {
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime));
|
||||||
|
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
adapter.open();
|
||||||
|
|
||||||
|
Cursor feedlistCursor = adapter.getExpiredFeedsCursor(expirationTime);
|
||||||
|
List<Feed> feeds = new ArrayList<Feed>(feedlistCursor.getCount());
|
||||||
|
|
||||||
|
if (feedlistCursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
Feed feed = extractFeedFromCursorRow(adapter, feedlistCursor);
|
||||||
|
feeds.add(feed);
|
||||||
|
} while (feedlistCursor.moveToNext());
|
||||||
|
}
|
||||||
|
feedlistCursor.close();
|
||||||
|
return feeds;
|
||||||
|
}
|
||||||
|
|
||||||
public static void loadFeedDataOfFeedItemlist(Context context,
|
public static void loadFeedDataOfFeedItemlist(Context context,
|
||||||
List<FeedItem> items) {
|
List<FeedItem> items) {
|
||||||
List<Feed> feeds = getFeedList(context);
|
List<Feed> feeds = getFeedList(context);
|
||||||
|
@ -272,6 +292,25 @@ public final class DBReader {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<FeedItem> getDownloadedItems(Context context) {
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Extracting downloaded items");
|
||||||
|
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
adapter.open();
|
||||||
|
|
||||||
|
Cursor itemlistCursor = adapter.getDownloadedItemsCursor();
|
||||||
|
List<FeedItem> items = extractItemlistFromCursor(adapter,
|
||||||
|
itemlistCursor);
|
||||||
|
itemlistCursor.close();
|
||||||
|
loadFeedDataOfFeedItemlist(context, items);
|
||||||
|
Collections.sort(items, new FeedItemPubdateComparator());
|
||||||
|
|
||||||
|
adapter.close();
|
||||||
|
return items;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static List<FeedItem> getUnreadItemsList(Context context) {
|
public static List<FeedItem> getUnreadItemsList(Context context) {
|
||||||
if (AppConfig.DEBUG)
|
if (AppConfig.DEBUG)
|
||||||
Log.d(TAG, "Extracting unread items list");
|
Log.d(TAG, "Extracting unread items list");
|
||||||
|
@ -411,6 +450,14 @@ public final class DBReader {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getNumberOfDownloadedEpisodes(final Context context) {
|
||||||
|
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||||
|
adapter.open();
|
||||||
|
final int result = adapter.getNumberOfDownloadedEpisodes();
|
||||||
|
adapter.close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches the DB for a FeedImage of the given id.
|
* Searches the DB for a FeedImage of the given id.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,16 +1,28 @@
|
||||||
package de.danoeh.antennapod.storage;
|
package de.danoeh.antennapod.storage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import de.danoeh.antennapod.AppConfig;
|
import de.danoeh.antennapod.AppConfig;
|
||||||
|
import de.danoeh.antennapod.feed.EventDistributor;
|
||||||
import de.danoeh.antennapod.feed.Feed;
|
import de.danoeh.antennapod.feed.Feed;
|
||||||
|
import de.danoeh.antennapod.feed.FeedImage;
|
||||||
import de.danoeh.antennapod.feed.FeedItem;
|
import de.danoeh.antennapod.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.feed.FeedMedia;
|
import de.danoeh.antennapod.feed.FeedMedia;
|
||||||
|
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.service.PlaybackService;
|
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.exception.MediaFileNotFoundException;
|
import de.danoeh.antennapod.util.exception.MediaFileNotFoundException;
|
||||||
|
|
||||||
public final class DBTasks {
|
public final class DBTasks {
|
||||||
|
@ -55,47 +67,308 @@ public final class DBTasks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void refreshAllFeeds(final Context context) {
|
private static ReentrantLock refreshAllFeedsLock = new ReentrantLock();
|
||||||
|
|
||||||
|
public static void refreshAllFeeds(final Context context,
|
||||||
|
final List<Feed> feeds) {
|
||||||
|
if (refreshAllFeedsLock.tryLock()) {
|
||||||
|
new Thread() {
|
||||||
|
public void run() {
|
||||||
|
refreshFeeds(context, feeds);
|
||||||
|
refreshAllFeedsLock.unlock();
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
} else {
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG,
|
||||||
|
"Ignoring request to refresh all feeds: Refresh lock is locked");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshExpiredFeeds(final Context context) {
|
public void refreshExpiredFeeds(final Context context) {
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Refreshing expired feeds");
|
||||||
|
|
||||||
|
new Thread() {
|
||||||
|
public void run() {
|
||||||
|
long millis = UserPreferences.getUpdateInterval();
|
||||||
|
|
||||||
|
if (millis > 0) {
|
||||||
|
long now = Calendar.getInstance().getTime().getTime();
|
||||||
|
|
||||||
|
// Allow a 10 minute window
|
||||||
|
millis -= 10 * 60 * 1000;
|
||||||
|
List<Feed> feedList = DBReader.getExpiredFeedsList(context,
|
||||||
|
now - millis);
|
||||||
|
if (feedList.size() > 0) {
|
||||||
|
refreshFeeds(context, feedList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void refreshFeeds(final Context context,
|
||||||
|
final List<Feed> feedList) {
|
||||||
|
|
||||||
|
for (Feed feed : feedList) {
|
||||||
|
try {
|
||||||
|
refreshFeed(context, feed);
|
||||||
|
} catch (DownloadRequestException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
DBWriter.addDownloadStatus(
|
||||||
|
context,
|
||||||
|
new DownloadStatus(feed, feed
|
||||||
|
.getHumanReadableIdentifier(),
|
||||||
|
DownloadError.ERROR_REQUEST_ERROR, false, e
|
||||||
|
.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates a specific feed. */
|
||||||
|
private static void refreshFeed(Context context, Feed feed)
|
||||||
|
throws DownloadRequestException {
|
||||||
|
DownloadRequester.getInstance().downloadFeed(context,
|
||||||
|
new Feed(feed.getDownload_url(), new Date(), feed.getTitle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyInvalidImageFile(final Context context,
|
public static void notifyInvalidImageFile(final Context context,
|
||||||
final long imageId) {
|
final FeedImage image) {
|
||||||
|
Log.i(TAG,
|
||||||
|
"The feedmanager was notified about an invalid image download. It will now try to redownload the image file");
|
||||||
|
try {
|
||||||
|
DownloadRequester.getInstance().downloadImage(context, image);
|
||||||
|
} catch (DownloadRequestException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Log.w(TAG, "Failed to download invalid feed image");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyMissingFeedMediaFile(final Context context,
|
public static void notifyMissingFeedMediaFile(final Context context,
|
||||||
final FeedMedia media) {
|
final FeedMedia media) {
|
||||||
|
Log.i(TAG,
|
||||||
|
"The feedmanager was notified about a missing episode. It will update its database now.");
|
||||||
|
media.setDownloaded(false);
|
||||||
|
media.setFile_url(null);
|
||||||
|
DBWriter.setFeedMedia(context, media);
|
||||||
|
EventDistributor.getInstance().sendFeedUpdateBroadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void downloadAllItemsInQueue(final Context context) {
|
public static void downloadAllItemsInQueue(final Context context) {
|
||||||
|
new Thread() {
|
||||||
|
public void run() {
|
||||||
|
List<FeedItem> queue = DBReader.getQueue(context);
|
||||||
|
if (!queue.isEmpty()) {
|
||||||
|
try {
|
||||||
|
downloadFeedItems(context,
|
||||||
|
queue.toArray(new FeedItem[queue.size()]));
|
||||||
|
} catch (DownloadRequestException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void refreshFeed(final Context context, final long feedId) {
|
public static void downloadFeedItems(final Context context,
|
||||||
|
FeedItem... items) throws DownloadRequestException {
|
||||||
|
downloadFeedItems(true, context, items);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void downloadFeedItem(final Context context, long... itemIds) {
|
private static void downloadFeedItems(boolean performAutoCleanup,
|
||||||
}
|
final Context context, final FeedItem... items)
|
||||||
|
|
||||||
static void downloadFeedItem(boolean performAutoCleanup,
|
|
||||||
final Context context, final long... itemIds)
|
|
||||||
throws DownloadRequestException {
|
throws DownloadRequestException {
|
||||||
|
final DownloadRequester requester = DownloadRequester.getInstance();
|
||||||
|
|
||||||
|
if (performAutoCleanup) {
|
||||||
|
new Thread() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
performAutoCleanup(context,
|
||||||
|
getPerformAutoCleanupArgs(context, items.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
|
for (FeedItem item : items) {
|
||||||
|
if (item.getMedia() != null
|
||||||
|
&& !requester.isDownloadingFile(item.getMedia())
|
||||||
|
&& !item.getMedia().isDownloaded()) {
|
||||||
|
if (items.length > 1) {
|
||||||
|
try {
|
||||||
|
requester.downloadMedia(context, item.getMedia());
|
||||||
|
} catch (DownloadRequestException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
DBWriter.addDownloadStatus(context,
|
||||||
|
new DownloadStatus(item.getMedia(), item
|
||||||
|
.getMedia()
|
||||||
|
.getHumanReadableIdentifier(),
|
||||||
|
DownloadError.ERROR_REQUEST_ERROR,
|
||||||
|
false, e.getMessage()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requester.downloadMedia(context, item.getMedia());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void autodownloadUndownloadedItems(Context context) {
|
private static int getNumberOfUndownloadedEpisodes(
|
||||||
|
final List<FeedItem> queue, final List<FeedItem> unreadItems) {
|
||||||
|
int counter = 0;
|
||||||
|
for (FeedItem item : queue) {
|
||||||
|
if (item.hasMedia() && !item.getMedia().isDownloaded()
|
||||||
|
&& !item.getMedia().isPlaying()) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (FeedItem item : unreadItems) {
|
||||||
|
if (item.hasMedia() && !item.getMedia().isDownloaded()) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getPerformAutoCleanupArgs(final int episodeNumber) {
|
public static void autodownloadUndownloadedItems(final Context context) {
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Performing auto-dl of undownloaded episodes");
|
||||||
|
if (NetworkUtils.autodownloadNetworkAvailable(context)
|
||||||
|
&& UserPreferences.isEnableAutodownload()) {
|
||||||
|
final List<FeedItem> queue = DBReader.getQueue(context);
|
||||||
|
final List<FeedItem> unreadItems = DBReader
|
||||||
|
.getUnreadItemsList(context);
|
||||||
|
|
||||||
|
int undownloadedEpisodes = getNumberOfUndownloadedEpisodes(queue,
|
||||||
|
unreadItems);
|
||||||
|
int downloadedEpisodes = DBReader
|
||||||
|
.getNumberOfDownloadedEpisodes(context);
|
||||||
|
int deletedEpisodes = performAutoCleanup(context,
|
||||||
|
getPerformAutoCleanupArgs(context, undownloadedEpisodes));
|
||||||
|
int episodeSpaceLeft = undownloadedEpisodes;
|
||||||
|
boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences
|
||||||
|
.getEpisodeCacheSizeUnlimited();
|
||||||
|
|
||||||
|
if (!cacheIsUnlimited
|
||||||
|
&& UserPreferences.getEpisodeCacheSize() < downloadedEpisodes
|
||||||
|
+ undownloadedEpisodes) {
|
||||||
|
episodeSpaceLeft = UserPreferences.getEpisodeCacheSize()
|
||||||
|
- (downloadedEpisodes - deletedEpisodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FeedItem> itemsToDownload = new ArrayList<FeedItem>();
|
||||||
|
if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
|
||||||
|
for (int i = 0; i < queue.size(); i++) { // ignore playing item
|
||||||
|
FeedItem item = queue.get(i);
|
||||||
|
if (item.hasMedia() && !item.getMedia().isDownloaded()
|
||||||
|
&& !item.getMedia().isPlaying()) {
|
||||||
|
itemsToDownload.add(item);
|
||||||
|
episodeSpaceLeft--;
|
||||||
|
undownloadedEpisodes--;
|
||||||
|
if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
|
||||||
|
for (FeedItem item : unreadItems) {
|
||||||
|
if (item.hasMedia() && !item.getMedia().isDownloaded()) {
|
||||||
|
itemsToDownload.add(item);
|
||||||
|
episodeSpaceLeft--;
|
||||||
|
undownloadedEpisodes--;
|
||||||
|
if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Enqueueing " + itemsToDownload.size()
|
||||||
|
+ " items for download");
|
||||||
|
|
||||||
|
try {
|
||||||
|
downloadFeedItems(false, context,
|
||||||
|
itemsToDownload.toArray(new FeedItem[itemsToDownload
|
||||||
|
.size()]));
|
||||||
|
} catch (DownloadRequestException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getPerformAutoCleanupArgs(Context context,
|
||||||
|
final int episodeNumber) {
|
||||||
|
if (episodeNumber >= 0
|
||||||
|
&& UserPreferences.getEpisodeCacheSize() != UserPreferences
|
||||||
|
.getEpisodeCacheSizeUnlimited()) {
|
||||||
|
int downloadedEpisodes = DBReader
|
||||||
|
.getNumberOfDownloadedEpisodes(context);
|
||||||
|
if (downloadedEpisodes + episodeNumber >= UserPreferences
|
||||||
|
.getEpisodeCacheSize()) {
|
||||||
|
|
||||||
|
return downloadedEpisodes + episodeNumber
|
||||||
|
- UserPreferences.getEpisodeCacheSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void performAutoCleanup(final Context context) {
|
public static void performAutoCleanup(final Context context) {
|
||||||
|
performAutoCleanup(context, getPerformAutoCleanupArgs(context, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int performAutoCleanup(final Context context,
|
private static int performAutoCleanup(final Context context,
|
||||||
final int episodeNumber) {
|
final int episodeNumber) {
|
||||||
return 0;
|
List<FeedItem> candidates = DBReader.getDownloadedItems(context);
|
||||||
|
List<FeedItem> queue = DBReader.getQueue(context);
|
||||||
|
List<FeedItem> delete;
|
||||||
|
for (FeedItem item : candidates) {
|
||||||
|
if (item.hasMedia() && item.getMedia().isDownloaded()
|
||||||
|
&& !queue.contains(item) && item.isRead()) {
|
||||||
|
candidates.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(candidates, new Comparator<FeedItem>() {
|
||||||
|
@Override
|
||||||
|
public int compare(FeedItem lhs, FeedItem rhs) {
|
||||||
|
Date l = lhs.getMedia().getPlaybackCompletionDate();
|
||||||
|
Date r = rhs.getMedia().getPlaybackCompletionDate();
|
||||||
|
|
||||||
|
if (l == null) {
|
||||||
|
l = new Date(0);
|
||||||
|
}
|
||||||
|
if (r == null) {
|
||||||
|
r = new Date(0);
|
||||||
|
}
|
||||||
|
return l.compareTo(r);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (candidates.size() > episodeNumber) {
|
||||||
|
delete = candidates.subList(0, episodeNumber);
|
||||||
|
} else {
|
||||||
|
delete = candidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FeedItem item : delete) {
|
||||||
|
DBWriter.deleteFeedMediaOfItem(context, item.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
int counter = delete.size();
|
||||||
|
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, String.format(
|
||||||
|
"Auto-delete deleted %d episodes (%d requested)", counter,
|
||||||
|
episodeNumber));
|
||||||
|
|
||||||
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void enqueueAllNewItems(final Context context) {
|
public static void enqueueAllNewItems(final Context context) {
|
||||||
|
@ -144,8 +417,8 @@ public final class DBTasks {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static synchronized Feed updateFeed(final Context context,
|
||||||
public static synchronized Feed updateFeed(final Context context, final Feed newFeed) {
|
final Feed newFeed) {
|
||||||
// Look up feed in the feedslist
|
// Look up feed in the feedslist
|
||||||
final Feed savedFeed = searchFeedByIdentifyingValue(context,
|
final Feed savedFeed = searchFeedByIdentifyingValue(context,
|
||||||
newFeed.getIdentifyingValue());
|
newFeed.getIdentifyingValue());
|
||||||
|
|
|
@ -506,7 +506,7 @@ public class DBWriter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setFeedMedia(final Context context,
|
static void setFeedMedia(final Context context,
|
||||||
final FeedMedia media) {
|
final FeedMedia media) {
|
||||||
dbExec.submit(new Runnable() {
|
dbExec.submit(new Runnable() {
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.database.DatabaseUtils;
|
||||||
import android.database.MergeCursor;
|
import android.database.MergeCursor;
|
||||||
import android.database.SQLException;
|
import android.database.SQLException;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteStatement;
|
||||||
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -574,6 +575,14 @@ public class PodDBAdapter {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final Cursor getExpiredFeedsCursor(long expirationTime) {
|
||||||
|
open();
|
||||||
|
Cursor c = db.query(TABLE_NAME_FEEDS, null, "?<?", new String[] {
|
||||||
|
KEY_LASTUPDATE, Long.toString(expirationTime) }, null, null,
|
||||||
|
null);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a cursor with all FeedItems of a Feed. Uses SEL_FI_SMALL
|
* Returns a cursor with all FeedItems of a Feed. Uses SEL_FI_SMALL
|
||||||
*
|
*
|
||||||
|
@ -680,6 +689,17 @@ 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);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a cursor which contains feed media objects with a playback
|
* Returns a cursor which contains feed media objects with a playback
|
||||||
* completion date in descending order.
|
* completion date in descending order.
|
||||||
|
@ -766,6 +786,16 @@ public class PodDBAdapter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final int getNumberOfDownloadedEpisodes() {
|
||||||
|
|
||||||
|
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);
|
||||||
|
c.close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses DatabaseUtils to escape a search query and removes ' at the
|
* Uses DatabaseUtils to escape a search query and removes ' at the
|
||||||
* beginning and the end of the string returned by the escape method.
|
* beginning and the end of the string returned by the escape method.
|
||||||
|
|
Loading…
Reference in New Issue