summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/de/danoeh/antennapod/feed/Feed.java2
-rw-r--r--src/de/danoeh/antennapod/storage/DBReader.java61
-rw-r--r--src/de/danoeh/antennapod/storage/DBWriter.java402
-rw-r--r--src/de/danoeh/antennapod/storage/PodDBAdapter.java49
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);
+
}
/**