From 2071793e6aa1a106744078fcbcf7c0529ed315c4 Mon Sep 17 00:00:00 2001 From: daniel oeh Date: Fri, 2 Aug 2013 23:54:50 +0200 Subject: Organizing the queue now works, several bugfixes etc. --- .../antennapod/activity/ItemviewActivity.java | 13 +-- .../antennapod/activity/OrganizeQueueActivity.java | 5 +- .../adapter/InternalFeedItemlistAdapter.java | 17 +--- .../antennapod/asynctask/OpmlExportWorker.java | 4 +- src/de/danoeh/antennapod/feed/FeedImage.java | 2 +- .../antennapod/fragment/EpisodesFragment.java | 13 +-- .../antennapod/fragment/ItemlistFragment.java | 23 +++--- .../fragment/PlaybackHistoryFragment.java | 8 +- .../receiver/ConnectivityActionReceiver.java | 3 +- .../antennapod/receiver/FeedUpdateReceiver.java | 3 +- .../service/download/DownloadService.java | 96 ++++++++++------------ src/de/danoeh/antennapod/storage/DBReader.java | 30 +++++-- src/de/danoeh/antennapod/storage/DBTasks.java | 4 +- src/de/danoeh/antennapod/storage/DBWriter.java | 65 +++++++++++---- src/de/danoeh/antennapod/storage/PodDBAdapter.java | 23 +++++- src/de/danoeh/antennapod/util/QueueAccess.java | 89 ++++++++++++++++++++ .../util/comparator/DownloadStatusComparator.java | 2 +- .../util/menuhandler/FeedItemMenuHandler.java | 30 ++++--- .../util/menuhandler/FeedMenuHandler.java | 8 +- .../util/playback/PlaybackController.java | 5 +- 20 files changed, 298 insertions(+), 145 deletions(-) create mode 100644 src/de/danoeh/antennapod/util/QueueAccess.java (limited to 'src/de/danoeh/antennapod') diff --git a/src/de/danoeh/antennapod/activity/ItemviewActivity.java b/src/de/danoeh/antennapod/activity/ItemviewActivity.java index 4568c535a..eb8d71bbe 100644 --- a/src/de/danoeh/antennapod/activity/ItemviewActivity.java +++ b/src/de/danoeh/antennapod/activity/ItemviewActivity.java @@ -22,6 +22,7 @@ import de.danoeh.antennapod.fragment.ItemlistFragment; import de.danoeh.antennapod.preferences.UserPreferences; import de.danoeh.antennapod.storage.DBReader; import de.danoeh.antennapod.storage.DownloadRequestException; +import de.danoeh.antennapod.util.QueueAccess; import de.danoeh.antennapod.util.StorageUtils; import de.danoeh.antennapod.util.menuhandler.FeedItemMenuHandler; @@ -149,13 +150,13 @@ public class ItemviewActivity extends SherlockFragmentActivity { @Override public boolean onPrepareOptionsMenu(final Menu menu) { return FeedItemMenuHandler.onPrepareMenu( - new FeedItemMenuHandler.MenuInterface() { + new FeedItemMenuHandler.MenuInterface() { - @Override - public void setItemVisibility(int id, boolean visible) { - menu.findItem(id).setVisible(visible); - } - }, item, true); + @Override + public void setItemVisibility(int id, boolean visible) { + menu.findItem(id).setVisible(visible); + } + }, item, true, QueueAccess.NotInQueueAccess()); } private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { diff --git a/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java b/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java index f7e55d06f..38f0b5ae6 100644 --- a/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java +++ b/src/de/danoeh/antennapod/activity/OrganizeQueueActivity.java @@ -113,9 +113,10 @@ public class OrganizeQueueActivity extends SherlockListActivity implements @Override public void drop(int from, int to) { - + final FeedItem item = queue.remove(from); + queue.add(to, item); + adapter.notifyDataSetChanged(); DBWriter.moveQueueItem(OrganizeQueueActivity.this, from, to, true); - //adapter.notifyDataSetChanged(); } }; diff --git a/src/de/danoeh/antennapod/adapter/InternalFeedItemlistAdapter.java b/src/de/danoeh/antennapod/adapter/InternalFeedItemlistAdapter.java index e473a6b57..b8bec44c8 100644 --- a/src/de/danoeh/antennapod/adapter/InternalFeedItemlistAdapter.java +++ b/src/de/danoeh/antennapod/adapter/InternalFeedItemlistAdapter.java @@ -156,7 +156,7 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter { } holder.lenSize.setVisibility(View.VISIBLE); - if (isInQueue(item)) { + if (((ItemAccess) itemAccess).isInQueue(item)) { holder.inPlaylist.setVisibility(View.VISIBLE); } else { holder.inPlaylist.setVisibility(View.GONE); @@ -205,19 +205,6 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter { } - private boolean isInQueue(FeedItem item) { - Iterator iter = ((ItemAccess) itemAccess).queueIterator(); - if (iter != null) { - while (iter.hasNext()) { - FeedItem current = iter.next(); - if (current.getId() == item.getId()) { - return true; - } - } - } - return false; - } - static class Holder extends DefaultFeedItemlistAdapter.Holder { TextView feedtitle; ImageView inPlaylist; @@ -239,7 +226,7 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter { } public static interface ItemAccess extends DefaultFeedItemlistAdapter.ItemAccess { - public Iterator queueIterator(); + public boolean isInQueue(FeedItem item); } } diff --git a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java index 978f53ac6..0ae328378 100644 --- a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java +++ b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java @@ -17,6 +17,7 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.opml.OpmlWriter; import de.danoeh.antennapod.preferences.UserPreferences; +import de.danoeh.antennapod.storage.DBReader; /** Writes an OPML file into the export directory in the background. */ public class OpmlExportWorker extends AsyncTask { @@ -51,8 +52,7 @@ public class OpmlExportWorker extends AsyncTask { } try { FileWriter writer = new FileWriter(output); - opmlWriter.writeDocument(Arrays.asList(FeedManager.getInstance().getFeedsArray()), - writer); + opmlWriter.writeDocument(DBReader.getFeedList(context), writer); writer.close(); } catch (IOException e) { e.printStackTrace(); diff --git a/src/de/danoeh/antennapod/feed/FeedImage.java b/src/de/danoeh/antennapod/feed/FeedImage.java index 09595f5eb..3cc99d1c2 100644 --- a/src/de/danoeh/antennapod/feed/FeedImage.java +++ b/src/de/danoeh/antennapod/feed/FeedImage.java @@ -9,7 +9,7 @@ import org.apache.commons.io.IOUtils; import de.danoeh.antennapod.asynctask.ImageLoader; -; + public class FeedImage extends FeedFile implements ImageLoader.ImageWorkerTaskResource { diff --git a/src/de/danoeh/antennapod/fragment/EpisodesFragment.java b/src/de/danoeh/antennapod/fragment/EpisodesFragment.java index 180cb0940..3acc39143 100644 --- a/src/de/danoeh/antennapod/fragment/EpisodesFragment.java +++ b/src/de/danoeh/antennapod/fragment/EpisodesFragment.java @@ -31,6 +31,7 @@ import de.danoeh.antennapod.storage.DBReader; import de.danoeh.antennapod.storage.DBTasks; import de.danoeh.antennapod.storage.DBWriter; import de.danoeh.antennapod.storage.DownloadRequestException; +import de.danoeh.antennapod.util.QueueAccess; import de.danoeh.antennapod.util.menuhandler.FeedItemMenuHandler; import java.util.List; @@ -220,13 +221,13 @@ public class EpisodesFragment extends SherlockFragment { menu.setHeaderTitle(selectedItem.getTitle()); FeedItemMenuHandler.onPrepareMenu( - new FeedItemMenuHandler.MenuInterface() { + new FeedItemMenuHandler.MenuInterface() { - @Override - public void setItemVisibility(int id, boolean visible) { - menu.findItem(id).setVisible(visible); - } - }, selectedItem, false); + @Override + public void setItemVisibility(int id, boolean visible) { + menu.findItem(id).setVisible(visible); + } + }, selectedItem, false, QueueAccess.ItemListAccess(queue)); } else if (selectedGroupId == ExternalEpisodesListAdapter.GROUP_POS_QUEUE) { menu.add(Menu.NONE, R.id.organize_queue_item, Menu.NONE, diff --git a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java index 2f0e90cff..6aca04073 100644 --- a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -29,6 +29,7 @@ import de.danoeh.antennapod.service.download.DownloadService; import de.danoeh.antennapod.storage.DBReader; import de.danoeh.antennapod.storage.DownloadRequestException; import de.danoeh.antennapod.storage.DownloadRequester; +import de.danoeh.antennapod.util.QueueAccess; import de.danoeh.antennapod.util.menuhandler.FeedItemMenuHandler; import java.util.Iterator; @@ -50,7 +51,7 @@ public class ItemlistFragment extends SherlockListFragment { protected DownloadRequester requester = DownloadRequester.getInstance(); private Feed feed; - protected List queue; + protected List queue; protected FeedItem selectedItem = null; protected boolean contextMenuClosed = true; @@ -99,8 +100,8 @@ public class ItemlistFragment extends SherlockListFragment { } @Override - public Iterator queueIterator() { - return (queue != null) ? queue.iterator() : null; + public boolean isInQueue(FeedItem item) { + return (queue != null) && queue.contains(item.getId()); } }; } @@ -127,7 +128,7 @@ public class ItemlistFragment extends SherlockListFragment { feedId = feed.getId(); } AsyncTask loadTask = new AsyncTask(){ - private volatile List queueRef; + private volatile List queueRef; @Override protected Feed doInBackground(Long... longs) { @@ -136,7 +137,7 @@ public class ItemlistFragment extends SherlockListFragment { Feed result = DBReader.getFeed(context, longs[0]); if (result != null) { result.setItems(DBReader.getFeedItemList(context, result)); - queueRef = DBReader.getQueue(context); + queueRef = DBReader.getQueueIDList(context); return result; } } @@ -277,13 +278,13 @@ public class ItemlistFragment extends SherlockListFragment { menu.setHeaderTitle(selectedItem.getTitle()); FeedItemMenuHandler.onPrepareMenu( - new FeedItemMenuHandler.MenuInterface() { + new FeedItemMenuHandler.MenuInterface() { - @Override - public void setItemVisibility(int id, boolean visible) { - menu.findItem(id).setVisible(visible); - } - }, selectedItem, false); + @Override + public void setItemVisibility(int id, boolean visible) { + menu.findItem(id).setVisible(visible); + } + }, selectedItem, false, QueueAccess.IDListAccess(queue)); } } diff --git a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index 2fe43767d..d20cb63c4 100644 --- a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -39,8 +39,8 @@ public class PlaybackHistoryFragment extends ItemlistFragment { } @Override - public Iterator queueIterator() { - return (queue != null) ? queue.iterator() : null; + public boolean isInQueue(FeedItem item) { + return (queue != null) ? queue.contains(item.getId()) : false; } }; } @@ -76,13 +76,13 @@ public class PlaybackHistoryFragment extends ItemlistFragment { protected void loadData() { AsyncTask loadTask = new AsyncTask() { private volatile List phRef; - private volatile List queueRef; + private volatile List queueRef; @Override protected Void doInBackground(Void... voids) { Context context = PlaybackHistoryFragment.this.getActivity(); if (context != null) { - queueRef = DBReader.getQueue(context); + queueRef = DBReader.getQueueIDList(context); phRef = DBReader.getPlaybackHistory(context); } return null; diff --git a/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java b/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java index b58527130..bbc8880a0 100644 --- a/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java +++ b/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java @@ -8,6 +8,7 @@ import android.net.NetworkInfo; import android.util.Log; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.feed.FeedManager; +import de.danoeh.antennapod.storage.DBTasks; import de.danoeh.antennapod.storage.DownloadRequester; import de.danoeh.antennapod.util.NetworkUtils; @@ -27,7 +28,7 @@ public class ConnectivityActionReceiver extends BroadcastReceiver { new Thread() { @Override public void run() { - FeedManager.getInstance() + DBTasks .autodownloadUndownloadedItems(context); } }.start(); diff --git a/src/de/danoeh/antennapod/receiver/FeedUpdateReceiver.java b/src/de/danoeh/antennapod/receiver/FeedUpdateReceiver.java index 821ade4b0..6e0f4c52a 100644 --- a/src/de/danoeh/antennapod/receiver/FeedUpdateReceiver.java +++ b/src/de/danoeh/antennapod/receiver/FeedUpdateReceiver.java @@ -9,6 +9,7 @@ import android.util.Log; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.preferences.UserPreferences; +import de.danoeh.antennapod.storage.DBTasks; /** Refreshes all feeds when it receives an intent */ public class FeedUpdateReceiver extends BroadcastReceiver { @@ -22,7 +23,7 @@ public class FeedUpdateReceiver extends BroadcastReceiver { Log.d(TAG, "Received intent"); boolean mobileUpdate = UserPreferences.isAllowMobileUpdate(); if (mobileUpdate || connectedToWifi(context)) { - FeedManager.getInstance().refreshExpiredFeeds(context); + DBTasks.refreshExpiredFeeds(context); } else { if (AppConfig.DEBUG) Log.d(TAG, diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java index fe327db59..21a91f81f 100644 --- a/src/de/danoeh/antennapod/service/download/DownloadService.java +++ b/src/de/danoeh/antennapod/service/download/DownloadService.java @@ -11,18 +11,12 @@ import java.lang.Thread.UncaughtExceptionHandler; import java.util.ArrayList; import java.util.Date; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import javax.xml.parsers.ParserConfigurationException; +import de.danoeh.antennapod.storage.DBTasks; +import de.danoeh.antennapod.storage.DBWriter; import org.xml.sax.SAXException; import android.annotation.SuppressLint; @@ -93,7 +87,6 @@ public class DownloadService extends Service { private static final int NUM_PARALLEL_DOWNLOADS = 4; private DownloadRequester requester; - private FeedManager manager; private NotificationCompat.Builder notificationCompatBuilder; private Notification.BigTextStyle notificationBuilder; private int NOTIFICATION_ID = 2; @@ -150,23 +143,23 @@ public class DownloadService extends Service { registerReceiver(cancelDownloadReceiver, cancelDownloadReceiverFilter); 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(); - downloadsBeingHandled -= 1; - queryDownloads(); - } - }); - return t; - } - }); + @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(); + downloadsBeingHandled -= 1; + queryDownloads(); + } + }); + return t; + } + }); downloadExecutor = Executors.newFixedThreadPool(NUM_PARALLEL_DOWNLOADS, new ThreadFactory() { @@ -195,7 +188,6 @@ public class DownloadService extends Service { } }); setupNotificationBuilders(); - manager = FeedManager.getInstance(); requester = DownloadRequester.getInstance(); } @@ -473,7 +465,7 @@ public class DownloadService extends Service { */ private void saveDownloadStatus(DownloadStatus status) { completedDownloads.add(status); - manager.addDownloadStatus(this, status); + DBWriter.addDownloadStatus(this, status); } private void sendDownloadHandledIntent() { @@ -610,7 +602,6 @@ public class DownloadService extends Service { reason = 0; String reasonDetailed = null; successful = true; - final FeedManager manager = FeedManager.getInstance(); FeedHandler feedHandler = new FeedHandler(); try { @@ -621,7 +612,7 @@ public class DownloadService extends Service { throw new InvalidFeedException(); } // Save information of feed in DB - savedFeed = manager.updateFeed(DownloadService.this, feed); + savedFeed = DBTasks.updateFeed(DownloadService.this, feed); // Download Feed Image if provided and not downloaded if (savedFeed.getImage() != null && savedFeed.getImage().isDownloaded() == false) { @@ -638,15 +629,15 @@ public class DownloadService extends Service { savedFeedRef.getImage()); } catch (DownloadRequestException e) { e.printStackTrace(); - manager.addDownloadStatus( - DownloadService.this, - new DownloadStatus( - savedFeedRef.getImage(), - savedFeedRef - .getImage() - .getHumanReadableIdentifier(), - DownloadError.ERROR_REQUEST_ERROR, - false, e.getMessage())); + DBWriter.addDownloadStatus( + DownloadService.this, + new DownloadStatus( + savedFeedRef.getImage(), + savedFeedRef + .getImage() + .getHumanReadableIdentifier(), + DownloadError.ERROR_REQUEST_ERROR, + false, e.getMessage())); } } }); @@ -779,13 +770,7 @@ public class DownloadService extends Service { saveDownloadStatus(status); sendDownloadHandledIntent(); - manager.setFeedImage(DownloadService.this, image); - if (image.getFeed() != null) { - manager.setFeed(DownloadService.this, image.getFeed()); - } else { - Log.e(TAG, - "Image has no feed, image might not be saved correctly!"); - } + DBWriter.setFeedImage(DownloadService.this, image); downloadsBeingHandled -= 1; handler.post(new Runnable() { @@ -852,12 +837,19 @@ public class DownloadService extends Service { saveDownloadStatus(status); sendDownloadHandledIntent(); - if (chaptersRead) { - manager.setFeedItem(DownloadService.this, media.getItem()); - } - manager.setFeedMedia(DownloadService.this, media); - if (!FeedManager.getInstance().isInQueue(media.getItem())) { + try { + if (chaptersRead) { + DBWriter.setFeedItem(DownloadService.this, media.getItem()).get(); + } + DBWriter.setFeedMedia(DownloadService.this, media).get(); + } catch (ExecutionException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (!FeedManager.getInstance().isInQueue(media.getItem())) { FeedManager.getInstance().addQueueItem(DownloadService.this, media.getItem()); } diff --git a/src/de/danoeh/antennapod/storage/DBReader.java b/src/de/danoeh/antennapod/storage/DBReader.java index ab3d6342d..c8135bea1 100644 --- a/src/de/danoeh/antennapod/storage/DBReader.java +++ b/src/de/danoeh/antennapod/storage/DBReader.java @@ -18,7 +18,7 @@ import de.danoeh.antennapod.feed.FeedMedia; import de.danoeh.antennapod.feed.ID3Chapter; import de.danoeh.antennapod.feed.SimpleChapter; import de.danoeh.antennapod.feed.VorbisCommentChapter; -import de.danoeh.antennapod.service.download.DownloadStatus; +import de.danoeh.antennapod.service.download.*; import de.danoeh.antennapod.util.comparator.DownloadStatusComparator; import de.danoeh.antennapod.util.comparator.FeedItemPubdateComparator; @@ -132,8 +132,7 @@ public final class DBReader { itemIds.add(String.valueOf(item.getId())); item.setRead((itemlistCursor - .getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0) ? true - : false); + .getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0)); item.setItemIdentifier(itemlistCursor .getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER)); @@ -182,7 +181,6 @@ public final class DBReader { } extractMediafromItemlist(adapter, items, itemIds); - Collections.sort(items, new FeedItemPubdateComparator()); return items; } @@ -275,11 +273,33 @@ public final class DBReader { itemlistCursor); itemlistCursor.close(); loadFeedDataOfFeedItemlist(context, items); - Collections.sort(items, new FeedItemPubdateComparator()); return items; } + public static List getQueueIDList(Context context) { + PodDBAdapter adapter = new PodDBAdapter(context); + + adapter.open(); + List result = getQueueIDList(adapter); + adapter.close(); + + return result; + } + + static List getQueueIDList(PodDBAdapter adapter) { + adapter.open(); + Cursor queueCursor = adapter.getQueueIDCursor(); + + List queueIds = new ArrayList(queueCursor.getCount()); + if (queueCursor.moveToFirst()) { + do { + queueIds.add(queueCursor.getLong(0)); + } while (queueCursor.moveToNext()); + } + return queueIds; + } + public static List getQueue(Context context) { if (AppConfig.DEBUG) Log.d(TAG, "Extracting queue"); diff --git a/src/de/danoeh/antennapod/storage/DBTasks.java b/src/de/danoeh/antennapod/storage/DBTasks.java index eceb3c1b4..39c30445e 100644 --- a/src/de/danoeh/antennapod/storage/DBTasks.java +++ b/src/de/danoeh/antennapod/storage/DBTasks.java @@ -87,7 +87,7 @@ public final class DBTasks { } } - public void refreshExpiredFeeds(final Context context) { + public static void refreshExpiredFeeds(final Context context) { if (AppConfig.DEBUG) Log.d(TAG, "Refreshing expired feeds"); @@ -130,7 +130,7 @@ public final class DBTasks { } /** Updates a specific feed. */ - private static void refreshFeed(Context context, Feed feed) + public static void refreshFeed(Context context, Feed feed) throws DownloadRequestException { DownloadRequester.getInstance().downloadFeed(context, new Feed(feed.getDownload_url(), new Date(), feed.getTitle())); diff --git a/src/de/danoeh/antennapod/storage/DBWriter.java b/src/de/danoeh/antennapod/storage/DBWriter.java index 3ff2fddc1..76f6306f8 100644 --- a/src/de/danoeh/antennapod/storage/DBWriter.java +++ b/src/de/danoeh/antennapod/storage/DBWriter.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.storage; import java.io.File; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -15,13 +16,11 @@ import android.database.Cursor; import android.preference.PreferenceManager; import android.util.Log; import de.danoeh.antennapod.AppConfig; -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.feed.*; import de.danoeh.antennapod.preferences.PlaybackPreferences; import de.danoeh.antennapod.service.PlaybackService; import de.danoeh.antennapod.service.download.DownloadStatus; +import de.danoeh.antennapod.util.QueueAccess; public class DBWriter { private static final String TAG = "DBWriter"; @@ -349,20 +348,23 @@ public class DBWriter { if (queue != null) { boolean queueModified = false; - - if (itemListContains(queue, itemId)) { + QueueAccess queueAccess = QueueAccess.ItemListAccess(queue); + if (queueAccess.contains(itemId)) { item = DBReader.getFeedItem(context, itemId); if (item != null) { - queue.remove(item); - queueModified = true; + queueModified = queueAccess.remove(itemId); } } if (queueModified) { adapter.setQueue(queue); EventDistributor.getInstance() .sendQueueUpdateBroadcast(); - } - } + } else { + Log.w(TAG, "Queue was not modified by call to removeQueueItem"); + } + } else { + Log.e(TAG, "removeQueueItem: Could not load queue"); + } adapter.close(); if (performAutoDownload) { @@ -393,21 +395,30 @@ public class DBWriter { 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); + + adapter.setQueue(queue); if (broadcastUpdate) { EventDistributor.getInstance() .sendQueueUpdateBroadcast(); } } - } + } else { + Log.e(TAG, "moveQueueItem: Could not load queue"); + } adapter.close(); } }); } + public static void markItemRead(Context context, FeedItem item, boolean read, boolean resetMediaPosition) { + long mediaId = (item.hasMedia()) ? item.getMedia().getId() : 0; + markItemRead(context, item.getId(), read, mediaId, resetMediaPosition); + } + public static void markItemRead(final Context context, final long itemId, final boolean read) { markItemRead(context, itemId, read, 0, false); @@ -507,9 +518,9 @@ public class DBWriter { } - static void setFeedMedia(final Context context, + public static Future setFeedMedia(final Context context, final FeedMedia media) { - dbExec.submit(new Runnable() { + return dbExec.submit(new Runnable() { @Override public void run() { @@ -522,6 +533,32 @@ public class DBWriter { } + public static Future setFeedItem(final Context context, + final FeedItem item) { + return dbExec.submit(new Runnable() { + + @Override + public void run() { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setSingleFeedItem(item); + adapter.close(); + }}); + } + + public static Future setFeedImage(final Context context, + final FeedImage image) { + return dbExec.submit(new Runnable() { + + @Override + public void run() { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setImage(image); + adapter.close(); + }}); + } + private static boolean itemListContains(List items, long itemId) { for (FeedItem item : items) { if (item.getId() == itemId) { diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java index 7c28ade14..1aa8c93d4 100644 --- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java +++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java @@ -305,6 +305,7 @@ public class PodDBAdapter { * @return the id of the entry * */ public long setImage(FeedImage image) { + db.beginTransaction(); ContentValues values = new ContentValues(); values.put(KEY_TITLE, image.getTitle()); values.put(KEY_DOWNLOAD_URL, image.getDownload_url()); @@ -316,6 +317,13 @@ public class PodDBAdapter { db.update(TABLE_NAME_FEED_IMAGES, values, KEY_ID + "=?", new String[] { String.valueOf(image.getId()) }); } + if (image.getFeed() != null && image.getFeed().getId() != 0 ) { + values.clear(); + values.put(KEY_IMAGE, image.getId()); + db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[] {String.valueOf(image.getFeed().getId())}); + } + db.setTransactionSuccessful(); + db.endTransaction(); return image.getId(); } @@ -686,11 +694,11 @@ public class PodDBAdapter { open(); String selFiSmall = Arrays.toString(SEL_FI_SMALL); Object[] args = (Object[]) new String[] { - selFiSmall.substring(1, selFiSmall.length() - 1), + selFiSmall.substring(1, selFiSmall.length() - 1) + "," + TABLE_NAME_QUEUE + "." + KEY_ID, TABLE_NAME_FEED_ITEMS, TABLE_NAME_QUEUE, TABLE_NAME_FEED_ITEMS + "." + KEY_ID, TABLE_NAME_QUEUE + "." + KEY_FEEDITEM, - TABLE_NAME_QUEUE + "." + KEY_FEEDITEM }; + TABLE_NAME_QUEUE + "." + KEY_ID }; String query = String.format( "SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s", args); Cursor c = db.rawQuery(query, null); @@ -703,6 +711,12 @@ public class PodDBAdapter { return c; } + public Cursor getQueueIDCursor() { + open(); + Cursor c = db.query(TABLE_NAME_QUEUE, new String[]{KEY_FEEDITEM}, null, null, null, null, KEY_ID + " ASC", null); + return c; + } + /** * Returns a cursor which contains all feed items in the unread items list. * The returned cursor uses the SEL_FI_SMALL selection. @@ -791,8 +805,11 @@ public class PodDBAdapter { /** Builds an IN-operator argument depending on the number of items. */ private String buildInOperator(int size) { + if (size == 1) { + return "(?)"; + } StringBuffer buffer = new StringBuffer("("); - for (int i = 0; i <= size; i++) { + for (int i = 0; i < size - 1; i++) { buffer.append("?,"); } buffer.append("?)"); diff --git a/src/de/danoeh/antennapod/util/QueueAccess.java b/src/de/danoeh/antennapod/util/QueueAccess.java new file mode 100644 index 000000000..4c70d74e2 --- /dev/null +++ b/src/de/danoeh/antennapod/util/QueueAccess.java @@ -0,0 +1,89 @@ +package de.danoeh.antennapod.util; + +import de.danoeh.antennapod.feed.FeedItem; + +import java.util.Iterator; +import java.util.List; + +/** + * Provides methods for accessing the queue. It is possible to load only a part of the information about the queue that + * is stored in the database (e.g. sometimes the user just has to test if a specific item is contained in the List. + * QueueAccess provides an interface for accessing the queue without having to care about the type of the queue + * representation. + */ +public abstract class QueueAccess { + /** + * Returns true if the item is in the queue, false otherwise. + */ + public abstract boolean contains(long id); + + /** + * Removes the item from the queue. + * + * @return true if the queue was modified by this operation. + */ + public abstract boolean remove(long id); + + private QueueAccess() { + + } + + public static QueueAccess IDListAccess(final List ids) { + return new QueueAccess() { + @Override + public boolean contains(long id) { + return (ids != null) && ids.contains(id); + } + + @Override + public boolean remove(long id) { + return ids.remove(id); + } + + + }; + } + + public static QueueAccess ItemListAccess(final List items) { + return new QueueAccess() { + @Override + public boolean contains(long id) { + Iterator it = items.iterator(); + for (FeedItem i = it.next(); it.hasNext(); i = it.next()) { + if (i.getId() == id) { + return true; + } + } + return false; + } + + @Override + public boolean remove(long id) { + Iterator it = items.iterator(); + for (FeedItem i = it.next(); it.hasNext(); i = it.next()) { + if (i.getId() == id) { + it.remove(); + return true; + } + } + return false; + } + }; + } + + public static QueueAccess NotInQueueAccess() { + return new QueueAccess() { + @Override + public boolean contains(long id) { + return false; + } + + @Override + public boolean remove(long id) { + return false; + } + }; + + } + +} diff --git a/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java b/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java index 1891addc9..2cfe52364 100644 --- a/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java +++ b/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java @@ -2,7 +2,7 @@ package de.danoeh.antennapod.util.comparator; import java.util.Comparator; -import de.danoeh.antennapod.service.download.DownloadStatus; +import de.danoeh.antennapod.service.download.*; /** Compares the completion date of two Downloadstatus objects. */ public class DownloadStatusComparator implements Comparator { diff --git a/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java b/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java index 472124bf7..912e7c1c6 100644 --- a/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java +++ b/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java @@ -7,12 +7,16 @@ import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.asynctask.FlattrClickWorker; import de.danoeh.antennapod.feed.FeedItem; -import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.service.PlaybackService; +import de.danoeh.antennapod.storage.DBTasks; +import de.danoeh.antennapod.storage.DBWriter; import de.danoeh.antennapod.storage.DownloadRequestException; import de.danoeh.antennapod.storage.DownloadRequester; +import de.danoeh.antennapod.util.QueueAccess; import de.danoeh.antennapod.util.ShareUtils; +import java.util.List; + /** Handles interactions with the FeedItemMenu. */ public class FeedItemMenuHandler { private FeedItemMenuHandler() { @@ -45,11 +49,12 @@ public class FeedItemMenuHandler { * True if MenuItems that let the user share information about * the FeedItem and visit its website should be set visible. This * parameter should be set to false if the menu space is limited. + * @param queueAccess + * Used for testing if the queue contains the selected item * @return Always returns true * */ public static boolean onPrepareMenu(MenuInterface mi, - FeedItem selectedItem, boolean showExtendedMenu) { - FeedManager manager = FeedManager.getInstance(); + FeedItem selectedItem, boolean showExtendedMenu, QueueAccess queueAccess) { DownloadRequester requester = DownloadRequester.getInstance(); boolean hasMedia = selectedItem.getMedia() != null; boolean downloaded = hasMedia && selectedItem.getMedia().isDownloaded(); @@ -79,7 +84,7 @@ public class FeedItemMenuHandler { mi.setItemVisibility(R.id.cancel_download_item, false); } - boolean isInQueue = manager.isInQueue(selectedItem); + boolean isInQueue = queueAccess.contains(selectedItem.getId()); if (!isInQueue || isPlaying) { mi.setItemVisibility(R.id.remove_from_queue_item, false); } @@ -111,39 +116,38 @@ public class FeedItemMenuHandler { public static boolean onMenuItemClicked(Context context, int menuItemId, FeedItem selectedItem) throws DownloadRequestException { DownloadRequester requester = DownloadRequester.getInstance(); - FeedManager manager = FeedManager.getInstance(); switch (menuItemId) { case R.id.skip_episode_item: context.sendBroadcast(new Intent( PlaybackService.ACTION_SKIP_CURRENT_EPISODE)); break; case R.id.download_item: - manager.downloadFeedItem(context, selectedItem); + DBTasks.downloadFeedItems(context, selectedItem); break; case R.id.play_item: - manager.playMedia(context, selectedItem.getMedia(), true, true, + DBTasks.playMedia(context, selectedItem.getMedia(), true, true, false); break; case R.id.remove_item: - manager.deleteFeedMedia(context, selectedItem.getMedia()); + DBWriter.deleteFeedMediaOfItem(context, selectedItem.getId()); break; case R.id.cancel_download_item: requester.cancelDownload(context, selectedItem.getMedia()); break; case R.id.mark_read_item: - manager.markItemRead(context, selectedItem, true, true); + DBWriter.markItemRead(context, selectedItem, true, true); break; case R.id.mark_unread_item: - manager.markItemRead(context, selectedItem, false, true); + DBWriter.markItemRead(context, selectedItem, false, true); break; case R.id.add_to_queue_item: - manager.addQueueItem(context, selectedItem); + DBWriter.addQueueItem(context, selectedItem.getId()); break; case R.id.remove_from_queue_item: - manager.removeQueueItem(context, selectedItem, true); + DBWriter.removeQueueItem(context, selectedItem.getId(), true); break; case R.id.stream_item: - manager.playMedia(context, selectedItem.getMedia(), true, true, + DBTasks.playMedia(context, selectedItem.getMedia(), true, true, true); break; case R.id.visit_website_item: diff --git a/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java b/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java index af8538e83..fee8027a0 100644 --- a/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java +++ b/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java @@ -14,8 +14,9 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.FeedInfoActivity; import de.danoeh.antennapod.asynctask.FlattrClickWorker; import de.danoeh.antennapod.feed.Feed; -import de.danoeh.antennapod.feed.FeedManager; import de.danoeh.antennapod.service.download.DownloadService; +import de.danoeh.antennapod.storage.DBTasks; +import de.danoeh.antennapod.storage.DBWriter; import de.danoeh.antennapod.storage.DownloadRequestException; import de.danoeh.antennapod.storage.DownloadRequester; import de.danoeh.antennapod.util.ShareUtils; @@ -56,7 +57,6 @@ public class FeedMenuHandler { */ public static boolean onOptionsItemClicked(Context context, MenuItem item, Feed selectedFeed) throws DownloadRequestException { - FeedManager manager = FeedManager.getInstance(); switch (item.getItemId()) { case R.id.show_info_item: Intent startIntent = new Intent(context, FeedInfoActivity.class); @@ -65,10 +65,10 @@ public class FeedMenuHandler { context.startActivity(startIntent); break; case R.id.refresh_item: - manager.refreshFeed(context, selectedFeed); + DBTasks.refreshFeed(context, selectedFeed); break; case R.id.mark_all_read_item: - manager.markFeedRead(context, selectedFeed); + DBWriter.markFeedRead(context, selectedFeed.getId()); break; case R.id.visit_website_item: Uri uri = Uri.parse(selectedFeed.getLink()); diff --git a/src/de/danoeh/antennapod/util/playback/PlaybackController.java b/src/de/danoeh/antennapod/util/playback/PlaybackController.java index cebb11cf0..1d7057b10 100644 --- a/src/de/danoeh/antennapod/util/playback/PlaybackController.java +++ b/src/de/danoeh/antennapod/util/playback/PlaybackController.java @@ -33,6 +33,7 @@ import de.danoeh.antennapod.feed.FeedMedia; import de.danoeh.antennapod.preferences.PlaybackPreferences; import de.danoeh.antennapod.service.PlaybackService; import de.danoeh.antennapod.service.PlayerStatus; +import de.danoeh.antennapod.storage.DBTasks; import de.danoeh.antennapod.util.Converter; import de.danoeh.antennapod.util.playback.Playable.PlayableUtils; @@ -214,8 +215,8 @@ public abstract class PlaybackController { boolean lastIsStream = PlaybackPreferences .getCurrentEpisodeIsStream(); if (!fileExists && !lastIsStream && media instanceof FeedMedia) { - FeedManager.getInstance().notifyMissingFeedMediaFile( - activity, (FeedMedia) media); + DBTasks.notifyMissingFeedMediaFile( + activity, (FeedMedia) media); } serviceIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, lastIsStream || !fileExists); -- cgit v1.2.3