From fbf1d8373c4e6bd38a73af7e8ff0abe932da0ad8 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 5 Apr 2015 19:48:57 +0200 Subject: Minor changes: Log, import order, small refactorings --- .../antennapod/core/feed/EventDistributor.java | 14 +- .../de/danoeh/antennapod/core/feed/FeedItem.java | 8 + .../core/service/playback/PlaybackService.java | 100 +++------ .../playback/PlaybackServiceTaskManager.java | 15 +- .../core/storage/APCleanupAlgorithm.java | 4 +- .../danoeh/antennapod/core/storage/DBReader.java | 31 ++- .../de/danoeh/antennapod/core/storage/DBTasks.java | 6 +- .../danoeh/antennapod/core/storage/DBWriter.java | 70 +++--- .../de/danoeh/antennapod/core/util/LongList.java | 241 +++++++++++++++++++++ .../danoeh/antennapod/core/util/QueueAccess.java | 21 +- .../core/util/playback/PlaybackController.java | 36 +-- 11 files changed, 371 insertions(+), 175 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/LongList.java (limited to 'core/src/main/java') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java b/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java index 5a2cfa40e..6655a7522 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java @@ -5,8 +5,6 @@ import android.util.Log; import org.apache.commons.lang3.Validate; -import de.danoeh.antennapod.core.BuildConfig; - import java.util.AbstractQueue; import java.util.Observable; import java.util.Observer; @@ -71,23 +69,17 @@ public class EventDistributor extends Observable { private void processEventQueue() { Integer result = 0; - if (BuildConfig.DEBUG) - Log.d(TAG, - "Processing event queue. Number of events: " - + events.size()); + Log.d(TAG, "Processing event queue. Number of events: " + events.size()); for (Integer current = events.poll(); current != null; current = events .poll()) { result |= current; } if (result != 0) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Notifying observers. Data: " + result); + Log.d(TAG, "Notifying observers. Data: " + result); setChanged(); notifyObservers(result); } else { - if (BuildConfig.DEBUG) - Log.d(TAG, - "Event queue didn't contain any new events. Observers will not be notified."); + Log.d(TAG, "Event queue didn't contain any new events. Observers will not be notified."); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 5a4d869e7..4fd7a184c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -2,6 +2,9 @@ package de.danoeh.antennapod.core.feed; import android.net.Uri; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + import java.util.Date; import java.util.List; import java.util.concurrent.Callable; @@ -384,4 +387,9 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr public boolean hasChapters() { return hasChapters; } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index c1563a0fa..43c345fec 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -36,7 +36,6 @@ import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.List; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.Chapter; @@ -184,8 +183,7 @@ public class PlaybackService extends Service { @Override public boolean onUnbind(Intent intent) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Received onUnbind event"); + Log.d(TAG, "Received onUnbind event"); return super.onUnbind(intent); } @@ -219,8 +217,7 @@ public class PlaybackService extends Service { @Override public void onCreate() { super.onCreate(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Service created."); + Log.d(TAG, "Service created."); isRunning = true; registerReceiver(headsetDisconnected, new IntentFilter( @@ -247,8 +244,7 @@ public class PlaybackService extends Service { @Override public void onDestroy() { super.onDestroy(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Service is about to be destroyed"); + Log.d(TAG, "Service is about to be destroyed"); isRunning = false; started = false; currentMediaType = MediaType.UNKNOWN; @@ -264,8 +260,7 @@ public class PlaybackService extends Service { @Override public IBinder onBind(Intent intent) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Received onBind event"); + Log.d(TAG, "Received onBind event"); return mBinder; } @@ -273,8 +268,7 @@ public class PlaybackService extends Service { public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); - if (BuildConfig.DEBUG) - Log.d(TAG, "OnStartCommand called"); + Log.d(TAG, "OnStartCommand called"); final int keycode = intent.getIntExtra(MediaButtonReceiver.EXTRA_KEYCODE, -1); final Playable playable = intent.getParcelableExtra(EXTRA_PLAYABLE); if (keycode == -1 && playable == null) { @@ -283,14 +277,12 @@ public class PlaybackService extends Service { } if ((flags & Service.START_FLAG_REDELIVERY) != 0) { - if (BuildConfig.DEBUG) - Log.d(TAG, "onStartCommand is a redelivered intent, calling stopForeground now."); + Log.d(TAG, "onStartCommand is a redelivered intent, calling stopForeground now."); stopForeground(true); } else { if (keycode != -1) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Received media button event"); + Log.d(TAG, "Received media button event"); handleKeycode(keycode); } else { started = true; @@ -310,8 +302,7 @@ public class PlaybackService extends Service { * Handles media button events */ private void handleKeycode(int keycode) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Handling keycode: " + keycode); + Log.d(TAG, "Handling keycode: " + keycode); final PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo(); final PlayerStatus status = info.playerStatus; switch (keycode) { @@ -381,8 +372,7 @@ public class PlaybackService extends Service { * mediaplayer. */ public void setVideoSurface(SurfaceHolder sh) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Setting display"); + Log.d(TAG, "Setting display"); mediaPlayer.setVideoSurface(sh); } @@ -465,22 +455,6 @@ public class PlaybackService extends Service { .build(); GpodnetPreferences.enqueueEpisodeAction(action); } - - // if episode is near end [outro playing]: - // mark as read, remove from queue, add to playlist history - // auto delete: see {@link de.danoeh.antennapod.activity.MediaPlayerActivity#onStop()} - if (playable instanceof FeedMedia) { - FeedMedia media = (FeedMedia) playable; - if(media.hasAlmostEnded()) { - FeedItem item = media.getItem(); - Log.d(TAG, "smart mark as read"); - DBWriter.markItemRead(PlaybackService.this, item, true, false); - DBWriter.removeQueueItem(PlaybackService.this, item.getId(), false); - DBWriter.addItemToPlaybackHistory(PlaybackService.this, media); - // episode should already be flattered, no action required - } - } - break; case STOPPED: @@ -489,10 +463,8 @@ public class PlaybackService extends Service { break; case PLAYING: - if (BuildConfig.DEBUG) - Log.d(TAG, "Audiofocus successfully requested"); - if (BuildConfig.DEBUG) - Log.d(TAG, "Resuming/Starting playback"); + Log.d(TAG, "Audiofocus successfully requested"); + Log.d(TAG, "Resuming/Starting playback"); taskManager.startPositionSaver(); taskManager.startWidgetUpdater(); @@ -574,8 +546,7 @@ public class PlaybackService extends Service { }; private void endPlayback(boolean playNextEpisode) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Playback ended"); + Log.d(TAG, "Playback ended"); final Playable playable = mediaPlayer.getPSMPInfo().playable; if (playable == null) { @@ -602,7 +573,7 @@ public class PlaybackService extends Service { // isInQueue remains false } if (isInQueue) { - DBWriter.removeQueueItem(PlaybackService.this, item.getId(), true); + DBWriter.removeQueueItem(PlaybackService.this, item, true); } DBWriter.addItemToPlaybackHistory(PlaybackService.this, media); @@ -643,8 +614,7 @@ public class PlaybackService extends Service { UserPreferences.isFollowQueue(); if (loadNextItem) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Loading next item in queue"); + Log.d(TAG, "Loading next item in queue"); nextMedia = nextItem.getMedia(); } final boolean prepareImmediately; @@ -770,8 +740,7 @@ public class PlaybackService extends Service { } private void writePlayerStatusPlaybackPreferences() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Writing player status playback preferences"); + Log.d(TAG, "Writing player status playback preferences"); SharedPreferences.Editor editor = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()).edit(); @@ -820,8 +789,7 @@ public class PlaybackService extends Service { @Override protected Void doInBackground(Void... params) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Starting background work"); + Log.d(TAG, "Starting background work"); if (android.os.Build.VERSION.SDK_INT >= 11) { if (info.playable != null) { try { @@ -931,8 +899,7 @@ public class PlaybackService extends Service { notification = notificationBuilder.build(); } startForeground(NOTIFICATION_ID, notification); - if (BuildConfig.DEBUG) - Log.d(TAG, "Notification set up"); + Log.d(TAG, "Notification set up"); } } @@ -958,8 +925,7 @@ public class PlaybackService extends Service { float playbackSpeed = getCurrentPlaybackSpeed(); final Playable playable = mediaPlayer.getPSMPInfo().playable; if (position != INVALID_TIME && duration != INVALID_TIME && playable != null) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Saving current position to " + position); + Log.d(TAG, "Saving current position to " + position); if (updatePlayedDuration && playable instanceof FeedMedia) { FeedMedia media = (FeedMedia) playable; FeedItem item = media.getItem(); @@ -968,8 +934,7 @@ public class PlaybackService extends Service { if (isAutoFlattrable(media) && (media.getPlayedDuration() > UserPreferences.getAutoFlattrPlayedDurationThreshold() * duration)) { - if (BuildConfig.DEBUG) - Log.d(TAG, "saveCurrentPosition: performing auto flattr since played duration " + Integer.toString(media.getPlayedDuration()) + Log.d(TAG, "saveCurrentPosition: performing auto flattr since played duration " + Integer.toString(media.getPlayedDuration()) + " is " + UserPreferences.getAutoFlattrPlayedDurationThreshold() * 100 + "% of file duration " + Integer.toString(duration)); DBTasks.flattrItemIfLoggedIn(this, item); } @@ -1062,8 +1027,7 @@ public class PlaybackService extends Service { editor.apply(); } - if (BuildConfig.DEBUG) - Log.d(TAG, "RemoteControlClient state was refreshed"); + Log.d(TAG, "RemoteControlClient state was refreshed"); } } } @@ -1106,15 +1070,12 @@ public class PlaybackService extends Service { if (StringUtils.equals(intent.getAction(), Intent.ACTION_HEADSET_PLUG)) { int state = intent.getIntExtra("state", -1); if (state != -1) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Headset plug event. State is " + state); + Log.d(TAG, "Headset plug event. State is " + state); if (state == UNPLUGGED) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Headset was unplugged during playback."); + Log.d(TAG, "Headset was unplugged during playback."); pauseIfPauseOnDisconnect(); } else if (state == PLUGGED) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Headset was plugged in during playback."); + Log.d(TAG, "Headset was plugged in during playback."); unpauseIfPauseOnDisconnect(); } } else { @@ -1131,8 +1092,7 @@ public class PlaybackService extends Service { int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); int prevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1); if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Received bluetooth connection intent"); + Log.d(TAG, "Received bluetooth connection intent"); unpauseIfPauseOnDisconnect(); } } @@ -1144,8 +1104,7 @@ public class PlaybackService extends Service { @Override public void onReceive(Context context, Intent intent) { // sound is about to change, eg. bluetooth -> speaker - if (BuildConfig.DEBUG) - Log.d(TAG, "Pausing playback because audio is becoming noisy"); + Log.d(TAG, "Pausing playback because audio is becoming noisy"); pauseIfPauseOnDisconnect(); } // android.media.AUDIO_BECOMING_NOISY @@ -1191,8 +1150,7 @@ public class PlaybackService extends Service { @Override public void onReceive(Context context, Intent intent) { if (StringUtils.equals(intent.getAction(), ACTION_SKIP_CURRENT_EPISODE)) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Received SKIP_CURRENT_EPISODE intent"); + Log.d(TAG, "Received SKIP_CURRENT_EPISODE intent"); mediaPlayer.endPlayback(); } } @@ -1202,8 +1160,7 @@ public class PlaybackService extends Service { @Override public void onReceive(Context context, Intent intent) { if (StringUtils.equals(intent.getAction(), ACTION_RESUME_PLAY_CURRENT_EPISODE)) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Received RESUME_PLAY_CURRENT_EPISODE intent"); + Log.d(TAG, "Received RESUME_PLAY_CURRENT_EPISODE intent"); mediaPlayer.resume(); } } @@ -1213,8 +1170,7 @@ public class PlaybackService extends Service { @Override public void onReceive(Context context, Intent intent) { if (StringUtils.equals(intent.getAction(), ACTION_PAUSE_PLAY_CURRENT_EPISODE)) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Received PAUSE_PLAY_CURRENT_EPISODE intent"); + Log.d(TAG, "Received PAUSE_PLAY_CURRENT_EPISODE intent"); mediaPlayer.pause(false, false); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java index 1865afa6f..3e414a8b7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java @@ -5,14 +5,21 @@ import android.util.Log; import org.apache.commons.lang3.Validate; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.QueueEvent; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.playback.Playable; - -import java.util.List; -import java.util.concurrent.*; +import de.greenrobot.event.EventBus; /** * Manages the background tasks of PlaybackSerivce, i.e. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index 0164e914b..de6c02de7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -12,7 +12,7 @@ import java.util.concurrent.ExecutionException; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.util.QueueAccess; +import de.danoeh.antennapod.core.util.LongList; /** * Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPod. @@ -24,7 +24,7 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { public int performCleanup(Context context, Integer episodeNumber) { List candidates = new ArrayList(); List downloadedItems = DBReader.getDownloadedItems(context); - QueueAccess queue = QueueAccess.IDListAccess(DBReader.getQueueIDList(context)); + LongList queue = DBReader.getQueueIDList(context); List delete; for (FeedItem item : downloadedItems) { if (item.hasMedia() && item.getMedia().isDownloaded() diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index e10fffc18..a7c98c7c6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -21,6 +21,7 @@ import de.danoeh.antennapod.core.feed.SimpleChapter; import de.danoeh.antennapod.core.feed.VorbisCommentChapter; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.util.DownloadError; +import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.comparator.DownloadStatusComparator; import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator; import de.danoeh.antennapod.core.util.comparator.PlaybackCompletionDateComparator; @@ -338,8 +339,7 @@ public final class DBReader { } static List getQueue(Context context, PodDBAdapter adapter) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Extracting queue"); + Log.d(TAG, "getQueue()"); Cursor itemlistCursor = adapter.getQueueCursor(); List items = extractItemlistFromCursor(adapter, @@ -358,21 +358,21 @@ public final class DBReader { * @return A list of IDs sorted by the same order as the queue. The caller can wrap the returned * list in a {@link de.danoeh.antennapod.core.util.QueueAccess} object for easier access to the queue's properties. */ - public static List getQueueIDList(Context context) { + public static LongList getQueueIDList(Context context) { PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); - List result = getQueueIDList(adapter); + LongList result = getQueueIDList(adapter); adapter.close(); return result; } - static List getQueueIDList(PodDBAdapter adapter) { + static LongList getQueueIDList(PodDBAdapter adapter) { adapter.open(); Cursor queueCursor = adapter.getQueueIDCursor(); - List queueIds = new ArrayList(queueCursor.getCount()); + LongList queueIds = new LongList(queueCursor.getCount()); if (queueCursor.moveToFirst()) { do { queueIds.add(queueCursor.getLong(0)); @@ -382,6 +382,22 @@ public final class DBReader { } + /** + * Return the size of the queue. + * + * @param context A context that is used for opening a database connection. + * @return Size of the queue. + */ + public static int getQueueSize(Context context) { + Log.d(TAG, "getQueueSize()"); + + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + int size = adapter.getQueueSize(); + adapter.close(); + return size; + } + /** * Loads a list of the FeedItems in the queue. If the FeedItems of the queue are not used directly, consider using * {@link #getQueueIDList(android.content.Context)} instead. @@ -391,8 +407,7 @@ public final class DBReader { * list in a {@link de.danoeh.antennapod.core.util.QueueAccess} object for easier access to the queue's properties. */ public static List getQueue(Context context) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Extracting queue"); + Log.d(TAG, "getQueue()"); PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index e0e370b0d..9fa17bf72 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -34,7 +34,7 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.util.DownloadError; -import de.danoeh.antennapod.core.util.QueueAccess; +import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator; import de.danoeh.antennapod.core.util.exception.MediaFileNotFoundException; import de.danoeh.antennapod.core.util.flattr.FlattrUtils; @@ -524,8 +524,8 @@ public final class DBTasks { * @param feedItemId ID of the FeedItem */ public static boolean isInQueue(Context context, final long feedItemId) { - List queue = DBReader.getQueueIDList(context); - return QueueAccess.IDListAccess(queue).contains(feedItemId); + LongList queue = DBReader.getQueueIDList(context); + return queue.contains(feedItemId); } private static Feed searchFeedByIdentifyingValueOrID(Context context, PodDBAdapter adapter, diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 53fe5149b..63c52b488 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -33,17 +33,19 @@ import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.QueueEvent; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction; -import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction.Action; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; +import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.QueueAccess; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.danoeh.antennapod.core.util.flattr.FlattrThing; import de.danoeh.antennapod.core.util.flattr.SimpleFlattrThing; +import de.greenrobot.event.EventBus; /** * Provides methods for writing data to AntennaPod's database. @@ -126,16 +128,15 @@ public class DBWriter { // Gpodder: queue delete action for synchronization if(GpodnetPreferences.loggedIn()) { FeedItem item = media.getItem(); - GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, Action.DELETE) + GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, GpodnetEpisodeAction.Action.DELETE) .currentDeviceId() .currentTimestamp() .build(); GpodnetPreferences.enqueueEpisodeAction(action); } } - if (BuildConfig.DEBUG) - Log.d(TAG, "Deleting File. Result: " + result); - EventDistributor.getInstance().sendQueueUpdateBroadcast(); + Log.d(TAG, "Deleting File. Result: " + result); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.DELETED_MEDIA, media.getItem())); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } } @@ -370,8 +371,7 @@ public class DBWriter { } if (queueModified) { adapter.setQueue(queue); - EventDistributor.getInstance() - .sendQueueUpdateBroadcast(); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); } if (unreadItemsModified && item != null) { adapter.setSingleFeedItem(item); @@ -439,8 +439,7 @@ public class DBWriter { } if (queueModified) { adapter.setQueue(queue); - EventDistributor.getInstance() - .sendQueueUpdateBroadcast(); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); } if (unreadItemsModified) { adapter.setFeedItemlist(itemsToSave); @@ -471,7 +470,7 @@ public class DBWriter { adapter.clearQueue(); adapter.close(); - EventDistributor.getInstance().sendQueueUpdateBroadcast(); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.CLEARED)); } }); } @@ -480,11 +479,11 @@ public class DBWriter { * Removes a FeedItem object from the queue. * * @param context A context that is used for opening a database connection. - * @param itemId ID of the FeedItem that should be removed. + * @param item FeedItem that should be removed. * @param performAutoDownload true if an auto-download process should be started after the operation. */ public static Future removeQueueItem(final Context context, - final long itemId, final boolean performAutoDownload) { + final FeedItem item, final boolean performAutoDownload) { return dbExec.submit(new Runnable() { @Override @@ -498,16 +497,14 @@ public class DBWriter { if (queue != null) { boolean queueModified = false; QueueAccess queueAccess = QueueAccess.ItemListAccess(queue); - if (queueAccess.contains(itemId)) { - item = DBReader.getFeedItem(context, itemId); + if (queueAccess.contains(item.getId())) { if (item != null) { - queueModified = queueAccess.remove(itemId); + queueModified = queueAccess.remove(item.getId()); } } if (queueModified) { adapter.setQueue(queue); - EventDistributor.getInstance() - .sendQueueUpdateBroadcast(); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.REMOVED, item)); } else { Log.w(TAG, "Queue was not modified by call to removeQueueItem"); } @@ -535,16 +532,13 @@ public class DBWriter { return dbExec.submit(new Runnable() { @Override public void run() { - List queueIdList = DBReader.getQueueIDList(context); - int currentLocation = 0; - for (long id : queueIdList) { - if (id == itemId) { - moveQueueItemHelper(context, currentLocation, 0, broadcastUpdate); - return; - } - currentLocation++; + LongList queueIdList = DBReader.getQueueIDList(context); + int index = queueIdList.indexOf(itemId); + if (index >=0) { + moveQueueItemHelper(context, index, 0, broadcastUpdate); + } else { + Log.e(TAG, "moveQueueItemToTop: item not found"); } - Log.e(TAG, "moveQueueItemToTop: item not found"); } }); } @@ -562,17 +556,14 @@ public class DBWriter { return dbExec.submit(new Runnable() { @Override public void run() { - List queueIdList = DBReader.getQueueIDList(context); - int currentLocation = 0; - for (long id : queueIdList) { - if (id == itemId) { - moveQueueItemHelper(context, currentLocation, queueIdList.size() - 1, - broadcastUpdate); - return; - } - currentLocation++; + LongList queueIdList = DBReader.getQueueIDList(context); + int index = queueIdList.indexOf(itemId); + if(index >= 0) { + moveQueueItemHelper(context, index, queueIdList.size() - 1, + broadcastUpdate); + } else { + Log.e(TAG, "moveQueueItemToBottom: item not found"); } - Log.e(TAG, "moveQueueItemToBottom: item not found"); } }); } @@ -626,8 +617,8 @@ public class DBWriter { adapter.setQueue(queue); if (broadcastUpdate) { - EventDistributor.getInstance() - .sendQueueUpdateBroadcast(); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.REMOVED, item)); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, to)); } } @@ -1036,8 +1027,7 @@ public class DBWriter { Collections.sort(queue, comparator); adapter.setQueue(queue); if (broadcastUpdate) { - EventDistributor.getInstance() - .sendQueueUpdateBroadcast(); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.SORTED)); } } else { Log.e(TAG, "sortQueue: Could not load queue"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java b/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java new file mode 100644 index 000000000..f5d0cab0c --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java @@ -0,0 +1,241 @@ +package de.danoeh.antennapod.core.util; + +import java.util.Arrays; + +/** + * Fast and memory efficient long list + */ +public final class LongList { + + private long[] values; + private int size; + + /** + * Constructs an empty instance with a default initial capacity. + */ + public LongList() { + this(4); + } + + /** + * Constructs an empty instance. + * + * @param initialCapacity {@code >= 0;} initial capacity of the list + */ + public LongList(int initialCapacity) { + if(initialCapacity < 0) { + throw new IllegalArgumentException("initial capacity must be 0 or higher"); + } + values = new long[initialCapacity]; + size = 0; + } + + @Override + public int hashCode() { + Arrays.hashCode(values); + int hashCode = 1; + for (int i = 0; i < size; i++) { + long value = values[i]; + hashCode = 31 * hashCode + (int)(value ^ (value >>> 32)); + } + return hashCode; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (! (other instanceof LongList)) { + return false; + } + LongList otherList = (LongList) other; + if (size != otherList.size) { + return false; + } + for (int i = 0; i < size; i++) { + if (values[i] != otherList.values[i]) { + return false; + } + } + return true; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(size * 5 + 10); + sb.append("LongList{"); + for (int i = 0; i < size; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(values[i]); + } + sb.append("}"); + return sb.toString(); + } + + /** + * Gets the number of elements in this list. + */ + public int size() { + return size; + } + + /** + * Gets the indicated value. + * + * @param n {@code >= 0, < size();} which element + * @return the indicated element's value + */ + public long get(int n) { + if (n >= size) { + throw new IndexOutOfBoundsException("n >= size()"); + } else if(n < 0) { + throw new IndexOutOfBoundsException("n < 0"); + } + return values[n]; + } + + /** + * Sets the value at the given index. + * + * @param index the index at which to put the specified object. + * @param value the object to add. + * @return the previous element at the index. + */ + public long set(int index, long value) { + if (index >= size) { + throw new IndexOutOfBoundsException("n >= size()"); + } else if(index < 0) { + throw new IndexOutOfBoundsException("n < 0"); + } + long result = values[index]; + values[index] = value; + return result; + } + + /** + * Adds an element to the end of the list. This will increase the + * list's capacity if necessary. + * + * @param value the value to add + */ + public void add(long value) { + growIfNeeded(); + values[size++] = value; + } + + /** + * Inserts element into specified index, moving elements at and above + * that index up one. May not be used to insert at an index beyond the + * current size (that is, insertion as a last element is legal but + * no further). + * + * @param n {@code >= 0, <=size();} index of where to insert + * @param value value to insert + */ + public void insert(int n, int value) { + if (n > size) { + throw new IndexOutOfBoundsException("n > size()"); + } else if(n < 0) { + throw new IndexOutOfBoundsException("n < 0"); + } + + growIfNeeded(); + + System.arraycopy (values, n, values, n+1, size - n); + values[n] = value; + size++; + } + + /** + * Removes value from this list. + * + * @param value value to remove + * return {@code true} if the value was removed, {@code false} otherwise + */ + public boolean remove(long value) { + for (int i = 0; i < size; i++) { + if (values[i] == value) { + size--; + System.arraycopy(values, i+1, values, i, size-i); + return true; + } + } + return false; + } + + /** + * Removes an element at a given index, shifting elements at greater + * indicies down one. + * + * @param index index of element to remove + */ + public void removeIndex(int index) { + if (index >= size) { + throw new IndexOutOfBoundsException("n >= size()"); + } else if(index < 0) { + throw new IndexOutOfBoundsException("n < 0"); + } + size--; + System.arraycopy (values, index + 1, values, index, size - index); + } + + /** + * Increases size of array if needed + */ + private void growIfNeeded() { + if (size == values.length) { + // Resize. + long[] newArray = new long[size * 3 / 2 + 10]; + System.arraycopy(values, 0, newArray, 0, size); + values = newArray; + } + } + + /** + * Returns the index of the given value, or -1 if the value does not + * appear in the list. + * + * @param value value to find + * @return index of value or -1 + */ + public int indexOf(long value) { + for (int i = 0; i < size; i++) { + if (values[i] == value) { + return i; + } + } + return -1; + } + + /** + * Removes all values from this list. + */ + public void clear() { + values = new long[4]; + size = 0; + } + + + /** + * Returns true if the given value is contained in the list + * + * @param value value to look for + * @return {@code true} if this list contains {@code value}, {@code false} otherwise + */ + public boolean contains(long value) { + return indexOf(value) >= 0; + } + + /** + * Returns an array with a copy of this list's values + * + * @return array with a copy of this list's values + */ + public long[] toArray() { + return Arrays.copyOf(values, size); + + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/QueueAccess.java b/core/src/main/java/de/danoeh/antennapod/core/util/QueueAccess.java index 8e40ae184..7377b202d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/QueueAccess.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/QueueAccess.java @@ -1,10 +1,10 @@ package de.danoeh.antennapod.core.util; -import de.danoeh.antennapod.core.feed.FeedItem; - import java.util.Iterator; import java.util.List; +import de.danoeh.antennapod.core.feed.FeedItem; + /** * 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. @@ -25,23 +25,6 @@ public abstract class QueueAccess { 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) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index 26dd2ec4c..17c752bb6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -1,7 +1,13 @@ package de.danoeh.antennapod.core.util.playback; import android.app.Activity; -import android.content.*; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.content.SharedPreferences; import android.content.res.TypedArray; import android.media.MediaPlayer; import android.os.AsyncTask; @@ -19,6 +25,13 @@ import android.widget.TextView; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; +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 de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.Chapter; @@ -33,8 +46,6 @@ import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.playback.Playable.PlayableUtils; -import java.util.concurrent.*; - /** * Communicates with the playback service. GUI classes should use this class to * control playback instead of communicating with the PlaybackService directly. @@ -118,8 +129,7 @@ public abstract class PlaybackController { * example in the activity's onStop() method. */ public void release() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Releasing PlaybackController"); + Log.d(TAG, "Releasing PlaybackController"); try { activity.unregisterReceiver(statusUpdate); @@ -177,7 +187,7 @@ public abstract class PlaybackController { boolean bound = false; if (!PlaybackService.started) { if (serviceIntent != null) { - if (BuildConfig.DEBUG) Log.d(TAG, "Calling start service"); + Log.d(TAG, "Calling start service"); activity.startService(serviceIntent); bound = activity.bindService(serviceIntent, mConnection, 0); } else { @@ -186,14 +196,11 @@ public abstract class PlaybackController { handleStatus(); } } else { - if (BuildConfig.DEBUG) - Log.d(TAG, - "PlaybackService is running, trying to connect without start command."); + Log.d(TAG, "PlaybackService is running, trying to connect without start command."); bound = activity.bindService(new Intent(activity, PlaybackService.class), mConnection, 0); } - if (BuildConfig.DEBUG) - Log.d(TAG, "Result for service binding: " + bound); + Log.d(TAG, "Result for service binding: " + bound); } }; intentLoader.execute(); @@ -272,8 +279,7 @@ public abstract class PlaybackController { .getService(); if (!released) { queryService(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Connection to Service established"); + Log.d(TAG, "Connection to Service established"); } else { Log.i(TAG, "Connection to playback service has been established, but controller has already been released"); } @@ -282,9 +288,7 @@ public abstract class PlaybackController { @Override public void onServiceDisconnected(ComponentName name) { playbackService = null; - if (BuildConfig.DEBUG) - Log.d(TAG, "Disconnected from Service"); - + Log.d(TAG, "Disconnected from Service"); } }; -- cgit v1.2.3