diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/de/danoeh/antennapod/feed/Feed.java | 2 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/storage/DBReader.java | 61 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/storage/DBWriter.java | 402 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/storage/PodDBAdapter.java | 49 |
4 files changed, 482 insertions, 32 deletions
diff --git a/src/de/danoeh/antennapod/feed/Feed.java b/src/de/danoeh/antennapod/feed/Feed.java index 27375f3ce..42221fc31 100644 --- a/src/de/danoeh/antennapod/feed/Feed.java +++ b/src/de/danoeh/antennapod/feed/Feed.java @@ -284,7 +284,7 @@ public class Feed extends FeedFile { this.image = image; } - List<FeedItem> getItems() { + public List<FeedItem> getItems() { return items; } diff --git a/src/de/danoeh/antennapod/storage/DBReader.java b/src/de/danoeh/antennapod/storage/DBReader.java index 3550aa6a2..97c52d749 100644 --- a/src/de/danoeh/antennapod/storage/DBReader.java +++ b/src/de/danoeh/antennapod/storage/DBReader.java @@ -246,25 +246,29 @@ public final class DBReader { } return null; } - - public static List<FeedItem> getQueue(Context context) { + + static List<FeedItem> getQueue(Context context, PodDBAdapter adapter) { if (AppConfig.DEBUG) Log.d(TAG, "Extracting queue"); - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - Cursor itemlistCursor = adapter.getQueueCursor(); List<FeedItem> items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(context, items); + Collections.sort(items, new FeedItemPubdateComparator()); - adapter.close(); + return items; + } - Collections.sort(items, new FeedItemPubdateComparator()); + public static List<FeedItem> getQueue(Context context) { + if (AppConfig.DEBUG) + Log.d(TAG, "Extracting queue"); + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + List<FeedItem> items = getQueue(context, adapter); + adapter.close(); return items; } @@ -287,8 +291,26 @@ public final class DBReader { return items; } - public static List<FeedItem> getPlaybackHistory() { - return null; + public static List<FeedItem> getPlaybackHistory(final Context context) { + if (AppConfig.DEBUG) + Log.d(TAG, "Loading playback history"); + final int PLAYBACK_HISTORY_SIZE = 50; + + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + + Cursor mediaCursor = adapter.getCompletedMediaCursor(PLAYBACK_HISTORY_SIZE); + String[] itemIds = new String[mediaCursor.getCount()]; + for (int i = 0; i < itemIds.length; i++) { + itemIds[i] = Long.toString(mediaCursor.getLong(PodDBAdapter.KEY_FEEDITEM_INDEX)); + } + mediaCursor.close(); + Cursor itemCursor = adapter.getFeedItemCursor(itemIds); + List<FeedItem> items = extractItemlistFromCursor(adapter, itemCursor); + itemCursor.close(); + + adapter.close(); + return items; } public static List<DownloadStatus> getDownloadLog(Context context) { @@ -345,21 +367,30 @@ public final class DBReader { adapter.close(); return feed; } - - public FeedItem getFeedItem(final Context context, final long itemId) { + + static FeedItem getFeedItem(final Context context, final long itemId, PodDBAdapter adapter) { if (AppConfig.DEBUG) Log.d(TAG, "Loading feeditem with id " + itemId); FeedItem item = null; - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - Cursor itemCursor = adapter.getFeedItemCursor(itemId); + Cursor itemCursor = adapter.getFeedItemCursor(Long.toString(itemId)); if (itemCursor.moveToFirst()) { List<FeedItem> list = extractItemlistFromCursor(adapter, itemCursor); if (list.size() > 0) { item = list.get(0); } } + return item; + + } + + public static FeedItem getFeedItem(final Context context, final long itemId) { + if (AppConfig.DEBUG) + Log.d(TAG, "Loading feeditem with id " + itemId); + + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + FeedItem item = getFeedItem(context, itemId, adapter); adapter.close(); return item; diff --git a/src/de/danoeh/antennapod/storage/DBWriter.java b/src/de/danoeh/antennapod/storage/DBWriter.java index 76a1ad98d..996c3e028 100644 --- a/src/de/danoeh/antennapod/storage/DBWriter.java +++ b/src/de/danoeh/antennapod/storage/DBWriter.java @@ -1,63 +1,441 @@ package de.danoeh.antennapod.storage; +import java.io.File; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.Log; +import de.danoeh.antennapod.AppConfig; +import de.danoeh.antennapod.asynctask.DownloadStatus; +import de.danoeh.antennapod.feed.EventDistributor; +import de.danoeh.antennapod.feed.Feed; +import de.danoeh.antennapod.feed.FeedItem; +import de.danoeh.antennapod.feed.FeedMedia; +import de.danoeh.antennapod.preferences.PlaybackPreferences; +import de.danoeh.antennapod.service.PlaybackService; public class DBWriter { private static final String TAG = "DBWriter"; - + + private static final ExecutorService dbExec; + static { + dbExec = Executors.newSingleThreadExecutor(new ThreadFactory() { + + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setPriority(Thread.MIN_PRIORITY); + return t; + } + }); + } + private DBWriter() { } - public static boolean deleteFeedMedia(final Context context, - final long mediaId) { - return false; + public static void deleteFeedMediaOfItem(final Context context, + final long itemId) { + dbExec.submit(new Runnable() { + @Override + public void run() { + final FeedItem item = DBReader.getFeedItem(context, itemId); + if (item != null && item.hasMedia()) { + final FeedMedia media = item.getMedia(); + boolean result = false; + if (media.isDownloaded()) { + // delete downloaded media file + File mediaFile = new File(media.getFile_url()); + if (mediaFile.exists()) { + result = mediaFile.delete(); + } + media.setDownloaded(false); + media.setFile_url(null); + setFeedMedia(context, media); + + // If media is currently being played, change playback + // type to 'stream' and shutdown playback service + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA) { + if (media.getId() == PlaybackPreferences + .getCurrentlyPlayingFeedMediaId()) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean( + PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM, + true); + editor.commit(); + } + if (PlaybackPreferences + .getCurrentlyPlayingFeedMediaId() == media + .getId()) { + context.sendBroadcast(new Intent( + PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE)); + } + } + } + if (AppConfig.DEBUG) + Log.d(TAG, "Deleting File. Result: " + result); + } + } + }); } public static void deleteFeed(final Context context, final long feedId) { + dbExec.submit(new Runnable() { + @Override + public void run() { + DownloadRequester requester = DownloadRequester.getInstance(); + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context + .getApplicationContext()); + final Feed feed = DBReader.getFeed(context, feedId); + if (feed != null) { + if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA + && PlaybackPreferences.getLastPlayedFeedId() == feed + .getId()) { + context.sendBroadcast(new Intent( + PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE)); + SharedPreferences.Editor editor = prefs.edit(); + editor.putLong( + PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID, + -1); + editor.commit(); + } + + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + // delete image file + if (feed.getImage() != null) { + if (feed.getImage().isDownloaded() + && feed.getImage().getFile_url() != null) { + File imageFile = new File(feed.getImage() + .getFile_url()); + imageFile.delete(); + } else if (requester.isDownloadingFile(feed.getImage())) { + requester.cancelDownload(context, feed.getImage()); + } + } + // delete stored media files and mark them as read + List<FeedItem> queue = DBReader.getQueue(context); + boolean queueWasModified = false; + if (feed.getItems() == null) { + DBReader.getFeedItemList(context, feed); + } + for (FeedItem item : feed.getItems()) { + queueWasModified |= queue.remove(item); + if (item.getMedia() != null + && item.getMedia().isDownloaded()) { + File mediaFile = new File(item.getMedia() + .getFile_url()); + mediaFile.delete(); + } else if (item.getMedia() != null + && requester.isDownloadingFile(item.getMedia())) { + requester.cancelDownload(context, item.getMedia()); + } + } + if (queueWasModified) { + adapter.setQueue(queue); + } + adapter.removeFeed(feed); + adapter.close(); + EventDistributor.getInstance().sendFeedUpdateBroadcast(); + } + } + }); } public static void clearPlaybackHistory(final Context context) { + dbExec.submit(new Runnable() { + @Override + public void run() { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.clearPlaybackHistory(); + adapter.close(); + EventDistributor.getInstance() + .sendPlaybackHistoryUpdateBroadcast(); + } + }); } public static void addItemToPlaybackHistory(final Context context, - long itemId) { + final FeedItem item) { + if (item.hasMedia() + && item.getMedia().getPlaybackCompletionDate() != null) { + if (AppConfig.DEBUG) + Log.d(TAG, "Adding new item to playback history"); + EventDistributor.getInstance().sendPlaybackHistoryUpdateBroadcast(); + } } - private static void removeItemFromPlaybackHistory(final Context context, - long itemId) { - + private static void cleanupDownloadLog(final PodDBAdapter adapter) { + final int DOWNLOAD_LOG_SIZE = 50; + final long logSize = adapter.getDownloadLogSize(); + if (logSize > DOWNLOAD_LOG_SIZE) { + if (AppConfig.DEBUG) + Log.d(TAG, "Cleaning up download log"); + adapter.removeDownloadLogItems(logSize - DOWNLOAD_LOG_SIZE); + } } public static void addDownloadStatus(final Context context, - final long statusId) { + final DownloadStatus status) { + dbExec.submit(new Runnable() { + + @Override + public void run() { + + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + + adapter.setDownloadStatus(status); + cleanupDownloadLog(adapter); + adapter.close(); + EventDistributor.getInstance().sendDownloadLogUpdateBroadcast(); + } + }); } public static void addQueueItemAt(final Context context, final long itemId, final int index, final boolean performAutoDownload) { + dbExec.submit(new Runnable() { + + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + final List<FeedItem> queue = DBReader + .getQueue(context, adapter); + FeedItem item = null; + + if (queue != null) { + boolean queueModified = false; + boolean unreadItemsModfied = false; + + if (!itemListContains(queue, itemId)) { + item = DBReader.getFeedItem(context, itemId); + if (item != null) { + queue.add(index, item); + queueModified = true; + if (!item.isRead()) { + item.setRead(true); + unreadItemsModfied = true; + } + } + } + if (queueModified) { + adapter.setQueue(queue); + EventDistributor.getInstance() + .sendQueueUpdateBroadcast(); + } + if (unreadItemsModfied && item != null) { + adapter.setSingleFeedItem(item); + EventDistributor.getInstance() + .sendUnreadItemsUpdateBroadcast(); + } + } + adapter.close(); + if (performAutoDownload) { + + new Thread() { + @Override + public void run() { + DBTasks.autodownloadUndownloadedItems(context); + + } + }.start(); + } + + } + }); } public static void addQueueItem(final Context context, final long... itemIds) { + if (itemIds.length > 0) { + dbExec.submit(new Runnable() { + + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + final List<FeedItem> queue = DBReader.getQueue(context, + adapter); + + if (queue != null) { + boolean queueModified = false; + boolean unreadItemsModfied = false; + List<FeedItem> itemsToSave = new LinkedList<FeedItem>(); + for (int i = 0; i < itemIds.length; i++) { + if (!itemListContains(queue, itemIds[i])) { + final FeedItem item = DBReader.getFeedItem( + context, itemIds[i]); + + if (item != null) { + queue.add(item); + queueModified = true; + if (!item.isRead()) { + item.setRead(true); + itemsToSave.add(item); + unreadItemsModfied = true; + } + } + } + } + if (queueModified) { + adapter.setQueue(queue); + EventDistributor.getInstance() + .sendQueueUpdateBroadcast(); + } + if (unreadItemsModfied) { + adapter.setFeedItemlist(itemsToSave); + EventDistributor.getInstance() + .sendUnreadItemsUpdateBroadcast(); + } + } + adapter.close(); + new Thread() { + @Override + public void run() { + DBTasks.autodownloadUndownloadedItems(context); + + } + }.start(); + } + }); + } } public static void clearQueue(final Context context) { + dbExec.submit(new Runnable() { + + @Override + public void run() { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.clearQueue(); + adapter.close(); + + EventDistributor.getInstance().sendQueueUpdateBroadcast(); + } + }); } public static void removeQueueItem(final Context context, final long itemId, final boolean performAutoDownload) { + dbExec.submit(new Runnable() { + + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + final List<FeedItem> queue = DBReader + .getQueue(context, adapter); + FeedItem item = null; + + if (queue != null) { + boolean queueModified = false; + + if (itemListContains(queue, itemId)) { + item = DBReader.getFeedItem(context, itemId); + if (item != null) { + queue.remove(item); + queueModified = true; + } + } + if (queueModified) { + adapter.setQueue(queue); + EventDistributor.getInstance() + .sendQueueUpdateBroadcast(); + } + } + adapter.close(); + if (performAutoDownload) { + + new Thread() { + @Override + public void run() { + DBTasks.autodownloadUndownloadedItems(context); + + } + }.start(); + } + } + }); } - public void moveQueueItem(final Context context, int from, int to, - boolean broadcastUpdate) { + public void moveQueueItem(final Context context, final int from, + final int to, final boolean broadcastUpdate) { + dbExec.submit(new Runnable() { + + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + final List<FeedItem> queue = DBReader + .getQueue(context, adapter); + + if (queue != null) { + if (from >= 0 && from < queue.size() && to >= 0 + && to < queue.size()) { + final FeedItem item = queue.remove(from); + queue.add(to, item); + adapter.setQueue(queue); + if (broadcastUpdate) { + EventDistributor.getInstance() + .sendQueueUpdateBroadcast(); + } + + } + } + adapter.close(); + } + }); } - void addNewFeed(final Context context, final long feedId) { + void addNewFeed(final Context context, final Feed feed) { + dbExec.submit(new Runnable() { + + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setCompleteFeed(feed); + adapter.close(); + + EventDistributor.getInstance().sendFeedUpdateBroadcast(); + } + }); + } + private static void setFeedMedia(final Context context, + final FeedMedia media) { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setMedia(media); + adapter.close(); + + } + + private static boolean itemListContains(List<FeedItem> items, long itemId) { + for (FeedItem item : items) { + if (item.getId() == itemId) { + return true; + } + } + return false; } } diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java index 5ec5df2c8..ef9b4bfe0 100644 --- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java +++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java @@ -340,6 +340,15 @@ public class PodDBAdapter { db.setTransactionSuccessful(); db.endTransaction(); } + + public void setFeedItemlist(List<FeedItem> items) { + db.beginTransaction(); + for (FeedItem item : items) { + setFeedItem(item); + } + db.setTransactionSuccessful(); + db.endTransaction(); + } public long setSingleFeedItem(FeedItem item) { db.beginTransaction(); @@ -439,6 +448,22 @@ public class PodDBAdapter { return status.getId(); } + public long getDownloadLogSize() { + Cursor result = db.rawQuery("SELECT COUNT(?) AS ? FROM ?", + new String[] { KEY_ID, KEY_ID, TABLE_NAME_DOWNLOAD_LOG }); + long count = result.getLong(KEY_ID_INDEX); + result.close(); + return count; + } + + public void removeDownloadLogItems(long count) { + if (count > 0) { + db.rawQuery("DELETE FROM ? ORDER BY ? ASC LIMIT ?", + new String[] { TABLE_NAME_DOWNLOAD_LOG, + KEY_COMPLETION_DATE, Long.toString(count) }); + } + } + public void setQueue(List<FeedItem> queue) { ContentValues values = new ContentValues(); db.beginTransaction(); @@ -454,6 +479,10 @@ public class PodDBAdapter { db.setTransactionSuccessful(); db.endTransaction(); } + + public void clearQueue() { + db.delete(TABLE_NAME_QUEUE, null, null); + } public void removeFeedMedia(FeedMedia media) { db.delete(TABLE_NAME_FEED_MEDIA, KEY_ID + "=?", @@ -502,6 +531,12 @@ public class PodDBAdapter { new String[] { String.valueOf(remove.getId()) }); } + public void clearPlaybackHistory() { + ContentValues values = new ContentValues(); + values.put(KEY_PLAYBACK_COMPLETION_DATE, 0); + db.update(TABLE_NAME_FEED_MEDIA, values, null, null); + } + /** * Get all Feeds from the Feed Table. * @@ -681,11 +716,17 @@ public class PodDBAdapter { return c; } - public final Cursor getFeedItemCursor(final long id) { + public final Cursor getFeedItemCursor(final String... ids) { + if (ids.length > IN_OPERATOR_MAXIMUM) { + throw new IllegalArgumentException( + "number of IDs must not be larger than " + + IN_OPERATOR_MAXIMUM); + } + open(); - Cursor c = db.query(TABLE_NAME_FEEDS, null, KEY_ID + "=" + id, null, - null, null, null); - return c; + return db.query(TABLE_NAME_FEED_ITEMS, null, KEY_ID + " IN " + + buildInOperator(ids.length), ids, null, null, null); + } /** |