From 9f8630869068208f1bb877a609ce62290f9dd6e1 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 4 Jun 2016 12:45:33 +0200 Subject: On resume, check if the feeds should be (automatically) refreshed. --- .../core/preferences/UserPreferences.java | 11 +++--- .../de/danoeh/antennapod/core/storage/DBTasks.java | 39 +++++++++++++++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index b5bbb0350..ceb96455f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -331,7 +331,10 @@ public class UserPreferences { } - + /* + * Returns update interval in milliseconds; value 0 means that auto update is disabled + * or feeds are updated at a certain time of day + */ public static long getUpdateInterval() { String updateInterval = prefs.getString(PREF_UPDATE_INTERVAL, "0"); if(!updateInterval.contains(":")) { @@ -743,12 +746,12 @@ public class UserPreferences { if (timeOfDay.length == 2) { restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]); } else { - long hours = getUpdateInterval(); - long startTrigger = hours; + long milliseconds = getUpdateInterval(); + long startTrigger = milliseconds; if (now) { startTrigger = TimeUnit.SECONDS.toMillis(10); } - restartUpdateIntervalAlarm(startTrigger, hours); + restartUpdateIntervalAlarm(startTrigger, milliseconds); } } 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 75bbd4adc..567ffc07a 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 @@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.database.Cursor; import android.util.Log; @@ -16,7 +17,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; -import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import de.danoeh.antennapod.core.ClientConfig; @@ -27,21 +28,29 @@ import de.danoeh.antennapod.core.feed.Feed; 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.preferences.UserPreferences; 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.Converter; import de.danoeh.antennapod.core.util.DownloadError; 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; +import static android.content.Context.MODE_PRIVATE; +import static android.provider.Contacts.SettingsColumns.KEY; + /** * Provides methods for doing common tasks that use DBReader and DBWriter. */ public final class DBTasks { private static final String TAG = "DBTasks"; + public static final String PREF_NAME = "dbtasks"; + private static final String PREF_LAST_REFRESH = "last_refresh"; + /** * Executor service used by the autodownloadUndownloadedEpisodes method. */ @@ -162,6 +171,9 @@ public final class DBTasks { } isRefreshing.set(false); + SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE); + prefs.edit().putLong(PREF_LAST_REFRESH, System.currentTimeMillis()).apply(); + if (FlattrUtils.hasToken()) { Log.d(TAG, "Flattring all pending things."); new FlattrClickWorker(context).executeAsync(); // flattr pending things @@ -313,6 +325,31 @@ public final class DBTasks { DownloadRequester.getInstance().downloadFeed(context, f, loadAllPages, force); } + /* + * Checks if the app should refresh all feeds, i.e. if the last auto refresh failed. + * + * The feeds are only refreshed if an update interval or time of day is set and the last + * (successful) refresh was before the last interval or more than a day ago, respectively. + */ + public static void checkShouldRefreshFeeds(Context context) { + long interval = 0; + if(UserPreferences.getUpdateInterval() > 0) { + interval = UserPreferences.getUpdateInterval(); + } else if(UserPreferences.getUpdateTimeOfDay().length > 0){ + interval = TimeUnit.DAYS.toMillis(1); + } + if(interval == 0) { // auto refresh is disabled + return; + } + SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE); + long lastRefresh = prefs.getLong(PREF_LAST_REFRESH, 0); + Log.d(TAG, "last refresh: " + Converter.getDurationStringLocalized(context, + System.currentTimeMillis() - lastRefresh) + " ago"); + if(lastRefresh <= System.currentTimeMillis() - interval) { + DBTasks.refreshAllFeeds(context, null); + } + } + /** * Notifies the database about a missing FeedMedia file. This method will correct the FeedMedia object's values in the * DB and send a FeedUpdateBroadcast. -- cgit v1.2.3 From e7cc0ffe05cd568c784431333df56ecae9a03762 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 26 Aug 2016 12:26:12 -0400 Subject: Enable separate functions for Previous and Rewind hardware buttons. Added prefHardwarePreviousButtonRestarts preference. --- .../de/danoeh/antennapod/core/preferences/UserPreferences.java | 5 +++++ .../danoeh/antennapod/core/service/playback/PlaybackService.java | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 0772597a2..7c01b7fef 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -65,6 +65,7 @@ public class UserPreferences { public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect"; public static final String PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT = "prefUnpauseOnBluetoothReconnect"; public static final String PREF_HARDWARE_FOWARD_BUTTON_SKIPS = "prefHardwareForwardButtonSkips"; + public static final String PREF_HARDWARE_PREVIOUS_BUTTON_RESTARTS = "prefHardwarePreviousButtonRestarts"; public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue"; public static final String PREF_SKIP_KEEPS_EPISODE = "prefSkipKeepsEpisode"; public static final String PREF_AUTO_DELETE = "prefAutoDelete"; @@ -282,6 +283,10 @@ public class UserPreferences { return prefs.getBoolean(PREF_HARDWARE_FOWARD_BUTTON_SKIPS, false); } + public static boolean shouldHardwarePreviousButtonRestart() { + return prefs.getBoolean(PREF_HARDWARE_PREVIOUS_BUTTON_RESTARTS, false); + } + public static boolean isFollowQueue() { return prefs.getBoolean(PREF_FOLLOW_QUEUE, true); 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 04b5b676d..15656de3b 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 @@ -478,6 +478,14 @@ public class PlaybackService extends MediaBrowserServiceCompat { mediaPlayer.seekDelta(UserPreferences.getFastFowardSecs() * 1000); break; case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + if(UserPreferences.shouldHardwarePreviousButtonRestart()) { + // user wants to restart current episode + mediaPlayer.seekTo(0); + } else { + // user wants to rewind current episode + mediaPlayer.seekDelta(-UserPreferences.getRewindSecs() * 1000); + } + break; case KeyEvent.KEYCODE_MEDIA_REWIND: mediaPlayer.seekDelta(-UserPreferences.getRewindSecs() * 1000); break; -- cgit v1.2.3 From 01c3f757a15679b18c3e5bf66074a877e6ed40cb Mon Sep 17 00:00:00 2001 From: orionlee Date: Fri, 9 Sep 2016 09:00:36 -0700 Subject: Issue #2105 : support optional rewind in lockscreen (by using skipToPrevious button) --- .../core/service/playback/PlaybackService.java | 25 ++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'core/src/main/java/de') 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 04b5b676d..d840c9fad 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 @@ -996,13 +996,34 @@ public class PlaybackService extends MediaBrowserServiceCompat { state = PlaybackStateCompat.STATE_NONE; } sessionState.setState(state, mediaPlayer.getPosition(), mediaPlayer.getPlaybackSpeed()); - sessionState.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE + long capabilities = PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_REWIND | PlaybackStateCompat.ACTION_FAST_FORWARD - | PlaybackStateCompat.ACTION_SKIP_TO_NEXT); + | PlaybackStateCompat.ACTION_SKIP_TO_NEXT; + + if (useSkipToPreviousForRewindInLockscreen()) { + // Workaround to fool Android so that Lockscreen will expose a skip-to-previous button, + // which will be used for rewind. + // + // @see #sessionCallback in the backing callback, skipToPrevious implementation + // is actually the same as rewind. So no new inconsistency is created. + capabilities = capabilities | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; + } + + sessionState.setActions(capabilities); mediaSession.setPlaybackState(sessionState.build()); } + private static boolean useSkipToPreviousForRewindInLockscreen() { + // showRewindOnCompactNotification() corresponds to the "Set Lockscreen Buttons" + // Settings in UI. + // Hence, from user perspective, he/she is setting the buttons for Loackscreen + // + // OPEN: it might contain other logic, e.g., the woakround might be applicable + // only to prev-Androidv5 devices. + return UserPreferences.showRewindOnCompactNotification(); + } + /** * Used by updateMediaSessionMetadata to load notification data in another thread. */ -- cgit v1.2.3 From 209058b3a7be15d8b3837ace29822eeb6d52960d Mon Sep 17 00:00:00 2001 From: orionlee Date: Sat, 10 Sep 2016 12:04:01 -0700 Subject: Make it explicit the lockscreen workaround is only relevant to pre Lollipop devices. --- .../antennapod/core/service/playback/PlaybackService.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'core/src/main/java/de') 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 d840c9fad..eca3d1bb9 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 @@ -1004,9 +1004,14 @@ public class PlaybackService extends MediaBrowserServiceCompat { if (useSkipToPreviousForRewindInLockscreen()) { // Workaround to fool Android so that Lockscreen will expose a skip-to-previous button, // which will be used for rewind. + // The workaround is used for pre Lollipop (Androidv5) devices. + // For Androidv5+, lockscreen widges are really notifications (compact), + // with an independent codepath // // @see #sessionCallback in the backing callback, skipToPrevious implementation - // is actually the same as rewind. So no new inconsistency is created. + // is actually the same as rewind. So no new inconsistency is created. + // @see #setupNotification() for the method to create Androidv5+ lockscreen UI + // with notification (compact) capabilities = capabilities | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; } @@ -1017,11 +1022,9 @@ public class PlaybackService extends MediaBrowserServiceCompat { private static boolean useSkipToPreviousForRewindInLockscreen() { // showRewindOnCompactNotification() corresponds to the "Set Lockscreen Buttons" // Settings in UI. - // Hence, from user perspective, he/she is setting the buttons for Loackscreen - // - // OPEN: it might contain other logic, e.g., the woakround might be applicable - // only to prev-Androidv5 devices. - return UserPreferences.showRewindOnCompactNotification(); + // Hence, from user perspective, he/she is setting the buttons for Lockscreen + return ( UserPreferences.showRewindOnCompactNotification() && + (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) ); } /** -- cgit v1.2.3 From 68b7431aac8ac62fc437f05cf72472969fe1b69e Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Fri, 23 Sep 2016 13:55:43 +0100 Subject: Use summary tag if content is not available --- .../danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index 52b05aa98..ec7ebe1ac 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -30,6 +30,7 @@ public class NSAtom extends Namespace { private static final String AUTHOR = "author"; private static final String AUTHOR_NAME = "name"; private static final String CONTENT = "content"; + private static final String SUMMARY = "summary"; private static final String IMAGE_LOGO = "logo"; private static final String IMAGE_ICON = "icon"; private static final String SUBTITLE = "subtitle"; @@ -59,8 +60,8 @@ public class NSAtom extends Namespace { /** * Regexp to test whether an Element is a Text Element. */ - private static final String isText = TITLE + "|" + CONTENT + "|" + "|" - + SUBTITLE; + private static final String isText = TITLE + "|" + CONTENT + "|" + + SUBTITLE + "|" + SUMMARY; public static final String isFeed = FEED + "|" + NSRSS20.CHANNEL; public static final String isFeedItem = ENTRY + "|" + NSRSS20.ITEM; @@ -191,6 +192,9 @@ public class NSAtom extends Namespace { } else if (CONTENT.equals(top) && ENTRY.equals(second) && textElement != null && state.getCurrentItem() != null) { state.getCurrentItem().setDescription(textElement.getProcessedContent()); + } else if (SUMMARY.equals(top) && ENTRY.equals(second) && textElement != null && + state.getCurrentItem() != null && state.getCurrentItem().getDescription() == null) { + state.getCurrentItem().setDescription(textElement.getProcessedContent()); } else if (UPDATED.equals(top) && ENTRY.equals(second) && state.getCurrentItem() != null && state.getCurrentItem().getPubDate() == null) { state.getCurrentItem().setPubDate(DateUtils.parse(content)); -- cgit v1.2.3 From ba37684d7c1664f638daae87a8b7d9ee519fd235 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 3 Oct 2016 11:46:02 +0200 Subject: Add option to show number of downloaded episodes as subscription counter --- .../core/preferences/UserPreferences.java | 16 +++---- .../antennapod/core/storage/PodDBAdapter.java | 51 +++++++++++++--------- 2 files changed, 39 insertions(+), 28 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index d5a1007af..aa3bbaeab 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -56,7 +56,6 @@ public class UserPreferences { public static final String PREF_LOCKSCREEN_BACKGROUND = "prefLockscreenBackground"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; - // Queue public static final String PREF_QUEUE_ADD_TO_FRONT = "prefQueueAddToFront"; @@ -123,13 +122,14 @@ public class UserPreferences { private static final int NOTIFICATION_BUTTON_FAST_FORWARD = 1; private static final int NOTIFICATION_BUTTON_SKIP = 2; private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; - public static int FEED_ORDER_COUNTER = 0; - public static int FEED_ORDER_ALPHABETICAL = 1; - public static int FEED_ORDER_LAST_UPDATE = 2; - public static int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0; - public static int FEED_COUNTER_SHOW_NEW = 1; - public static int FEED_COUNTER_SHOW_UNPLAYED = 2; - public static int FEED_COUNTER_SHOW_NONE = 3; + public static final int FEED_ORDER_COUNTER = 0; + public static final int FEED_ORDER_ALPHABETICAL = 1; + public static final int FEED_ORDER_LAST_UPDATE = 2; + public static final int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0; + public static final int FEED_COUNTER_SHOW_NEW = 1; + public static final int FEED_COUNTER_SHOW_UNPLAYED = 2; + public static final int FEED_COUNTER_SHOW_NONE = 3; + public static final int FEED_COUNTER_SHOW_DOWNLOADED = 4; private static Context context; private static SharedPreferences prefs; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 7631d26d5..b0d053f5a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -42,12 +42,12 @@ import de.greenrobot.event.EventBus; public class PodDBAdapter { private static final String TAG = "PodDBAdapter"; - public static final String DATABASE_NAME = "Antennapod.db"; + private static final String DATABASE_NAME = "Antennapod.db"; /** * Maximum number of arguments for IN-operator. */ - public static final int IN_OPERATOR_MAXIMUM = 800; + private static final int IN_OPERATOR_MAXIMUM = 800; /** * Maximum number of entries per search request. @@ -109,14 +109,14 @@ public class PodDBAdapter { public static final String KEY_EXCLUDE_FILTER = "exclude_filter"; // Table names - public static final String TABLE_NAME_FEEDS = "Feeds"; - public static final String TABLE_NAME_FEED_ITEMS = "FeedItems"; - public static final String TABLE_NAME_FEED_IMAGES = "FeedImages"; - public static final String TABLE_NAME_FEED_MEDIA = "FeedMedia"; - public static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog"; - public static final String TABLE_NAME_QUEUE = "Queue"; - public static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters"; - public static final String TABLE_NAME_FAVORITES = "Favorites"; + private static final String TABLE_NAME_FEEDS = "Feeds"; + private static final String TABLE_NAME_FEED_ITEMS = "FeedItems"; + private static final String TABLE_NAME_FEED_IMAGES = "FeedImages"; + private static final String TABLE_NAME_FEED_MEDIA = "FeedMedia"; + private static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog"; + private static final String TABLE_NAME_QUEUE = "Queue"; + private static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters"; + private static final String TABLE_NAME_FAVORITES = "Favorites"; // SQL Statements for creating new tables private static final String TABLE_PRIMARY_KEY = KEY_ID @@ -1436,15 +1436,24 @@ public class PodDBAdapter { public final LongIntMap getFeedCounters(long... feedIds) { int setting = UserPreferences.getFeedCounterSetting(); String whereRead; - if(setting == UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM) { - whereRead = "(" + KEY_READ + "=" + FeedItem.NEW - + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; - } else if(setting == UserPreferences.FEED_COUNTER_SHOW_NEW) { - whereRead = KEY_READ + "=" + FeedItem.NEW; - } else if(setting == UserPreferences.FEED_COUNTER_SHOW_UNPLAYED) { - whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; - } else { // NONE - return new LongIntMap(0); + switch(setting) { + case UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM: + whereRead = "(" + KEY_READ + "=" + FeedItem.NEW + + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; + break; + case UserPreferences.FEED_COUNTER_SHOW_NEW: + whereRead = KEY_READ + "=" + FeedItem.NEW; + break; + case UserPreferences.FEED_COUNTER_SHOW_UNPLAYED: + whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; + break; + case UserPreferences.FEED_COUNTER_SHOW_DOWNLOADED: + whereRead = KEY_DOWNLOADED + "=1"; + break; + case UserPreferences.FEED_COUNTER_SHOW_NONE: + // deliberate fall-through + default: // NONE + return new LongIntMap(0); } // work around TextUtils.join wanting only boxed items @@ -1459,8 +1468,10 @@ public class PodDBAdapter { builder.deleteCharAt(builder.length() - 1); } - final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count " + final String query = "SELECT " + KEY_FEED + ", COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ") AS count " + " FROM " + TABLE_NAME_FEED_ITEMS + + " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON " + + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") " + " AND " + whereRead + " GROUP BY " + KEY_FEED; -- cgit v1.2.3 From 25c1936c7c6a961e57c50acbfe8141168feff382 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 3 Oct 2016 12:06:58 +0200 Subject: Feed media is only valid when download url is not empty --- .../core/syndication/handler/SyndHandler.java | 19 +++------- .../core/syndication/namespace/NSRSS20.java | 43 ++++++++++++---------- 2 files changed, 29 insertions(+), 33 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java index 47503dee4..ae91c0743 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java @@ -6,7 +6,6 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.syndication.namespace.NSContent; import de.danoeh.antennapod.core.syndication.namespace.NSDublinCore; @@ -86,34 +85,28 @@ public class SyndHandler extends DefaultHandler { state.defaultNamespaces.push(new NSAtom()); } else if (prefix.equals(NSAtom.NSTAG)) { state.namespaces.put(uri, new NSAtom()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized Atom namespace"); + Log.d(TAG, "Recognized Atom namespace"); } } else if (uri.equals(NSContent.NSURI) && prefix.equals(NSContent.NSTAG)) { state.namespaces.put(uri, new NSContent()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized Content namespace"); + Log.d(TAG, "Recognized Content namespace"); } else if (uri.equals(NSITunes.NSURI) && prefix.equals(NSITunes.NSTAG)) { state.namespaces.put(uri, new NSITunes()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized ITunes namespace"); + Log.d(TAG, "Recognized ITunes namespace"); } else if (uri.equals(NSSimpleChapters.NSURI) && prefix.matches(NSSimpleChapters.NSTAG)) { state.namespaces.put(uri, new NSSimpleChapters()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized SimpleChapters namespace"); + Log.d(TAG, "Recognized SimpleChapters namespace"); } else if (uri.equals(NSMedia.NSURI) && prefix.equals(NSMedia.NSTAG)) { state.namespaces.put(uri, new NSMedia()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized media namespace"); + Log.d(TAG, "Recognized media namespace"); } else if (uri.equals(NSDublinCore.NSURI) && prefix.equals(NSDublinCore.NSTAG)) { state.namespaces.put(uri, new NSDublinCore()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized DublinCore namespace"); + Log.d(TAG, "Recognized DublinCore namespace"); } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index a5ca9d6f4..c91444552 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -20,25 +20,27 @@ import de.danoeh.antennapod.core.util.DateUtils; * */ public class NSRSS20 extends Namespace { - private static final String TAG = "NSRSS20"; - public static final String NSTAG = "rss"; - public static final String NSURI = ""; - public static final String CHANNEL = "channel"; + private static final String TAG = "NSRSS20"; + + private static final String NSTAG = "rss"; + private static final String NSURI = ""; + + public static final String CHANNEL = "channel"; public static final String ITEM = "item"; - public static final String GUID = "guid"; - public static final String TITLE = "title"; - public static final String LINK = "link"; - public static final String DESCR = "description"; - public static final String PUBDATE = "pubDate"; - public static final String ENCLOSURE = "enclosure"; - public static final String IMAGE = "image"; - public static final String URL = "url"; - public static final String LANGUAGE = "language"; + private static final String GUID = "guid"; + private static final String TITLE = "title"; + private static final String LINK = "link"; + private static final String DESCR = "description"; + private static final String PUBDATE = "pubDate"; + private static final String ENCLOSURE = "enclosure"; + private static final String IMAGE = "image"; + private static final String URL = "url"; + private static final String LANGUAGE = "language"; - public static final String ENC_URL = "url"; - public static final String ENC_LEN = "length"; - public static final String ENC_TYPE = "type"; + private static final String ENC_URL = "url"; + private static final String ENC_LEN = "length"; + private static final String ENC_TYPE = "type"; @Override public SyndElement handleElementStart(String localName, HandlerState state, @@ -55,11 +57,12 @@ public class NSRSS20 extends Namespace { if(SyndTypeUtils.enclosureTypeValid(type)) { validType = true; } else { - type = type = SyndTypeUtils.getValidMimeTypeFromUrl(url); + type = SyndTypeUtils.getValidMimeTypeFromUrl(url); validType = type != null; } + boolean validUrl = !TextUtils.isEmpty(url); if (state.getCurrentItem() != null && state.getCurrentItem().getMedia() == null && - validType) { + validType && validUrl) { long size = 0; try { size = Long.parseLong(attributes.getValue(ENC_LEN)); @@ -70,8 +73,8 @@ public class NSRSS20 extends Namespace { } catch (NumberFormatException e) { Log.d(TAG, "Length attribute could not be parsed."); } - state.getCurrentItem().setMedia( - new FeedMedia(state.getCurrentItem(), url, size, type)); + FeedMedia media = new FeedMedia(state.getCurrentItem(), url, size, type); + state.getCurrentItem().setMedia(media); } } else if (IMAGE.equals(localName)) { -- cgit v1.2.3 From 92899affab62873ca855d5dfcdc05bfa5fea47b7 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 3 Oct 2016 17:21:42 +0200 Subject: Add "has media" filter to episodes filter --- .../main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java index 9d8f4adf8..200153876 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java @@ -18,6 +18,7 @@ public class FeedItemFilter { private boolean showNotQueued = false; private boolean showDownloaded = false; private boolean showNotDownloaded = false; + private boolean showHasMedia = false; public FeedItemFilter(String properties) { this(TextUtils.split(properties, ",")); @@ -49,6 +50,9 @@ public class FeedItemFilter { case "not_downloaded": showNotDownloaded = true; break; + case "has_media": + showHasMedia = true; + break; } } } @@ -82,6 +86,8 @@ public class FeedItemFilter { if (showDownloaded && !downloaded) continue; if (showNotDownloaded && downloaded) continue; + if (showHasMedia && !item.hasMedia()) continue; + // If the item reaches here, it meets all criteria result.add(item); } -- cgit v1.2.3 From e75d60ef61600571273376674c5d2842314521a7 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 9 Oct 2016 21:49:23 +0200 Subject: Extract sleep timer preferences into dedicated class --- .../core/preferences/SleepTimerPreferences.java | 71 ++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java new file mode 100644 index 000000000..3871eca22 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java @@ -0,0 +1,71 @@ +package de.danoeh.antennapod.core.preferences; + +import android.content.Context; +import android.content.SharedPreferences; +import android.support.annotation.NonNull; +import android.util.Log; + +public class SleepTimerPreferences { + + private static final String TAG = "SleepTimerPreferences"; + + private static final String PREF_NAME = "SleepTimerDialog"; + private static final String PREF_VALUE = "LastValue"; + private static final String PREF_TIME_UNIT = "LastTimeUnit"; + private static final String PREF_VIBRATE = "Vibrate"; + private static final String PREF_SHAKE_TO_RESET = "ShakeToReset"; + private static final String PREF_AUTO_ENABLE = "AutoEnable"; + + private static final String DEFAULT_VALUE = "15"; + private static final int DEFAULT_TIME_UNIT = 1; + + private static Context context; + private static SharedPreferences prefs; + + /** + * Sets up the UserPreferences class. + * + * @throws IllegalArgumentException if context is null + */ + public static void init(@NonNull Context context) { + Log.d(TAG, "Creating new instance of SleepTimerPreferences"); + SleepTimerPreferences.prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); + } + + public static void setLastTimer(String value, int timeUnit) { + prefs.edit().putString(PREF_VALUE, value).putInt(PREF_TIME_UNIT, timeUnit).apply(); + } + + public static String lastTimerValue() { + return prefs.getString(PREF_VALUE, DEFAULT_VALUE); + } + + public static int lastTimerTimeUnit() { + return prefs.getInt(PREF_TIME_UNIT, DEFAULT_TIME_UNIT); + } + + public static void setVibrate(boolean vibrate) { + prefs.edit().putBoolean(PREF_VIBRATE, vibrate).apply(); + } + + public static boolean vibrate() { + return prefs.getBoolean(PREF_VIBRATE, true); + } + + public static void setShakeToReset(boolean shakeToReset) { + prefs.edit().putBoolean(PREF_SHAKE_TO_RESET, shakeToReset).apply(); + } + + public static boolean shakeToReset() { + return prefs.getBoolean(PREF_SHAKE_TO_RESET, true); + } + + public static void setAutoEnable(boolean autoEnable) { + prefs.edit().putBoolean(PREF_AUTO_ENABLE, autoEnable).apply(); + } + + public static boolean autoEnable() { + return prefs.getBoolean(PREF_AUTO_ENABLE, false); + } + +} -- cgit v1.2.3 From 21799ab22c6c72b263337678a9d5de68957e12b9 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 9 Oct 2016 22:40:40 +0200 Subject: Add dialog option to auto-enable sleep timer --- .../danoeh/antennapod/core/event/MessageEvent.java | 24 ++++++++++++++++++++++ .../core/preferences/SleepTimerPreferences.java | 9 ++++++++ .../core/service/playback/PlaybackService.java | 10 +++++++++ 3 files changed, 43 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java new file mode 100644 index 000000000..f35bfd14c --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java @@ -0,0 +1,24 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.danoeh.antennapod.core.event; + +public class MessageEvent { + + public final String message; + + public MessageEvent(String message) { + this.message = message; + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java index 3871eca22..b7ed890f5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/SleepTimerPreferences.java @@ -5,6 +5,8 @@ import android.content.SharedPreferences; import android.support.annotation.NonNull; import android.util.Log; +import java.util.concurrent.TimeUnit; + public class SleepTimerPreferences { private static final String TAG = "SleepTimerPreferences"; @@ -16,6 +18,8 @@ public class SleepTimerPreferences { private static final String PREF_SHAKE_TO_RESET = "ShakeToReset"; private static final String PREF_AUTO_ENABLE = "AutoEnable"; + private static final TimeUnit[] UNITS = { TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS }; + private static final String DEFAULT_VALUE = "15"; private static final int DEFAULT_TIME_UNIT = 1; @@ -44,6 +48,11 @@ public class SleepTimerPreferences { return prefs.getInt(PREF_TIME_UNIT, DEFAULT_TIME_UNIT); } + public static long timerMillis() { + long value = Long.parseLong(lastTimerValue()); + return UNITS[lastTimerTimeUnit()].toMillis(value); + } + public static void setVibrate(boolean vibrate) { prefs.edit().putBoolean(PREF_VIBRATE, vibrate).apply(); } 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 e67dc9d0a..b967be6aa 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 @@ -47,12 +47,14 @@ import java.util.List; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; +import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.storage.DBReader; @@ -62,6 +64,7 @@ import de.danoeh.antennapod.core.util.IntList; import de.danoeh.antennapod.core.util.QueueAccess; import de.danoeh.antennapod.core.util.playback.ExternalMedia; import de.danoeh.antennapod.core.util.playback.Playable; +import de.greenrobot.event.EventBus; /** * Controls the MediaPlayer that plays a FeedMedia-file @@ -605,6 +608,11 @@ public class PlaybackService extends MediaBrowserServiceCompat { writePlayerStatusPlaybackPreferences(); setupNotification(newInfo); started = true; + // set sleep timer if auto-enabled + if(SleepTimerPreferences.autoEnable() && !sleepTimerActive()) { + setSleepTimer(SleepTimerPreferences.timerMillis(), SleepTimerPreferences.shakeToReset(), + SleepTimerPreferences.vibrate()); + } break; case ERROR: @@ -846,11 +854,13 @@ public class PlaybackService extends MediaBrowserServiceCompat { Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime) + " milliseconds"); taskManager.setSleepTimer(waitingTime, shakeToReset, vibrate); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); + EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_enabled_label))); } public void disableSleepTimer() { taskManager.disableSleepTimer(); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); + EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_disabled_label))); } private void writePlaybackPreferencesNoMediaPlaying() { -- cgit v1.2.3 From fdc7d41824cef94578469572c0f79c5e06444737 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 12 Oct 2016 17:51:14 +0200 Subject: Replace toast with snackbar and optional undo action --- .../danoeh/antennapod/core/event/MessageEvent.java | 23 ++++++++++------------ .../core/service/playback/PlaybackService.java | 3 ++- 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java index f35bfd14c..9fc488fbc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/event/MessageEvent.java @@ -1,24 +1,21 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package de.danoeh.antennapod.core.event; +import android.support.annotation.Nullable; + public class MessageEvent { public final String message; + @Nullable + public final Runnable action; + public MessageEvent(String message) { + this(message, null); + } + + public MessageEvent(String message, Runnable action) { this.message = message; + this.action = action; } } 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 b967be6aa..33aec0ee0 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 @@ -854,7 +854,8 @@ public class PlaybackService extends MediaBrowserServiceCompat { Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime) + " milliseconds"); taskManager.setSleepTimer(waitingTime, shakeToReset, vibrate); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); - EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_enabled_label))); + EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_enabled_label), + () -> disableSleepTimer())); } public void disableSleepTimer() { -- cgit v1.2.3 From 7fe1e07048ffe9e80bd6e722e7a8b30922fb2e55 Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Wed, 5 Oct 2016 17:34:05 +0100 Subject: Support multiple author tags in a feed --- .../danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index ec7ebe1ac..89070155b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -206,7 +206,12 @@ public class NSAtom extends Namespace { state.getFeed().setImage(new FeedImage(state.getFeed(), content, null)); } else if (AUTHOR.equals(second) && state.getFeed() != null) { if (AUTHOR_NAME.equals(top)) { - state.getFeed().setAuthor(content); + String currentName = state.getFeed().getAuthor(); + if (currentName == null) { + state.getFeed().setAuthor(content); + } else { + state.getFeed().setAuthor(currentName + ", " + content); + } } } } -- cgit v1.2.3 From 85e08a270aab885f6630cde668e3ba2df30b10e9 Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Thu, 6 Oct 2016 09:40:18 +0100 Subject: Suport archive RSS/Atom links as alternate feeds --- .../antennapod/core/syndication/namespace/atom/NSAtom.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index 89070155b..5443678ea 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -45,6 +45,7 @@ public class NSAtom extends Namespace { private static final String LINK_LENGTH = "length"; // rel-values private static final String LINK_REL_ALTERNATE = "alternate"; + private static final String LINK_REL_ARCHIVES = "archives"; private static final String LINK_REL_ENCLOSURE = "enclosure"; private static final String LINK_REL_PAYMENT = "payment"; private static final String LINK_REL_RELATED = "related"; @@ -130,6 +131,17 @@ public class NSAtom extends Namespace { } state.addAlternateFeedUrl(title, href); } + } else if (LINK_REL_ARCHIVES.equals(rel) && state.getFeed() != null) { + String type = attributes.getValue(LINK_TYPE); + if (LINK_TYPE_ATOM.equals(type) || LINK_TYPE_RSS.equals(type)) { + String title = attributes.getValue(LINK_TITLE); + if (TextUtils.isEmpty(title)) { + title = href; + } + state.addAlternateFeedUrl(title, href); + } else if (LINK_TYPE_HTML.equals(type) || LINK_TYPE_XHTML.equals(type)) { + //A Link such as to a directory such as iTunes + } } else if (LINK_REL_PAYMENT.equals(rel) && state.getFeed() != null) { state.getFeed().setPaymentLink(href); } else if (LINK_REL_NEXT.equals(rel) && state.getFeed() != null) { -- cgit v1.2.3 From 0f7fe57454c8fd3c312daa479b2e141a39d56f6b Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Tue, 11 Oct 2016 14:54:46 +0100 Subject: Add support for images in mrss content SyndTypeUtils.getValidMimeTypeFromUrl is now unused and SyndTypeUtils.getMimeTypeFromUrl is used instead. It gets the mime type from the file extension, but dosen't check it so this function can how be used for both images or media files. --- .../core/syndication/namespace/NSMedia.java | 34 ++++++++++++++++++---- .../core/syndication/namespace/NSRSS20.java | 13 +++++---- .../core/syndication/namespace/atom/NSAtom.java | 12 ++++---- .../core/syndication/util/SyndTypeUtils.java | 29 ++++++++++++++++-- 4 files changed, 68 insertions(+), 20 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java index 839e2ae0c..f2cfc2e57 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java @@ -26,6 +26,11 @@ public class NSMedia extends Namespace { private static final String MIME_TYPE = "type"; private static final String DURATION = "duration"; private static final String DEFAULT = "isDefault"; + private static final String MEDIUM = "medium"; + + private static final String MEDIUM_IMAGE = "image"; + private static final String MEDIUM_AUDIO = "audio"; + private static final String MEDIUM_VIDEO = "video"; private static final String IMAGE = "thumbnail"; private static final String IMAGE_URL = "url"; @@ -40,20 +45,31 @@ public class NSMedia extends Namespace { String url = attributes.getValue(DOWNLOAD_URL); String type = attributes.getValue(MIME_TYPE); String defaultStr = attributes.getValue(DEFAULT); - boolean validType; + String medium = attributes.getValue(MEDIUM); + boolean validTypeMedia = false; + boolean validTypeImage = false; boolean isDefault = "true".equals(defaultStr); - if (SyndTypeUtils.enclosureTypeValid(type)) { - validType = true; + if (MEDIUM_AUDIO.equals(medium) || MEDIUM_VIDEO.equals(medium)) { + validTypeMedia = true; + } else if (MEDIUM_IMAGE.equals(medium)) { + validTypeImage = true; } else { - type = SyndTypeUtils.getValidMimeTypeFromUrl(url); - validType = type != null; + if (type == null) { + type = SyndTypeUtils.getMimeTypeFromUrl(url); + } + + if (SyndTypeUtils.enclosureTypeValid(type)) { + validTypeMedia = true; + } else if (SyndTypeUtils.imageTypeValid(type)) { + validTypeImage = true; + } } if (state.getCurrentItem() != null && (state.getCurrentItem().getMedia() == null || isDefault) && - url != null && validType) { + url != null && validTypeMedia) { long size = 0; String sizeStr = attributes.getValue(SIZE); try { @@ -77,6 +93,12 @@ public class NSMedia extends Namespace { media.setDuration(durationMs); } state.getCurrentItem().setMedia(media); + } else if (state.getCurrentItem() != null && url != null && validTypeImage) { + FeedImage image = new FeedImage(); + image.setDownload_url(url); + image.setOwner(state.getCurrentItem()); + + state.getCurrentItem().setImage(image); } } else if (IMAGE.equals(localName)) { String url = attributes.getValue(IMAGE_URL); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index c91444552..90dd67a0b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -53,14 +53,17 @@ public class NSRSS20 extends Namespace { } else if (ENCLOSURE.equals(localName)) { String type = attributes.getValue(ENC_TYPE); String url = attributes.getValue(ENC_URL); - boolean validType; + boolean validType = false; + boolean validUrl = !TextUtils.isEmpty(url); + + if (type == null) { + type = SyndTypeUtils.getMimeTypeFromUrl(url); + } + if(SyndTypeUtils.enclosureTypeValid(type)) { validType = true; - } else { - type = SyndTypeUtils.getValidMimeTypeFromUrl(url); - validType = type != null; } - boolean validUrl = !TextUtils.isEmpty(url); + if (state.getCurrentItem() != null && state.getCurrentItem().getMedia() == null && validType && validUrl) { long size = 0; diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index 5443678ea..b14f84c7a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -95,14 +95,12 @@ public class NSAtom extends Namespace { Log.d(TAG, "Length attribute could not be parsed."); } String type = attributes.getValue(LINK_TYPE); - boolean validType; - if(SyndTypeUtils.enclosureTypeValid(type)) { - validType = true; - } else { - type = SyndTypeUtils.getValidMimeTypeFromUrl(href); - validType = type != null; + + if (type == null) { + type = SyndTypeUtils.getMimeTypeFromUrl(href); } - if (validType) { + + if(SyndTypeUtils.enclosureTypeValid(type)) { FeedItem currItem = state.getCurrentItem(); if(currItem != null && !currItem.hasMedia()) { currItem.setMedia(new FeedMedia(currItem, href, size, type)); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java index d228b9ef7..3c92805b2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java @@ -6,8 +6,10 @@ import org.apache.commons.io.FilenameUtils; /** Utility class for handling MIME-Types of enclosures */ public class SyndTypeUtils { - private static final String VALID_MIMETYPE = "audio/.*" + "|" + "video/.*" + private static final String VALID_MEDIA_MIMETYPE = "audio/.*" + "|" + "video/.*" + "|" + "application/ogg"; + private static final String VALID_IMAGE_MIMETYPE = "image/.*"; + private SyndTypeUtils() { @@ -17,10 +19,18 @@ public class SyndTypeUtils { if (type == null) { return false; } else { - return type.matches(VALID_MIMETYPE); + return type.matches(VALID_MEDIA_MIMETYPE); + } + } + public static boolean imageTypeValid(String type) { + if (type == null) { + return false; + } else { + return type.matches(VALID_IMAGE_MIMETYPE); } } + /** * Should be used if mime-type of enclosure tag is not supported. This * method will check if the mime-type of the file extension is supported. If @@ -38,4 +48,19 @@ public class SyndTypeUtils { } return null; } + + /** + * Should be used if mime-type of enclosure tag is not supported. This + * method will return the mime-type of the file extension. + */ + public static String getMimeTypeFromUrl(String url) { + if (url != null) { + String extension = FilenameUtils.getExtension(url); + if (extension != null) { + return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + } + } + return null; + } + } -- cgit v1.2.3 From 2c17e033972a0498a15b58f9fb206c6d8d025d5b Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Thu, 13 Oct 2016 05:56:26 +0100 Subject: Improve readablilty --- .../core/syndication/util/SyndTypeUtils.java | 29 ++++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java index 3c92805b2..5b12fa772 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java @@ -37,16 +37,12 @@ public class SyndTypeUtils { * the type is not supported, this method will return null. */ public static String getValidMimeTypeFromUrl(String url) { - if (url != null) { - String extension = FilenameUtils.getExtension(url); - if (extension != null) { - String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - if (type != null && enclosureTypeValid(type)) { - return type; - } - } + String type = getMimeTypeFromUrl(url); + if (enclosureTypeValid(type)) { + return type; + } else { + return null; } - return null; } /** @@ -54,13 +50,14 @@ public class SyndTypeUtils { * method will return the mime-type of the file extension. */ public static String getMimeTypeFromUrl(String url) { - if (url != null) { - String extension = FilenameUtils.getExtension(url); - if (extension != null) { - return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - } + if (url == null) { + return null; + } + String extension = FilenameUtils.getExtension(url); + if (extension == null) { + return null; } - return null; - } + return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + } } -- cgit v1.2.3 From fee2acb5ab7a9c7b39ce8b85241ecf939a8c4f2f Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 15 Oct 2016 12:43:03 +0200 Subject: Move opml package --- .../antennapod/core/export/opml/OpmlElement.java | 46 +++++++++++ .../antennapod/core/export/opml/OpmlReader.java | 89 ++++++++++++++++++++++ .../antennapod/core/export/opml/OpmlSymbols.java | 22 ++++++ .../antennapod/core/export/opml/OpmlWriter.java | 86 +++++++++++++++++++++ .../danoeh/antennapod/core/opml/OpmlElement.java | 46 ----------- .../de/danoeh/antennapod/core/opml/OpmlReader.java | 89 ---------------------- .../danoeh/antennapod/core/opml/OpmlSymbols.java | 22 ------ .../de/danoeh/antennapod/core/opml/OpmlWriter.java | 86 --------------------- 8 files changed, 243 insertions(+), 243 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java new file mode 100644 index 000000000..61eb4d0c9 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java @@ -0,0 +1,46 @@ +package de.danoeh.antennapod.core.export.opml; + +/** Represents a single feed in an OPML file. */ +public class OpmlElement { + private String text; + private String xmlUrl; + private String htmlUrl; + private String type; + + public OpmlElement() { + + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getXmlUrl() { + return xmlUrl; + } + + public void setXmlUrl(String xmlUrl) { + this.xmlUrl = xmlUrl; + } + + public String getHtmlUrl() { + return htmlUrl; + } + + public void setHtmlUrl(String htmlUrl) { + this.htmlUrl = htmlUrl; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java new file mode 100644 index 000000000..a17fedd7d --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java @@ -0,0 +1,89 @@ +package de.danoeh.antennapod.core.export.opml; + +import android.util.Log; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; + +import de.danoeh.antennapod.core.BuildConfig; + +/** Reads OPML documents. */ +public class OpmlReader { + private static final String TAG = "OpmlReader"; + + // ATTRIBUTES + private boolean isInOpml = false; + private ArrayList elementList; + + /** + * Reads an Opml document and returns a list of all OPML elements it can + * find + * + * @throws IOException + * @throws XmlPullParserException + */ + public ArrayList readDocument(Reader reader) + throws XmlPullParserException, IOException { + elementList = new ArrayList<>(); + XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + factory.setNamespaceAware(true); + XmlPullParser xpp = factory.newPullParser(); + xpp.setInput(reader); + int eventType = xpp.getEventType(); + + while (eventType != XmlPullParser.END_DOCUMENT) { + switch (eventType) { + case XmlPullParser.START_DOCUMENT: + if (BuildConfig.DEBUG) + Log.d(TAG, "Reached beginning of document"); + break; + case XmlPullParser.START_TAG: + if (xpp.getName().equals(OpmlSymbols.OPML)) { + isInOpml = true; + if (BuildConfig.DEBUG) + Log.d(TAG, "Reached beginning of OPML tree."); + } else if (isInOpml && xpp.getName().equals(OpmlSymbols.OUTLINE)) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Found new Opml element"); + OpmlElement element = new OpmlElement(); + + final String title = xpp.getAttributeValue(null, OpmlSymbols.TITLE); + if (title != null) { + Log.i(TAG, "Using title: " + title); + element.setText(title); + } else { + Log.i(TAG, "Title not found, using text"); + element.setText(xpp.getAttributeValue(null, OpmlSymbols.TEXT)); + } + element.setXmlUrl(xpp.getAttributeValue(null, OpmlSymbols.XMLURL)); + element.setHtmlUrl(xpp.getAttributeValue(null, OpmlSymbols.HTMLURL)); + element.setType(xpp.getAttributeValue(null, OpmlSymbols.TYPE)); + if (element.getXmlUrl() != null) { + if (element.getText() == null) { + Log.i(TAG, "Opml element has no text attribute."); + element.setText(element.getXmlUrl()); + } + elementList.add(element); + } else { + if (BuildConfig.DEBUG) + Log.d(TAG, + "Skipping element because of missing xml url"); + } + } + break; + } + eventType = xpp.next(); + } + + if (BuildConfig.DEBUG) + Log.d(TAG, "Parsing finished."); + + return elementList; + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java new file mode 100644 index 000000000..8b2c24847 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java @@ -0,0 +1,22 @@ +package de.danoeh.antennapod.core.export.opml; + +/** Contains symbols for reading and writing OPML documents. */ +public final class OpmlSymbols { + + public static final String OPML = "opml"; + public static final String BODY = "body"; + public static final String OUTLINE = "outline"; + public static final String TEXT = "text"; + public static final String XMLURL = "xmlUrl"; + public static final String HTMLURL = "htmlUrl"; + public static final String TYPE = "type"; + public static final String VERSION = "version"; + public static final String HEAD = "head"; + public static final String TITLE = "title"; + public static final String DATE_CREATED = "dateCreated"; + + private OpmlSymbols() { + + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java new file mode 100644 index 000000000..0eaed1563 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java @@ -0,0 +1,86 @@ +package de.danoeh.antennapod.core.export.opml; + +import android.util.Log; +import android.util.Xml; + +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.io.Writer; +import java.util.Date; +import java.util.List; + +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.util.DateUtils; + +/** Writes OPML documents. */ +public class OpmlWriter { + private static final String TAG = "OpmlWriter"; + private static final String ENCODING = "UTF-8"; + private static final String OPML_VERSION = "2.0"; + private static final String OPML_TITLE = "AntennaPod Subscriptions"; + + /** + * Takes a list of feeds and a writer and writes those into an OPML + * document. + * + * @throws IOException + * @throws IllegalStateException + * @throws IllegalArgumentException + */ + public void writeDocument(List feeds, Writer writer) + throws IllegalArgumentException, IllegalStateException, IOException { + Log.d(TAG, "Starting to write document"); + XmlSerializer xs = Xml.newSerializer(); + xs.setOutput(writer); + + xs.startDocument(ENCODING, false); + xs.text("\n"); + xs.startTag(null, OpmlSymbols.OPML); + xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION); + xs.text("\n"); + + xs.text(" "); + xs.startTag(null, OpmlSymbols.HEAD); + xs.text("\n"); + xs.text(" "); + xs.startTag(null, OpmlSymbols.TITLE); + xs.text(OPML_TITLE); + xs.endTag(null, OpmlSymbols.TITLE); + xs.text("\n"); + xs.text(" "); + xs.startTag(null, OpmlSymbols.DATE_CREATED); + xs.text(DateUtils.formatRFC822Date(new Date())); + xs.endTag(null, OpmlSymbols.DATE_CREATED); + xs.text("\n"); + xs.text(" "); + xs.endTag(null, OpmlSymbols.HEAD); + xs.text("\n"); + + xs.text(" "); + xs.startTag(null, OpmlSymbols.BODY); + xs.text("\n"); + for (Feed feed : feeds) { + xs.text(" "); + xs.startTag(null, OpmlSymbols.OUTLINE); + xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle()); + xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle()); + if (feed.getType() != null) { + xs.attribute(null, OpmlSymbols.TYPE, feed.getType()); + } + xs.attribute(null, OpmlSymbols.XMLURL, feed.getDownload_url()); + if (feed.getLink() != null) { + xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink()); + } + xs.endTag(null, OpmlSymbols.OUTLINE); + xs.text("\n"); + } + xs.text(" "); + xs.endTag(null, OpmlSymbols.BODY); + xs.text("\n"); + xs.endTag(null, OpmlSymbols.OPML); + xs.text("\n"); + xs.endDocument(); + Log.d(TAG, "Finished writing document"); + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java deleted file mode 100644 index 8d0a4a842..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java +++ /dev/null @@ -1,46 +0,0 @@ -package de.danoeh.antennapod.core.opml; - -/** Represents a single feed in an OPML file. */ -public class OpmlElement { - private String text; - private String xmlUrl; - private String htmlUrl; - private String type; - - public OpmlElement() { - - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public String getXmlUrl() { - return xmlUrl; - } - - public void setXmlUrl(String xmlUrl) { - this.xmlUrl = xmlUrl; - } - - public String getHtmlUrl() { - return htmlUrl; - } - - public void setHtmlUrl(String htmlUrl) { - this.htmlUrl = htmlUrl; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java deleted file mode 100644 index 17afc7904..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java +++ /dev/null @@ -1,89 +0,0 @@ -package de.danoeh.antennapod.core.opml; - -import android.util.Log; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; - -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; - -import de.danoeh.antennapod.core.BuildConfig; - -/** Reads OPML documents. */ -public class OpmlReader { - private static final String TAG = "OpmlReader"; - - // ATTRIBUTES - private boolean isInOpml = false; - private ArrayList elementList; - - /** - * Reads an Opml document and returns a list of all OPML elements it can - * find - * - * @throws IOException - * @throws XmlPullParserException - */ - public ArrayList readDocument(Reader reader) - throws XmlPullParserException, IOException { - elementList = new ArrayList<>(); - XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); - factory.setNamespaceAware(true); - XmlPullParser xpp = factory.newPullParser(); - xpp.setInput(reader); - int eventType = xpp.getEventType(); - - while (eventType != XmlPullParser.END_DOCUMENT) { - switch (eventType) { - case XmlPullParser.START_DOCUMENT: - if (BuildConfig.DEBUG) - Log.d(TAG, "Reached beginning of document"); - break; - case XmlPullParser.START_TAG: - if (xpp.getName().equals(OpmlSymbols.OPML)) { - isInOpml = true; - if (BuildConfig.DEBUG) - Log.d(TAG, "Reached beginning of OPML tree."); - } else if (isInOpml && xpp.getName().equals(OpmlSymbols.OUTLINE)) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Found new Opml element"); - OpmlElement element = new OpmlElement(); - - final String title = xpp.getAttributeValue(null, OpmlSymbols.TITLE); - if (title != null) { - Log.i(TAG, "Using title: " + title); - element.setText(title); - } else { - Log.i(TAG, "Title not found, using text"); - element.setText(xpp.getAttributeValue(null, OpmlSymbols.TEXT)); - } - element.setXmlUrl(xpp.getAttributeValue(null, OpmlSymbols.XMLURL)); - element.setHtmlUrl(xpp.getAttributeValue(null, OpmlSymbols.HTMLURL)); - element.setType(xpp.getAttributeValue(null, OpmlSymbols.TYPE)); - if (element.getXmlUrl() != null) { - if (element.getText() == null) { - Log.i(TAG, "Opml element has no text attribute."); - element.setText(element.getXmlUrl()); - } - elementList.add(element); - } else { - if (BuildConfig.DEBUG) - Log.d(TAG, - "Skipping element because of missing xml url"); - } - } - break; - } - eventType = xpp.next(); - } - - if (BuildConfig.DEBUG) - Log.d(TAG, "Parsing finished."); - - return elementList; - } - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java deleted file mode 100644 index c973713cb..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.danoeh.antennapod.core.opml; - -/** Contains symbols for reading and writing OPML documents. */ -public final class OpmlSymbols { - - public static final String OPML = "opml"; - public static final String BODY = "body"; - public static final String OUTLINE = "outline"; - public static final String TEXT = "text"; - public static final String XMLURL = "xmlUrl"; - public static final String HTMLURL = "htmlUrl"; - public static final String TYPE = "type"; - public static final String VERSION = "version"; - public static final String HEAD = "head"; - public static final String TITLE = "title"; - public static final String DATE_CREATED = "dateCreated"; - - private OpmlSymbols() { - - } - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java deleted file mode 100644 index 673c602df..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java +++ /dev/null @@ -1,86 +0,0 @@ -package de.danoeh.antennapod.core.opml; - -import android.util.Log; -import android.util.Xml; - -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.io.Writer; -import java.util.Date; -import java.util.List; - -import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.util.DateUtils; - -/** Writes OPML documents. */ -public class OpmlWriter { - private static final String TAG = "OpmlWriter"; - private static final String ENCODING = "UTF-8"; - private static final String OPML_VERSION = "2.0"; - private static final String OPML_TITLE = "AntennaPod Subscriptions"; - - /** - * Takes a list of feeds and a writer and writes those into an OPML - * document. - * - * @throws IOException - * @throws IllegalStateException - * @throws IllegalArgumentException - */ - public void writeDocument(List feeds, Writer writer) - throws IllegalArgumentException, IllegalStateException, IOException { - Log.d(TAG, "Starting to write document"); - XmlSerializer xs = Xml.newSerializer(); - xs.setOutput(writer); - - xs.startDocument(ENCODING, false); - xs.text("\n"); - xs.startTag(null, OpmlSymbols.OPML); - xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION); - xs.text("\n"); - - xs.text(" "); - xs.startTag(null, OpmlSymbols.HEAD); - xs.text("\n"); - xs.text(" "); - xs.startTag(null, OpmlSymbols.TITLE); - xs.text(OPML_TITLE); - xs.endTag(null, OpmlSymbols.TITLE); - xs.text("\n"); - xs.text(" "); - xs.startTag(null, OpmlSymbols.DATE_CREATED); - xs.text(DateUtils.formatRFC822Date(new Date())); - xs.endTag(null, OpmlSymbols.DATE_CREATED); - xs.text("\n"); - xs.text(" "); - xs.endTag(null, OpmlSymbols.HEAD); - xs.text("\n"); - - xs.text(" "); - xs.startTag(null, OpmlSymbols.BODY); - xs.text("\n"); - for (Feed feed : feeds) { - xs.text(" "); - xs.startTag(null, OpmlSymbols.OUTLINE); - xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle()); - xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle()); - if (feed.getType() != null) { - xs.attribute(null, OpmlSymbols.TYPE, feed.getType()); - } - xs.attribute(null, OpmlSymbols.XMLURL, feed.getDownload_url()); - if (feed.getLink() != null) { - xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink()); - } - xs.endTag(null, OpmlSymbols.OUTLINE); - xs.text("\n"); - } - xs.text(" "); - xs.endTag(null, OpmlSymbols.BODY); - xs.text("\n"); - xs.endTag(null, OpmlSymbols.OPML); - xs.text("\n"); - xs.endDocument(); - Log.d(TAG, "Finished writing document"); - } -} -- cgit v1.2.3 From df17d4712837bfb0e811bc8acdf8d6e16a668735 Mon Sep 17 00:00:00 2001 From: Maurice Gilden Date: Sun, 16 Oct 2016 12:14:36 +0200 Subject: PlayLastPlayedMediaIntent now seeks to last position before user starts playback. --- .../de/danoeh/antennapod/core/util/playback/PlaybackController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/java/de') 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 13aadf027..6251cc4a0 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 @@ -216,7 +216,7 @@ public abstract class PlaybackController { Intent serviceIntent = new Intent(activity, PlaybackService.class); serviceIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media); serviceIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED, false); - serviceIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, false); + serviceIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, true); boolean fileExists = media.localFileAvailable(); boolean lastIsStream = PlaybackPreferences.getCurrentEpisodeIsStream(); if (!fileExists && !lastIsStream && media instanceof FeedMedia) { -- cgit v1.2.3 From 99ab34b26f0f996f7b90e00042230ee77707a9db Mon Sep 17 00:00:00 2001 From: Maurice Gilden Date: Sun, 16 Oct 2016 12:15:36 +0200 Subject: Fixed problem with seeking before starting playback. --- .../java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 0871758d0..cad67539b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -383,6 +383,9 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { statusBeforeSeeking = playerStatus; setPlayerStatus(PlayerStatus.SEEKING, media, getPosition()); mediaPlayer.seekTo(t); + if (statusBeforeSeeking == PlayerStatus.PREPARED) { + media.setPosition(t); + } try { seekLatch.await(3, TimeUnit.SECONDS); } catch (InterruptedException e) { -- cgit v1.2.3 From 695a73c09dbb3aff6a1d7cd27de0708ac7d0c40d Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 16 Oct 2016 12:40:01 +0200 Subject: Add option to export subscriptions as HTML --- .../antennapod/core/backup/OpmlBackupAgent.java | 22 +++--- .../antennapod/core/export/CommonSymbols.java | 22 ++++++ .../antennapod/core/export/ExportWriter.java | 29 +++++++ .../antennapod/core/export/html/HtmlSymbols.java | 30 +++++++ .../antennapod/core/export/html/HtmlWriter.java | 92 ++++++++++++++++++++++ .../antennapod/core/export/opml/OpmlSymbols.java | 21 +++-- .../antennapod/core/export/opml/OpmlWriter.java | 10 ++- 7 files changed, 203 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java index 982015314..80ce6cf56 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java @@ -8,6 +8,7 @@ import android.content.Context; import android.os.ParcelFileDescriptor; import android.util.Log; +import org.apache.commons.io.IOUtils; import org.xmlpull.v1.XmlPullParserException; import java.io.ByteArrayOutputStream; @@ -27,10 +28,10 @@ import java.util.ArrayList; import java.util.Arrays; import de.danoeh.antennapod.core.BuildConfig; +import de.danoeh.antennapod.core.export.opml.OpmlElement; +import de.danoeh.antennapod.core.export.opml.OpmlReader; +import de.danoeh.antennapod.core.export.opml.OpmlWriter; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.opml.OpmlElement; -import de.danoeh.antennapod.core.opml.OpmlReader; -import de.danoeh.antennapod.core.opml.OpmlWriter; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; @@ -56,7 +57,9 @@ public class OpmlBackupAgent extends BackupAgentHelper { } } - /** Class for backing up and restoring the OPML file. */ + /** + * Class for backing up and restoring the OPML file. + */ private static class OpmlBackupHelper implements BackupHelper { private static final String TAG = "OpmlBackupHelper"; @@ -64,7 +67,9 @@ public class OpmlBackupAgent extends BackupAgentHelper { private final Context mContext; - /** Checksum of restored OPML file */ + /** + * Checksum of restored OPML file + */ private byte[] mChecksum; public OpmlBackupHelper(Context context) { @@ -170,12 +175,7 @@ public class OpmlBackupAgent extends BackupAgentHelper { } catch (IOException e) { Log.e(TAG, "Failed to restore OPML backup", e); } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - } - } + IOUtils.closeQuietly(reader); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java new file mode 100644 index 000000000..020a0671f --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java @@ -0,0 +1,22 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.danoeh.antennapod.core.export; + +public class CommonSymbols { + + public static final String HEAD = "head"; + public static final String BODY = "body"; + public static final String TITLE = "title"; + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java new file mode 100644 index 000000000..d6a187b21 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java @@ -0,0 +1,29 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.danoeh.antennapod.core.export; + +import java.io.IOException; +import java.io.Writer; +import java.util.List; + +import de.danoeh.antennapod.core.feed.Feed; + +public interface ExportWriter { + + void writeDocument(List feeds, Writer writer) + throws IllegalArgumentException, IllegalStateException, IOException; + + String fileExtension(); + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java new file mode 100644 index 000000000..b8807a686 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java @@ -0,0 +1,30 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.danoeh.antennapod.core.export.html; + +import de.danoeh.antennapod.core.export.CommonSymbols; + +class HtmlSymbols extends CommonSymbols { + + static final String HTML = "html"; + + static final String ORDERED_LIST = "ol"; + static final String LIST_ITEM = "li"; + + static String HEADING = "h1"; + + static final String LINK = "a"; + static final String LINK_DESTINATION = "href"; + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java new file mode 100644 index 000000000..2fdd8ffa6 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java @@ -0,0 +1,92 @@ +package de.danoeh.antennapod.core.export.html; + +import android.text.TextUtils; +import android.util.Log; +import android.util.Xml; + +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.io.Writer; +import java.util.List; + +import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.feed.Feed; + +/** Writes HTML documents. */ +public class HtmlWriter implements ExportWriter { + + private static final String TAG = "HtmlWriter"; + private static final String ENCODING = "UTF-8"; + private static final String HTML_TITLE = "AntennaPod Subscriptions"; + + /** + * Takes a list of feeds and a writer and writes those into an HTML + * document. + * + * @throws IOException + * @throws IllegalStateException + * @throws IllegalArgumentException + */ + @Override + public void writeDocument(List feeds, Writer writer) + throws IllegalArgumentException, IllegalStateException, IOException { + Log.d(TAG, "Starting to write document"); + XmlSerializer xs = Xml.newSerializer(); + xs.setOutput(writer); + + xs.startDocument(ENCODING, false); + xs.text("\n"); + xs.startTag(null, HtmlSymbols.HTML); + xs.text("\n"); + xs.startTag(null, HtmlSymbols.HEAD); + xs.text("\n"); + xs.startTag(null, HtmlSymbols.TITLE); + xs.text(HTML_TITLE); + xs.endTag(null, HtmlSymbols.TITLE); + xs.text("\n"); + xs.endTag(null, HtmlSymbols.HEAD); + xs.text("\n"); + + xs.startTag(null, HtmlSymbols.BODY); + xs.text("\n"); + xs.startTag(null, HtmlSymbols.HEADING); + xs.text(HTML_TITLE); + xs.endTag(null, HtmlSymbols.HEADING); + xs.text("\n"); + xs.startTag(null, HtmlSymbols.ORDERED_LIST); + xs.text("\n"); + for (Feed feed : feeds) { + xs.startTag(null, HtmlSymbols.LIST_ITEM); + xs.text(feed.getTitle()); + if (!TextUtils.isEmpty(feed.getLink())) { + xs.text(" ["); + xs.startTag(null, HtmlSymbols.LINK); + xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getLink()); + xs.text("Website"); + xs.endTag(null, HtmlSymbols.LINK); + xs.text("]"); + } + xs.text(" ["); + xs.startTag(null, HtmlSymbols.LINK); + xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getDownload_url()); + xs.text("Feed"); + xs.endTag(null, HtmlSymbols.LINK); + xs.text("]"); + xs.endTag(null, HtmlSymbols.LIST_ITEM); + xs.text("\n"); + } + xs.endTag(null, HtmlSymbols.ORDERED_LIST); + xs.endTag(null, HtmlSymbols.BODY); + xs.text("\n"); + xs.endTag(null, HtmlSymbols.HTML); + xs.text("\n"); + xs.endDocument(); + Log.d(TAG, "Finished writing document"); + } + + public String fileExtension() { + return "html"; + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java index 8b2c24847..40b0e23b8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java @@ -1,19 +1,18 @@ package de.danoeh.antennapod.core.export.opml; +import de.danoeh.antennapod.core.export.CommonSymbols; + /** Contains symbols for reading and writing OPML documents. */ -public final class OpmlSymbols { +public final class OpmlSymbols extends CommonSymbols { public static final String OPML = "opml"; - public static final String BODY = "body"; - public static final String OUTLINE = "outline"; - public static final String TEXT = "text"; - public static final String XMLURL = "xmlUrl"; - public static final String HTMLURL = "htmlUrl"; - public static final String TYPE = "type"; - public static final String VERSION = "version"; - public static final String HEAD = "head"; - public static final String TITLE = "title"; - public static final String DATE_CREATED = "dateCreated"; + static final String OUTLINE = "outline"; + static final String TEXT = "text"; + static final String XMLURL = "xmlUrl"; + static final String HTMLURL = "htmlUrl"; + static final String TYPE = "type"; + static final String VERSION = "version"; + static final String DATE_CREATED = "dateCreated"; private OpmlSymbols() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java index 0eaed1563..afd652cff 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java @@ -10,11 +10,13 @@ import java.io.Writer; import java.util.Date; import java.util.List; +import de.danoeh.antennapod.core.export.ExportWriter; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.util.DateUtils; /** Writes OPML documents. */ -public class OpmlWriter { +public class OpmlWriter implements ExportWriter { + private static final String TAG = "OpmlWriter"; private static final String ENCODING = "UTF-8"; private static final String OPML_VERSION = "2.0"; @@ -28,6 +30,7 @@ public class OpmlWriter { * @throws IllegalStateException * @throws IllegalArgumentException */ + @Override public void writeDocument(List feeds, Writer writer) throws IllegalArgumentException, IllegalStateException, IOException { Log.d(TAG, "Starting to write document"); @@ -83,4 +86,9 @@ public class OpmlWriter { xs.endDocument(); Log.d(TAG, "Finished writing document"); } + + public String fileExtension() { + return "opml"; + } + } -- cgit v1.2.3 From 8086d9b3164030c3bed37878b05fb9249d373b6a Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 16 Oct 2016 15:15:41 +0200 Subject: Check if view is still attached --- .../main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java index e475e696c..67c460e78 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java @@ -38,10 +38,11 @@ public class FeedRemover extends AsyncTask { @Override protected void onPostExecute(Void result) { - dialog.dismiss(); + if(dialog != null && dialog.isShowing()) { + dialog.dismiss(); + } if(skipOnCompletion) { - context.sendBroadcast(new Intent( - PlaybackService.ACTION_SKIP_CURRENT_EPISODE)); + context.sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE)); } } -- cgit v1.2.3 From 2a7845ee655780696ca5314d861435930f4f4e0c Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Mon, 31 Oct 2016 15:06:31 +0000 Subject: Indent exported files --- .../danoeh/antennapod/core/export/CommonSymbols.java | 2 ++ .../danoeh/antennapod/core/export/html/HtmlWriter.java | 12 +----------- .../danoeh/antennapod/core/export/opml/OpmlWriter.java | 18 +----------------- 3 files changed, 4 insertions(+), 28 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java index 020a0671f..3ed251047 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java @@ -19,4 +19,6 @@ public class CommonSymbols { public static final String BODY = "body"; public static final String TITLE = "title"; + public static final String XML_FEATURE_INDENT_OUTPUT = "http://xmlpull.org/v1/doc/features.html#indent-output"; + } diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java index 2fdd8ffa6..c24b39812 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java @@ -33,29 +33,22 @@ public class HtmlWriter implements ExportWriter { throws IllegalArgumentException, IllegalStateException, IOException { Log.d(TAG, "Starting to write document"); XmlSerializer xs = Xml.newSerializer(); + xs.setFeature(HtmlSymbols.XML_FEATURE_INDENT_OUTPUT, true); xs.setOutput(writer); xs.startDocument(ENCODING, false); - xs.text("\n"); xs.startTag(null, HtmlSymbols.HTML); - xs.text("\n"); xs.startTag(null, HtmlSymbols.HEAD); - xs.text("\n"); xs.startTag(null, HtmlSymbols.TITLE); xs.text(HTML_TITLE); xs.endTag(null, HtmlSymbols.TITLE); - xs.text("\n"); xs.endTag(null, HtmlSymbols.HEAD); - xs.text("\n"); xs.startTag(null, HtmlSymbols.BODY); - xs.text("\n"); xs.startTag(null, HtmlSymbols.HEADING); xs.text(HTML_TITLE); xs.endTag(null, HtmlSymbols.HEADING); - xs.text("\n"); xs.startTag(null, HtmlSymbols.ORDERED_LIST); - xs.text("\n"); for (Feed feed : feeds) { xs.startTag(null, HtmlSymbols.LIST_ITEM); xs.text(feed.getTitle()); @@ -74,13 +67,10 @@ public class HtmlWriter implements ExportWriter { xs.endTag(null, HtmlSymbols.LINK); xs.text("]"); xs.endTag(null, HtmlSymbols.LIST_ITEM); - xs.text("\n"); } xs.endTag(null, HtmlSymbols.ORDERED_LIST); xs.endTag(null, HtmlSymbols.BODY); - xs.text("\n"); xs.endTag(null, HtmlSymbols.HTML); - xs.text("\n"); xs.endDocument(); Log.d(TAG, "Finished writing document"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java index afd652cff..fd0922f72 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java @@ -35,36 +35,24 @@ public class OpmlWriter implements ExportWriter { throws IllegalArgumentException, IllegalStateException, IOException { Log.d(TAG, "Starting to write document"); XmlSerializer xs = Xml.newSerializer(); + xs.setFeature(OpmlSymbols.XML_FEATURE_INDENT_OUTPUT, true); xs.setOutput(writer); xs.startDocument(ENCODING, false); - xs.text("\n"); xs.startTag(null, OpmlSymbols.OPML); xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION); - xs.text("\n"); - xs.text(" "); xs.startTag(null, OpmlSymbols.HEAD); - xs.text("\n"); - xs.text(" "); xs.startTag(null, OpmlSymbols.TITLE); xs.text(OPML_TITLE); xs.endTag(null, OpmlSymbols.TITLE); - xs.text("\n"); - xs.text(" "); xs.startTag(null, OpmlSymbols.DATE_CREATED); xs.text(DateUtils.formatRFC822Date(new Date())); xs.endTag(null, OpmlSymbols.DATE_CREATED); - xs.text("\n"); - xs.text(" "); xs.endTag(null, OpmlSymbols.HEAD); - xs.text("\n"); - xs.text(" "); xs.startTag(null, OpmlSymbols.BODY); - xs.text("\n"); for (Feed feed : feeds) { - xs.text(" "); xs.startTag(null, OpmlSymbols.OUTLINE); xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle()); xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle()); @@ -76,13 +64,9 @@ public class OpmlWriter implements ExportWriter { xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink()); } xs.endTag(null, OpmlSymbols.OUTLINE); - xs.text("\n"); } - xs.text(" "); xs.endTag(null, OpmlSymbols.BODY); - xs.text("\n"); xs.endTag(null, OpmlSymbols.OPML); - xs.text("\n"); xs.endDocument(); Log.d(TAG, "Finished writing document"); } -- cgit v1.2.3 From 0760feac819e292723fdcb2caae820a5dbf709d9 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 1 Nov 2016 17:23:04 +0100 Subject: Change authors delimiter to newline --- .../de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index b14f84c7a..6214b8793 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -220,8 +220,8 @@ public class NSAtom extends Namespace { if (currentName == null) { state.getFeed().setAuthor(content); } else { - state.getFeed().setAuthor(currentName + ", " + content); } + state.getFeed().setAuthor(currentName + "\n" + content); } } } -- cgit v1.2.3 From 04bcf6e697827c6e449b2e10d2c589ff763fa5a3 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 1 Nov 2016 17:26:58 +0100 Subject: Only store the feed's author(s), not that of individual items --- .../antennapod/core/syndication/namespace/atom/NSAtom.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index 6214b8793..90f5f5f20 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -214,13 +214,12 @@ public class NSAtom extends Namespace { state.getFeed().setImage(new FeedImage(state.getFeed(), content, null)); } else if (IMAGE_ICON.equals(top) && state.getFeed() != null) { state.getFeed().setImage(new FeedImage(state.getFeed(), content, null)); - } else if (AUTHOR.equals(second) && state.getFeed() != null) { - if (AUTHOR_NAME.equals(top)) { - String currentName = state.getFeed().getAuthor(); - if (currentName == null) { - state.getFeed().setAuthor(content); - } else { - } + } else if (AUTHOR_NAME.equals(top) && AUTHOR.equals(second) && + state.getFeed() != null && state.getCurrentItem() == null) { + String currentName = state.getFeed().getAuthor(); + if (currentName == null) { + state.getFeed().setAuthor(content); + } else { state.getFeed().setAuthor(currentName + "\n" + content); } } -- cgit v1.2.3 From 8a626faf73070085e2f520247a5f701c4f125c10 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 1 Nov 2016 19:35:43 +0100 Subject: Add ability to rename feeds --- .../java/de/danoeh/antennapod/core/feed/Feed.java | 52 ++++++++++++++++------ .../danoeh/antennapod/core/storage/DBWriter.java | 11 +++++ .../antennapod/core/storage/PodDBAdapter.java | 18 ++++++-- 3 files changed, 64 insertions(+), 17 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index bb0724d66..ac23f3d3d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -26,7 +26,11 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { public static final String TYPE_RSS091 = "rss"; public static final String TYPE_ATOM1 = "atom"; - private String title; + /* title as defined by the feed */ + private String feedTitle; + /* custom title set by the user */ + private String customTitle; + /** * Contains 'id'-element in Atom feed. */ @@ -92,13 +96,14 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { /** * This constructor is used for restoring a feed from the database. */ - public Feed(long id, String lastUpdate, String title, String link, String description, String paymentLink, + public Feed(long id, String lastUpdate, String title, String customTitle, String link, String description, String paymentLink, String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl, String downloadUrl, boolean downloaded, FlattrStatus status, boolean paged, String nextPageLink, String filter, boolean lastUpdateFailed) { super(fileUrl, downloadUrl, downloaded); this.id = id; - this.title = title; + this.feedTitle = title; + this.customTitle = customTitle; this.lastUpdate = lastUpdate; this.link = link; this.description = description; @@ -126,7 +131,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { public Feed(long id, String lastUpdate, String title, String link, String description, String paymentLink, String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl, String downloadUrl, boolean downloaded) { - this(id, lastUpdate, title, link, description, paymentLink, author, language, type, feedIdentifier, image, + this(id, lastUpdate, title, null, link, description, paymentLink, author, language, type, feedIdentifier, image, fileUrl, downloadUrl, downloaded, new FlattrStatus(), false, null, null, false); } @@ -154,7 +159,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { */ public Feed(String url, String lastUpdate, String title) { this(url, lastUpdate); - this.title = title; + this.feedTitle = title; this.flattrStatus = new FlattrStatus(); } @@ -171,6 +176,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); int indexLastUpdate = cursor.getColumnIndex(PodDBAdapter.KEY_LASTUPDATE); int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexCustomTitle = cursor.getColumnIndex(PodDBAdapter.KEY_CUSTOM_TITLE); int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); int indexDescription = cursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION); int indexPaymentLink = cursor.getColumnIndex(PodDBAdapter.KEY_PAYMENT_LINK); @@ -191,6 +197,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { cursor.getLong(indexId), cursor.getString(indexLastUpdate), cursor.getString(indexTitle), + cursor.getString(indexCustomTitle), cursor.getString(indexLink), cursor.getString(indexDescription), cursor.getString(indexPaymentLink), @@ -268,8 +275,8 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { return feedIdentifier; } else if (download_url != null && !download_url.isEmpty()) { return download_url; - } else if (title != null && !title.isEmpty()) { - return title; + } else if (feedTitle != null && !feedTitle.isEmpty()) { + return feedTitle; } else { return link; } @@ -277,8 +284,8 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { @Override public String getHumanReadableIdentifier() { - if (title != null) { - return title; + if (feedTitle != null) { + return feedTitle; } else { return download_url; } @@ -287,8 +294,8 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { public void updateFromOther(Feed other) { // don't update feed's download_url, we do that manually if redirected // see AntennapodHttpClient - if (other.title != null) { - title = other.title; + if (other.feedTitle != null) { + feedTitle = other.feedTitle; } if (other.feedIdentifier != null) { feedIdentifier = other.feedIdentifier; @@ -323,7 +330,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { if (super.compareWithOther(other)) { return true; } - if (!TextUtils.equals(title, other.title)) { + if (!TextUtils.equals(feedTitle, other.feedTitle)) { return true; } if (other.feedIdentifier != null) { @@ -384,11 +391,28 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { } public String getTitle() { - return title; + return !TextUtils.isEmpty(customTitle) ? customTitle : feedTitle; } public void setTitle(String title) { - this.title = title; + this.feedTitle = title; + } + + public String getFeedTitle() { + return this.feedTitle; + } + + @Nullable + public String getCustomTitle() { + return this.customTitle; + } + + public void setCustomTitle(String customTitle) { + if(customTitle == null || customTitle.equals(feedTitle)) { + this.customTitle = null; + } else { + this.customTitle = customTitle; + } } public String getLink() { 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 8e007019f..563d80da0 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 @@ -884,6 +884,17 @@ public class DBWriter { }); } + public static Future setFeedCustomTitle(Feed feed) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedCustomTitle(feed.getId(), feed.getCustomTitle()); + adapter.close(); + EventDistributor.getInstance().sendFeedUpdateBroadcast(); + }); + } + + /** * format an url for querying the database * (postfix a / and apply percent-encoding) diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index b0d053f5a..ff003550c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -57,6 +57,7 @@ public class PodDBAdapter { // Key-constants public static final String KEY_ID = "id"; public static final String KEY_TITLE = "title"; + public static final String KEY_CUSTOM_TITLE = "custom_title"; public static final String KEY_NAME = "name"; public static final String KEY_LINK = "link"; public static final String KEY_DESCRIPTION = "description"; @@ -124,7 +125,7 @@ public class PodDBAdapter { public static final String CREATE_TABLE_FEEDS = "CREATE TABLE " + TABLE_NAME_FEEDS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE - + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT," + + " TEXT," + KEY_CUSTOM_TITLE + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT," + KEY_DOWNLOADED + " INTEGER," + KEY_LINK + " TEXT," + KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT," + KEY_LASTUPDATE + " TEXT," + KEY_LANGUAGE + " TEXT," + KEY_AUTHOR @@ -225,6 +226,7 @@ public class PodDBAdapter { private static final String[] FEED_SEL_STD = { TABLE_NAME_FEEDS + "." + KEY_ID, TABLE_NAME_FEEDS + "." + KEY_TITLE, + TABLE_NAME_FEEDS + "." + KEY_CUSTOM_TITLE, TABLE_NAME_FEEDS + "." + KEY_FILE_URL, TABLE_NAME_FEEDS + "." + KEY_DOWNLOAD_URL, TABLE_NAME_FEEDS + "." + KEY_DOWNLOADED, @@ -363,7 +365,7 @@ public class PodDBAdapter { */ public long setFeed(Feed feed) { ContentValues values = new ContentValues(); - values.put(KEY_TITLE, feed.getTitle()); + values.put(KEY_TITLE, feed.getFeedTitle()); values.put(KEY_LINK, feed.getLink()); values.put(KEY_DESCRIPTION, feed.getDescription()); values.put(KEY_PAYMENT_LINK, feed.getPaymentLink()); @@ -854,6 +856,12 @@ public class PodDBAdapter { db.execSQL(sql); } + void setFeedCustomTitle(long feedId, String customTitle) { + ContentValues values = new ContentValues(); + values.put(KEY_CUSTOM_TITLE, customTitle); + db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)}); + } + /** * Inserts or updates a download status. */ @@ -1628,7 +1636,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private static final int VERSION = 1050004; + private static final int VERSION = 1060200; private Context context; @@ -1924,6 +1932,10 @@ public class PodDBAdapter { db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS +" SET " + PodDBAdapter.KEY_LASTUPDATE + "=NULL"); } + if(oldVersion < 1060200) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + PodDBAdapter.KEY_CUSTOM_TITLE + " TEXT"); + } EventBus.getDefault().post(ProgressEvent.end()); } -- cgit v1.2.3 From ab182c4b63fd52c67692ade92cff43461f0b9587 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 1 Nov 2016 12:01:21 +0100 Subject: Replace jsoup's example html to plain text parser with adaptation thereof --- .../core/util/syndication/HtmlToPlainText.java | 89 ++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java new file mode 100644 index 000000000..bd40f398d --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java @@ -0,0 +1,89 @@ +package de.danoeh.antennapod.core.util.syndication; + +import org.jsoup.helper.StringUtil; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.NodeTraversor; +import org.jsoup.select.NodeVisitor; + +/** + * This class is based on HtmlToPlainText from jsoup's examples package. + * + * HTML to plain-text. This example program demonstrates the use of jsoup to convert HTML input to lightly-formatted + * plain-text. That is divergent from the general goal of jsoup's .text() methods, which is to get clean data from a + * scrape. + *

+ * Note that this is a fairly simplistic formatter -- for real world use you'll want to embrace and extend. + *

+ *

+ * To invoke from the command line, assuming you've downloaded the jsoup jar to your current directory:

+ *

java -cp jsoup.jar org.jsoup.examples.HtmlToPlainText url [selector]

+ * where url is the URL to fetch, and selector is an optional CSS selector. + * + * @author Jonathan Hedley, jonathan@hedley.net + * @author AntennaPod open source community + */ +public class HtmlToPlainText { + + /** + * Format an Element to plain-text + * @param element the root element to format + * @return formatted text + */ + public String getPlainText(Element element) { + FormattingVisitor formatter = new FormattingVisitor(); + NodeTraversor traversor = new NodeTraversor(formatter); + traversor.traverse(element); // walk the DOM, and call .head() and .tail() for each node + + return formatter.toString(); + } + + // the formatting rules, implemented in a breadth-first DOM traverse + private class FormattingVisitor implements NodeVisitor { + + private StringBuilder accum = new StringBuilder(); // holds the accumulated text + + // hit when the node is first seen + public void head(Node node, int depth) { + String name = node.nodeName(); + if (node instanceof TextNode) { + append(((TextNode) node).text()); // TextNodes carry all user-readable text in the DOM. + } + else if (name.equals("li")) { + append("\n * "); + } + else if (name.equals("dt")) { + append(" "); + } + else if (StringUtil.in(name, "p", "h1", "h2", "h3", "h4", "h5", "tr")) { + append("\n"); + } + } + + // hit when all of the node's children (if any) have been visited + public void tail(Node node, int depth) { + String name = node.nodeName(); + if (StringUtil.in(name, "br", "dd", "dt", "p", "h1", "h2", "h3", "h4", "h5")) { + append("\n"); + } else if (name.equals("a")) { + append(String.format(" <%s>", node.absUrl("href"))); + } + } + + // appends text to the string builder with a simple word wrap method + private void append(String text) { + if (text.equals(" ") && + (accum.length() == 0 || StringUtil.in(accum.substring(accum.length() - 1), " ", "\n"))) { + return; // don't accumulate long runs of empty spaces + } + + accum.append(text); + } + + @Override + public String toString() { + return accum.toString(); + } + } +} -- cgit v1.2.3 From 527dfe737ebc2effc81b66c417bc4ee6f33c19a5 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 4 Nov 2016 22:35:41 +0100 Subject: Accept 'application/octet-stream' as valid media mime type --- .../antennapod/core/syndication/util/SyndTypeUtils.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java index 5b12fa772..1d564ab0e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java @@ -1,15 +1,22 @@ package de.danoeh.antennapod.core.syndication.util; +import android.text.TextUtils; import android.webkit.MimeTypeMap; + import org.apache.commons.io.FilenameUtils; +import java.util.Arrays; + /** Utility class for handling MIME-Types of enclosures */ public class SyndTypeUtils { - private static final String VALID_MEDIA_MIMETYPE = "audio/.*" + "|" + "video/.*" - + "|" + "application/ogg"; - private static final String VALID_IMAGE_MIMETYPE = "image/.*"; + private static final String VALID_MEDIA_MIMETYPE = TextUtils.join("|", Arrays.asList( + "audio/.*", + "video/.*", + "application/ogg", + "application/octet-stream")); + private static final String VALID_IMAGE_MIMETYPE = "image/.*"; private SyndTypeUtils() { -- cgit v1.2.3 From 8fd886c273b07c2f5e2b2648c3cdb9de513fe5c4 Mon Sep 17 00:00:00 2001 From: Domingos Lopes Date: Wed, 9 Nov 2016 13:28:50 -0500 Subject: fix unskipped episodes being removed from queue --- .../core/service/playback/LocalPSMP.java | 9 ++++---- .../core/service/playback/PlaybackService.java | 27 +++++++++++++--------- .../playback/PlaybackServiceMediaPlayer.java | 26 ++++++++++++--------- 3 files changed, 36 insertions(+), 26 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index cad67539b..dd7bba964 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -146,7 +146,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { if (!media.getIdentifier().equals(playable.getIdentifier())) { final Playable oldMedia = media; - executor.submit(() -> callback.onPostPlayback(oldMedia, false, true)); + executor.submit(() -> callback.onPostPlayback(oldMedia, false, false, true)); } setPlayerStatus(PlayerStatus.INDETERMINATE, null); @@ -758,7 +758,8 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { @Override - protected Future endPlayback(final boolean wasSkipped, final boolean shouldContinue, final boolean toStoppedState) { + protected Future endPlayback(final boolean hasEnded, final boolean wasSkipped, + final boolean shouldContinue, final boolean toStoppedState) { return executor.submit(() -> { playerLock.lock(); releaseWifiLockIfNecessary(); @@ -816,7 +817,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } final boolean hasNext = nextMedia != null; - executor.submit(() -> callback.onPostPlayback(currentMedia, !wasSkipped, hasNext)); + executor.submit(() -> callback.onPostPlayback(currentMedia, hasEnded, wasSkipped, hasNext)); } else if (isPlaying) { callback.onPlaybackPause(currentMedia, currentMedia.getPosition()); } @@ -883,7 +884,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { mp -> genericOnCompletion(); private void genericOnCompletion() { - endPlayback(false, true, true); + endPlayback(true, false, true, true); } private final MediaPlayer.OnBufferingUpdateListener audioBufferingUpdateListener = 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 33aec0ee0..ee6c46130 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 @@ -685,8 +685,9 @@ public class PlaybackService extends MediaBrowserServiceCompat { } @Override - public void onPostPlayback(@NonNull Playable media, boolean ended, boolean playingNext) { - PlaybackService.this.onPostPlayback(media, ended, playingNext); + public void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, + boolean playingNext) { + PlaybackService.this.onPostPlayback(media, ended, skipped, playingNext); } @Override @@ -784,16 +785,20 @@ public class PlaybackService extends MediaBrowserServiceCompat { * Even though these tasks aren't supposed to be resource intensive, a good practice is to * usually call this method on a background thread. * - * @param playable the media object that was playing. It is assumed that its position property - * was updated before this method was called. - * @param ended if true, it signals that {@param playable} was played until its end. - * In such case, the position property of the media becomes irrelevant for most of - * the tasks (although it's still a good practice to keep it accurate). - * @param playingNext if true, it means another media object is being loaded in place of this one. + * @param playable the media object that was playing. It is assumed that its position + * property was updated before this method was called. + * @param ended if true, it signals that {@param playable} was played until its end. + * In such case, the position property of the media becomes irrelevant for + * most of the tasks (although it's still a good practice to keep it + * accurate). + * @param skipped if the user pressed a skip >| button. + * @param playingNext if true, it means another media object is being loaded in place of this + * one. * Instances when we'd set it to false would be when we're not following the * queue or when the queue has ended. */ - private void onPostPlayback(final Playable playable, boolean ended, boolean playingNext) { + private void onPostPlayback(final Playable playable, boolean ended, boolean skipped, + boolean playingNext) { if (playable == null) { Log.e(TAG, "Cannot do post-playback processing: media was null"); return; @@ -824,7 +829,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { if (item != null) { if (ended || smartMarkAsPlayed || - !UserPreferences.shouldSkipKeepEpisode()) { + (skipped && !UserPreferences.shouldSkipKeepEpisode())) { // only mark the item as played if we're not keeping it anyways DBWriter.markItemPlayed(item, FeedItem.PLAYED, ended); try { @@ -845,7 +850,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { } } - if (ended || playingNext) { + if (ended || skipped || playingNext) { DBWriter.addItemToPlaybackHistory(media); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index aec059ca0..3b9a11610 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -228,32 +228,35 @@ public abstract class PlaybackServiceMediaPlayer { protected abstract void setPlayable(Playable playable); public void skip() { - endPlayback(true, true, true); + endPlayback(false, true, true, true); } /** * Ends playback of current media (if any) and moves into INDETERMINATE state, unless * {@param toStoppedState} is set to true, in which case it moves into STOPPED state. * - * @see #endPlayback(boolean, boolean, boolean) + * @see #endPlayback(boolean, boolean, boolean, boolean) */ public Future stopPlayback(boolean toStoppedState) { - return endPlayback(true, false, toStoppedState); + return endPlayback(false, false, false, toStoppedState); } /** * Internal method that handles end of playback. * - * Currently, it has 4 use cases: + * Currently, it has 5 use cases: *
    - *
  • Media playback has completed: call with (false, true, true)
  • - *
  • User asks to skip to next episode: call with (true, true, true)
  • - *
  • Stopping the media player: call with (true, false, true)
  • - *
  • We want to change the media player implementation: call with (true, false, false)
  • + *
  • Media playback has completed: call with (true, false, true, true)
  • + *
  • User asks to skip to next episode: call with (false, true, true, true)
  • + *
  • Skipping to next episode due to playback error: call with (false, false, true, true)
  • + *
  • Stopping the media player: call with (false, false, false, true)
  • + *
  • We want to change the media player implementation: call with (false, false, false, false)
  • *
* - * @param wasSkipped If true, we assume the current media's playback has ended, for + * @param hasEnded If true, we assume the current media's playback has ended, for * purposes of post playback processing. + * @param wasSkipped Whether the user chose to skip the episode (by pressing the skip + * button). * @param shouldContinue If true, the media player should try to load, and possibly play, * the next item, based on the user preferences and whether such item * exists. @@ -264,7 +267,8 @@ public abstract class PlaybackServiceMediaPlayer { * * @return a Future, just for the purpose of tracking its execution. */ - protected abstract Future endPlayback(boolean wasSkipped, boolean shouldContinue, boolean toStoppedState); + protected abstract Future endPlayback(boolean hasEnded, boolean wasSkipped, + boolean shouldContinue, boolean toStoppedState); /** * @return {@code true} if the WifiLock feature should be used, {@code false} otherwise. @@ -346,7 +350,7 @@ public abstract class PlaybackServiceMediaPlayer { boolean onMediaPlayerError(Object inObj, int what, int extra); - void onPostPlayback(@NonNull Playable media, boolean ended, boolean playingNext); + void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, boolean playingNext); void onPlaybackStart(@NonNull Playable playable, int position); -- cgit v1.2.3 From 4a6b630e56fc486308b6fb53784264e36988fd78 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 12 Nov 2016 09:25:10 +0100 Subject: Prevent NPE --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java | 2 ++ .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'core/src/main/java/de') 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 2481645e0..ee7a738d0 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 @@ -1,6 +1,7 @@ package de.danoeh.antennapod.core.feed; import android.database.Cursor; +import android.support.annotation.Nullable; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -269,6 +270,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr } } + @Nullable public FeedMedia getMedia() { return media; } 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 ee6c46130..b556bba7a 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 @@ -301,7 +301,10 @@ public class PlaybackService extends MediaBrowserServiceCompat { List queueItems = new ArrayList<>(); try { for (FeedItem feedItem : taskManager.getQueue()) { - queueItems.add(new MediaSessionCompat.QueueItem(feedItem.getMedia().getMediaItem().getDescription(), feedItem.getId())); + if(feedItem.getMedia() != null) { + MediaDescriptionCompat mediaDescription = feedItem.getMedia().getMediaItem().getDescription(); + queueItems.add(new MediaSessionCompat.QueueItem(mediaDescription, feedItem.getId())); + } } mediaSession.setQueue(queueItems); } catch (InterruptedException e) { -- cgit v1.2.3 From 2682cbd784a23a627771bba36b123d4727ccfc24 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 13 Nov 2016 22:04:08 +0100 Subject: Upgrade to OkHttp3 --- .../antennapod/core/glide/ApOkHttpUrlLoader.java | 24 ++++--- .../antennapod/core/gpoddernet/GpodnetService.java | 40 +++-------- .../service/download/AntennapodHttpClient.java | 78 ++++++++++++++-------- .../core/service/download/HttpDownloader.java | 41 +++++++----- .../danoeh/antennapod/core/util/NetworkUtils.java | 8 +-- 5 files changed, 99 insertions(+), 92 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java index 762e92286..8ca9faa0d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -4,15 +4,12 @@ import android.content.Context; import android.text.TextUtils; import android.util.Log; -import com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher; +import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher; import com.bumptech.glide.load.data.DataFetcher; import com.bumptech.glide.load.model.GenericLoaderFactory; import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.model.ModelLoaderFactory; -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Response; import java.io.IOException; import java.io.InputStream; @@ -22,9 +19,13 @@ import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.NetworkUtils; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; /** - * @see com.bumptech.glide.integration.okhttp.OkHttpUrlLoader + * @see com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader */ public class ApOkHttpUrlLoader implements ModelLoader { @@ -42,9 +43,10 @@ public class ApOkHttpUrlLoader implements ModelLoader { if (internalClient == null) { synchronized (Factory.class) { if (internalClient == null) { - internalClient = AntennapodHttpClient.newHttpClient(); - internalClient.interceptors().add(new NetworkAllowanceInterceptor()); - internalClient.interceptors().add(new BasicAuthenticationInterceptor()); + OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder(); + builder.interceptors().add(new NetworkAllowanceInterceptor()); + builder.interceptors().add(new BasicAuthenticationInterceptor()); + internalClient = builder.build(); } } } @@ -113,8 +115,8 @@ public class ApOkHttpUrlLoader implements ModelLoader { @Override public Response intercept(Chain chain) throws IOException { - com.squareup.okhttp.Request request = chain.request(); - String url = request.urlString(); + Request request = chain.request(); + String url = request.url().toString(); String authentication = DBReader.getImageAuthentication(url); if(TextUtils.isEmpty(authentication)) { @@ -125,7 +127,7 @@ public class ApOkHttpUrlLoader implements ModelLoader { // add authentication String[] auth = authentication.split(":"); String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1"); - com.squareup.okhttp.Request newRequest = request + Request newRequest = request .newBuilder() .addHeader("Authorization", credentials) .build(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java index 9f716e546..0218b103a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java @@ -1,15 +1,6 @@ package de.danoeh.antennapod.core.gpoddernet; import android.support.annotation.NonNull; - -import com.squareup.okhttp.Credentials; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.RequestBody; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; - import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -38,6 +29,13 @@ import de.danoeh.antennapod.core.gpoddernet.model.GpodnetTag; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; +import okhttp3.Credentials; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; /** * Communicates with the gpodder.net service. @@ -570,15 +568,7 @@ public class GpodnetService { e.printStackTrace(); throw new GpodnetServiceException(e); } finally { - if (response != null && body != null) { - try { - body.close(); - } catch (IOException e) { - e.printStackTrace(); - throw new GpodnetServiceException(e); - } - } - + body.close(); } return responseString; } @@ -605,12 +595,7 @@ public class GpodnetService { throw new GpodnetServiceException(e); } finally { if (body != null) { - try { - body.close(); - } catch (IOException e) { - e.printStackTrace(); - throw new GpodnetServiceException(e); - } + body.close(); } } return result; @@ -619,12 +604,7 @@ public class GpodnetService { private String getStringFromResponseBody(@NonNull ResponseBody body) throws GpodnetServiceException { ByteArrayOutputStream outputStream; - int contentLength = 0; - try { - contentLength = (int) body.contentLength(); - } catch (IOException ignore) { - // ignore - } + int contentLength = (int) body.contentLength(); if (contentLength > 0) { outputStream = new ByteArrayOutputStream(contentLength); } else { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java index 5dd1e2dfa..eb28050f0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java @@ -5,12 +5,6 @@ import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; -import com.squareup.okhttp.Credentials; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.internal.http.StatusLine; - import java.io.IOException; import java.net.CookieManager; import java.net.CookiePolicy; @@ -20,16 +14,27 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.net.Socket; import java.net.SocketAddress; -import java.net.URL; import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.Arrays; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBWriter; +import okhttp3.Credentials; +import okhttp3.HttpUrl; +import okhttp3.JavaNetCookieJar; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.internal.http.StatusLine; /** * Provides access to a HttpClient singleton. @@ -50,13 +55,13 @@ public class AntennapodHttpClient { */ public static synchronized OkHttpClient getHttpClient() { if (httpClient == null) { - httpClient = newHttpClient(); + httpClient = newBuilder().build(); } return httpClient; } public static synchronized void reinit() { - httpClient = newHttpClient(); + httpClient = newBuilder().build(); } /** @@ -67,33 +72,33 @@ public class AntennapodHttpClient { * @return http client */ @NonNull - public static OkHttpClient newHttpClient() { + public static OkHttpClient.Builder newBuilder() { Log.d(TAG, "Creating new instance of HTTP client"); System.setProperty("http.maxConnections", String.valueOf(MAX_CONNECTIONS)); - OkHttpClient client = new OkHttpClient(); + OkHttpClient.Builder builder = new OkHttpClient.Builder(); // detect 301 Moved permanently and 308 Permanent Redirect - client.networkInterceptors().add(chain -> { + builder.networkInterceptors().add(chain -> { Request request = chain.request(); Response response = chain.proceed(request); if (response.code() == HttpURLConnection.HTTP_MOVED_PERM || response.code() == StatusLine.HTTP_PERM_REDIRECT) { String location = response.header("Location"); if (location.startsWith("/")) { // URL is not absolute, but relative - URL url = request.url(); - location = url.getProtocol() + "://" + url.getHost() + location; + HttpUrl url = request.url(); + location = url.scheme() + "://" + url.host() + location; } else if (!location.toLowerCase().startsWith("http://") && !location.toLowerCase().startsWith("https://")) { // Reference is relative to current path - URL url = request.url(); - String path = url.getPath(); + HttpUrl url = request.url(); + String path = url.encodedPath(); String newPath = path.substring(0, path.lastIndexOf("/") + 1) + location; - location = url.getProtocol() + "://" + url.getHost() + newPath; + location = url.scheme() + "://" + url.host() + newPath; } try { - DBWriter.updateFeedDownloadURL(request.urlString(), location).get(); + DBWriter.updateFeedDownloadURL(request.url().toString(), location).get(); } catch (Exception e) { Log.e(TAG, Log.getStackTraceString(e)); } @@ -104,26 +109,26 @@ public class AntennapodHttpClient { // set cookie handler CookieManager cm = new CookieManager(); cm.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); - client.setCookieHandler(cm); + builder.cookieJar(new JavaNetCookieJar(cm)); // set timeouts - client.setConnectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); - client.setReadTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); - client.setWriteTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); + builder.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); + builder.readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); + builder.writeTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); // configure redirects - client.setFollowRedirects(true); - client.setFollowSslRedirects(true); + builder.followRedirects(true); + builder.followSslRedirects(true); ProxyConfig config = UserPreferences.getProxyConfig(); if (config.type != Proxy.Type.DIRECT) { int port = config.port > 0 ? config.port : ProxyConfig.DEFAULT_PORT; SocketAddress address = InetSocketAddress.createUnresolved(config.host, port); Proxy proxy = new Proxy(config.type, address); - client.setProxy(proxy); + builder.proxy(proxy); if (!TextUtils.isEmpty(config.username)) { String credentials = Credentials.basic(config.username, config.password); - client.interceptors().add(chain -> { + builder.interceptors().add(chain -> { Request request = chain.request().newBuilder() .header("Proxy-Authorization", credentials).build(); return chain.proceed(request); @@ -131,9 +136,9 @@ public class AntennapodHttpClient { } } if(16 <= Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 21) { - client.setSslSocketFactory(new CustomSslSocketFactory()); + builder.sslSocketFactory(new CustomSslSocketFactory(), trustManager()); } - return client; + return builder; } /** @@ -146,6 +151,23 @@ public class AntennapodHttpClient { } } + private static X509TrustManager trustManager() { + try { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init((KeyStore) null); + TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); + if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { + throw new IllegalStateException("Unexpected default trust managers:" + + Arrays.toString(trustManagers)); + } + return (X509TrustManager) trustManagers[0]; + } catch (Exception e) { + Log.e(TAG, Log.getStackTraceString(e)); + return null; + } + } + private static class CustomSslSocketFactory extends SSLSocketFactory { private SSLSocketFactory factory; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index 99456b756..b409a419a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -2,21 +2,7 @@ package de.danoeh.antennapod.core.service.download; import android.text.TextUtils; import android.util.Log; -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Protocol; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; -import de.danoeh.antennapod.core.ClientConfig; -import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.feed.FeedImage; -import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.util.DateUtils; -import de.danoeh.antennapod.core.util.DownloadError; -import de.danoeh.antennapod.core.util.StorageUtils; -import de.danoeh.antennapod.core.util.URIUtil; -import okio.ByteString; + import org.apache.commons.io.IOUtils; import java.io.BufferedInputStream; @@ -32,6 +18,22 @@ import java.net.UnknownHostException; import java.util.Collections; import java.util.Date; +import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.core.feed.FeedImage; +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.util.DateUtils; +import de.danoeh.antennapod.core.util.DownloadError; +import de.danoeh.antennapod.core.util.StorageUtils; +import de.danoeh.antennapod.core.util.URIUtil; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okio.ByteString; + public class HttpDownloader extends Downloader { private static final String TAG = "HttpDownloader"; @@ -57,8 +59,9 @@ public class HttpDownloader extends Downloader { } } - OkHttpClient httpClient = AntennapodHttpClient.newHttpClient(); - httpClient.interceptors().add(new BasicAuthorizationInterceptor(request)); + OkHttpClient.Builder httpClientBuilder = AntennapodHttpClient.newBuilder(); + httpClientBuilder.interceptors().add(new BasicAuthorizationInterceptor(request)); + OkHttpClient httpClient = httpClientBuilder.build(); RandomAccessFile out = null; InputStream connection; ResponseBody responseBody = null; @@ -103,7 +106,9 @@ public class HttpDownloader extends Downloader { } catch (IOException e) { Log.e(TAG, e.toString()); if (e.getMessage().contains("PROTOCOL_ERROR")) { - httpClient.setProtocols(Collections.singletonList(Protocol.HTTP_1_1)); + httpClient = httpClient.newBuilder() + .protocols(Collections.singletonList(Protocol.HTTP_1_1)) + .build(); response = httpClient.newCall(httpReq.build()).execute(); } else { throw e; diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java index 43158c471..1717bde0e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java @@ -8,11 +8,6 @@ import android.net.wifi.WifiManager; import android.support.v4.net.ConnectivityManagerCompat; import android.text.TextUtils; import android.util.Log; - -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; - import java.io.File; import java.io.IOException; import java.util.Arrays; @@ -22,6 +17,9 @@ import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.storage.DBWriter; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import rx.Observable; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; -- cgit v1.2.3 From cbe00b4c770cc4d57cdd4ab8e2b1b5c4a961a57f Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 19 Nov 2016 14:56:25 +0100 Subject: Also compare drawer items with same counter value case-insensitive --- core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/java/de') 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 9a7b2c852..8c8e8f029 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 @@ -1063,7 +1063,7 @@ public final class DBReader { // reverse natural order: podcast with most unplayed episodes first return -1; } else if(counterLhs == counterRhs) { - return lhs.getTitle().compareTo(rhs.getTitle()); + return lhs.getTitle().toLowerCase().compareTo(rhs.getTitle().toLowerCase()); } else { return 1; } -- cgit v1.2.3 From 8c901bb640af741e24500f42a8db15056b7e4419 Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Sat, 19 Nov 2016 17:54:43 +0000 Subject: Clean up sort --- core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src/main/java/de') 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 8c8e8f029..1d57d902c 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 @@ -1063,7 +1063,7 @@ public final class DBReader { // reverse natural order: podcast with most unplayed episodes first return -1; } else if(counterLhs == counterRhs) { - return lhs.getTitle().toLowerCase().compareTo(rhs.getTitle().toLowerCase()); + return lhs.getTitle().compareToIgnoreCase(rhs.getTitle()); } else { return 1; } @@ -1077,7 +1077,7 @@ public final class DBReader { } else if(t2 == null) { return -1; } else { - return t1.toLowerCase().compareTo(t2.toLowerCase()); + return t1.compareToIgnoreCase(t2); } }; } else { -- cgit v1.2.3 From 7a23e1f13fba25e7de643ee4e9419f799fdc5d6d Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Sat, 19 Nov 2016 17:55:07 +0000 Subject: Revert author delimiter back to commer --- .../de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index 90f5f5f20..cfb20d578 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -220,7 +220,7 @@ public class NSAtom extends Namespace { if (currentName == null) { state.getFeed().setAuthor(content); } else { - state.getFeed().setAuthor(currentName + "\n" + content); + state.getFeed().setAuthor(currentName + ", " + content); } } } -- cgit v1.2.3 From 65d6cea22a57baf070a72f89ac9b730b8a3fdb09 Mon Sep 17 00:00:00 2001 From: Cj Malone Date: Tue, 22 Nov 2016 19:14:35 +0000 Subject: Fallback to mime type from the URL when the defined is invalid --- .../java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index 90dd67a0b..9bd377293 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -56,7 +56,9 @@ public class NSRSS20 extends Namespace { boolean validType = false; boolean validUrl = !TextUtils.isEmpty(url); - if (type == null) { + if(SyndTypeUtils.enclosureTypeValid(type)) { + validType = true; + } else { type = SyndTypeUtils.getMimeTypeFromUrl(url); } -- cgit v1.2.3 From 4ff8d5430fb83d54b7ef63132b400033e5cf4392 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 27 Nov 2016 10:44:49 +0100 Subject: Refactor --- .../core/syndication/namespace/NSRSS20.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index 9bd377293..3d752df76 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -53,20 +53,15 @@ public class NSRSS20 extends Namespace { } else if (ENCLOSURE.equals(localName)) { String type = attributes.getValue(ENC_TYPE); String url = attributes.getValue(ENC_URL); - boolean validType = false; - boolean validUrl = !TextUtils.isEmpty(url); - if(SyndTypeUtils.enclosureTypeValid(type)) { - validType = true; - } else { - type = SyndTypeUtils.getMimeTypeFromUrl(url); - } - - if(SyndTypeUtils.enclosureTypeValid(type)) { - validType = true; - } + boolean validType = SyndTypeUtils.enclosureTypeValid(type); + if(!validType) { + type = SyndTypeUtils.getMimeTypeFromUrl(url); + validType = SyndTypeUtils.enclosureTypeValid(type); + } - if (state.getCurrentItem() != null && state.getCurrentItem().getMedia() == null && + boolean validUrl = !TextUtils.isEmpty(url); + if (state.getCurrentItem() != null && state.getCurrentItem().getMedia() == null && validType && validUrl) { long size = 0; try { -- cgit v1.2.3 From ea6cfad6c8d984edfa92fc67d32dbbd6ec59248b Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 4 Dec 2016 13:29:36 +0100 Subject: Catch out of memory exception --- .../danoeh/antennapod/core/service/playback/PlaybackService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'core/src/main/java/de') 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 b556bba7a..22c4a8d29 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 @@ -1101,7 +1101,13 @@ public class PlaybackService extends MediaBrowserServiceCompat { mediaSession.setSessionActivity(PendingIntent.getActivity(this, 0, PlaybackService.getPlayerActivityIntent(this), PendingIntent.FLAG_UPDATE_CURRENT)); - mediaSession.setMetadata(builder.build()); + try { + mediaSession.setMetadata(builder.build()); + } catch (OutOfMemoryError e) { + Log.e(TAG, "Setting media session metadata", e); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, null); + mediaSession.setMetadata(builder.build()); + } } }; -- cgit v1.2.3 From 1a7d8041bb60e226bd1ac03ad43557540199353c Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 4 Dec 2016 13:41:23 +0100 Subject: Cast certain playable information int values to long to prevent class cast exceptions --- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'core/src/main/java/de') 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 b556bba7a..2fb261beb 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 @@ -1336,7 +1336,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { if (info.playable != null) { Intent i = new Intent(whatChanged); - i.putExtra("id", 1); + i.putExtra("id", 1L); i.putExtra("artist", ""); i.putExtra("album", info.playable.getFeedTitle()); i.putExtra("track", info.playable.getEpisodeTitle()); @@ -1345,8 +1345,8 @@ public class PlaybackService extends MediaBrowserServiceCompat { if (queue != null) { i.putExtra("ListSize", queue.size()); } - i.putExtra("duration", info.playable.getDuration()); - i.putExtra("position", info.playable.getPosition()); + i.putExtra("duration", (long) info.playable.getDuration()); + i.putExtra("position", (long) info.playable.getPosition()); sendBroadcast(i); } } -- cgit v1.2.3 From dc65f13f442ae7feddd7b8c12c2e61aada29983c Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 4 Dec 2016 21:42:03 +0100 Subject: Do not auto-enable sleep timer after skipping --- .../core/service/playback/PlaybackService.java | 3 +- .../playback/PlaybackServiceMediaPlayer.java | 32 ++++++++++++---------- 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'core/src/main/java/de') 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 aca1d34e1..39d79e521 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 @@ -612,7 +612,8 @@ public class PlaybackService extends MediaBrowserServiceCompat { setupNotification(newInfo); started = true; // set sleep timer if auto-enabled - if(SleepTimerPreferences.autoEnable() && !sleepTimerActive()) { + if(newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING && + SleepTimerPreferences.autoEnable() && !sleepTimerActive()) { setSleepTimer(SleepTimerPreferences.timerMillis(), SleepTimerPreferences.shakeToReset(), SleepTimerPreferences.vibrate()); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 3b9a11610..393019fd1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -29,9 +29,10 @@ public abstract class PlaybackServiceMediaPlayer { /** * Return value of some PSMP methods if the method call failed. */ - public static final int INVALID_TIME = -1; + static final int INVALID_TIME = -1; - protected volatile PlayerStatus playerStatus; + volatile PlayerStatus oldPlayerStatus; + volatile PlayerStatus playerStatus; /** * A wifi-lock that is acquired if the media file is being streamed. @@ -41,8 +42,8 @@ public abstract class PlaybackServiceMediaPlayer { protected final PSMPCallback callback; protected final Context context; - public PlaybackServiceMediaPlayer(@NonNull Context context, - @NonNull PSMPCallback callback){ + PlaybackServiceMediaPlayer(@NonNull Context context, + @NonNull PSMPCallback callback){ this.context = context; this.callback = callback; @@ -204,7 +205,7 @@ public abstract class PlaybackServiceMediaPlayer { * @return The PSMPInfo object. */ public final synchronized PSMPInfo getPSMPInfo() { - return new PSMPInfo(playerStatus, getPlayable()); + return new PSMPInfo(oldPlayerStatus, playerStatus, getPlayable()); } /** @@ -275,7 +276,7 @@ public abstract class PlaybackServiceMediaPlayer { */ protected abstract boolean shouldLockWifi(); - protected final synchronized void acquireWifiLockIfNecessary() { + final synchronized void acquireWifiLockIfNecessary() { if (shouldLockWifi()) { if (wifiLock == null) { wifiLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)) @@ -286,7 +287,7 @@ public abstract class PlaybackServiceMediaPlayer { } } - protected final synchronized void releaseWifiLockIfNecessary() { + final synchronized void releaseWifiLockIfNecessary() { if (wifiLock != null && wifiLock.isHeld()) { wifiLock.release(); } @@ -307,29 +308,28 @@ public abstract class PlaybackServiceMediaPlayer { * @param position The position to be set to the current Playable object in case playback started or paused. * Will be ignored if given the value of {@link #INVALID_TIME}. */ - protected final synchronized void setPlayerStatus(@NonNull PlayerStatus newStatus, Playable newMedia, int position) { + final synchronized void setPlayerStatus(@NonNull PlayerStatus newStatus, Playable newMedia, int position) { Log.d(TAG, this.getClass().getSimpleName() + ": Setting player status to " + newStatus); - PlayerStatus oldStatus = playerStatus; - + this.oldPlayerStatus = playerStatus; this.playerStatus = newStatus; setPlayable(newMedia); if (newMedia != null && newStatus != PlayerStatus.INDETERMINATE) { - if (oldStatus == PlayerStatus.PLAYING && newStatus != PlayerStatus.PLAYING) { + if (oldPlayerStatus == PlayerStatus.PLAYING && newStatus != PlayerStatus.PLAYING) { callback.onPlaybackPause(newMedia, position); - } else if (oldStatus != PlayerStatus.PLAYING && newStatus == PlayerStatus.PLAYING) { + } else if (oldPlayerStatus != PlayerStatus.PLAYING && newStatus == PlayerStatus.PLAYING) { callback.onPlaybackStart(newMedia, position); } } - callback.statusChanged(new PSMPInfo(playerStatus, getPlayable())); + callback.statusChanged(new PSMPInfo(oldPlayerStatus, playerStatus, getPlayable())); } /** * @see #setPlayerStatus(PlayerStatus, Playable, int) */ - protected final void setPlayerStatus(@NonNull PlayerStatus newStatus, Playable newMedia) { + final void setPlayerStatus(@NonNull PlayerStatus newStatus, Playable newMedia) { setPlayerStatus(newStatus, newMedia, INVALID_TIME); } @@ -365,10 +365,12 @@ public abstract class PlaybackServiceMediaPlayer { * Holds information about a PSMP object. */ public static class PSMPInfo { + public PlayerStatus oldPlayerStatus; public PlayerStatus playerStatus; public Playable playable; - public PSMPInfo(PlayerStatus playerStatus, Playable playable) { + PSMPInfo(PlayerStatus oldPlayerStatus, PlayerStatus playerStatus, Playable playable) { + this.oldPlayerStatus = oldPlayerStatus; this.playerStatus = playerStatus; this.playable = playable; } -- cgit v1.2.3 From b24201696213fb9baf1d34b593d376d717a31c9f Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 19 Dec 2016 18:18:50 +0100 Subject: Assume media type is audio when mime type is unknown --- .../core/service/playback/LocalPSMP.java | 39 ++++++++++------------ 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index dd7bba964..f395dfb32 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -852,27 +852,24 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } private IPlayer setMediaPlayerListeners(IPlayer mp) { - if (mp != null && media != null) { - if (media.getMediaType() == MediaType.AUDIO) { - ((AudioPlayer) mp) - .setOnCompletionListener(audioCompletionListener); - ((AudioPlayer) mp) - .setOnSeekCompleteListener(audioSeekCompleteListener); - ((AudioPlayer) mp).setOnErrorListener(audioErrorListener); - ((AudioPlayer) mp) - .setOnBufferingUpdateListener(audioBufferingUpdateListener); - ((AudioPlayer) mp).setOnInfoListener(audioInfoListener); - ((AudioPlayer) mp).setOnSpeedAdjustmentAvailableChangedListener(audioSetSpeedAbilityListener); - } else { - ((VideoPlayer) mp) - .setOnCompletionListener(videoCompletionListener); - ((VideoPlayer) mp) - .setOnSeekCompleteListener(videoSeekCompleteListener); - ((VideoPlayer) mp).setOnErrorListener(videoErrorListener); - ((VideoPlayer) mp) - .setOnBufferingUpdateListener(videoBufferingUpdateListener); - ((VideoPlayer) mp).setOnInfoListener(videoInfoListener); - } + if (mp == null || media == null) { + return mp; + } + if (media.getMediaType() == MediaType.VIDEO) { + VideoPlayer vp = (VideoPlayer) mp; + vp.setOnCompletionListener(videoCompletionListener); + vp.setOnSeekCompleteListener(videoSeekCompleteListener); + vp.setOnErrorListener(videoErrorListener); + vp.setOnBufferingUpdateListener(videoBufferingUpdateListener); + vp.setOnInfoListener(videoInfoListener); + } else { + AudioPlayer ap = (AudioPlayer) mp; + ap.setOnCompletionListener(audioCompletionListener); + ap.setOnSeekCompleteListener(audioSeekCompleteListener); + ap.setOnErrorListener(audioErrorListener); + ap.setOnBufferingUpdateListener(audioBufferingUpdateListener); + ap.setOnInfoListener(audioInfoListener); + ap.setOnSpeedAdjustmentAvailableChangedListener(audioSetSpeedAbilityListener); } return mp; } -- cgit v1.2.3 From a8539dde840e63010b07d7b588bae29b7352605f Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 31 Dec 2016 16:36:23 +0100 Subject: Remove cached feed file after parsing --- .../danoeh/antennapod/core/service/download/DownloadService.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 6bd9fc83c..87c454964 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -842,11 +842,14 @@ public class DownloadService extends Service { successful = false; reason = DownloadError.ERROR_PARSER_EXCEPTION; reasonDetailed = e.getMessage(); + } finally { + File feedFile = new File(request.getDestination()); + if(feedFile.exists()) { + boolean deleted = feedFile.delete(); + Log.d(TAG, "Deletion of file '" + feedFile.getAbsolutePath() + "' " + (deleted ? "successful" : "FAILED")); + } } - // cleanup(); - - if (successful) { // we create a 'successful' download log if the feed's last refresh failed List log = DBReader.getFeedDownloadLog(feed); -- cgit v1.2.3 From c54878a0f56bf978aa0ca6d901457f666dab51ff Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 31 Dec 2016 17:29:45 +0100 Subject: Add setting whether or not to enqueue downloaded episodes --- .../de/danoeh/antennapod/core/preferences/UserPreferences.java | 10 +++++----- .../antennapod/core/service/download/DownloadService.java | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index aa3bbaeab..2221da2e7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -74,6 +74,7 @@ public class UserPreferences { public static final String PREF_RESUME_AFTER_CALL = "prefResumeAfterCall"; // Network + public static final String PREF_ENQUEUE_DOWNLOADED = "prefEnqueueDownloaded"; public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall"; public static final String PREF_MOBILE_UPDATE = "prefMobileUpdate"; public static final String PREF_EPISODE_CLEANUP = "prefEpisodeCleanup"; @@ -258,11 +259,10 @@ public class UserPreferences { return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); } - /** - * Returns {@code true} if new queue elements are added to the front - * - * @return {@code true} if new queue elements are added to the front; {@code false} otherwise - */ + public static boolean enqueueDownloadedEpisodes() { + return prefs.getBoolean(PREF_ENQUEUE_DOWNLOADED, true); + } + public static boolean enqueueAtFront() { return prefs.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 6bd9fc83c..546a8c8d4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -22,6 +22,7 @@ import android.util.Log; import android.webkit.URLUtil; import org.apache.commons.io.FileUtils; +import org.shredzone.flattr4j.model.User; import org.xml.sax.SAXException; import java.io.File; @@ -1048,7 +1049,8 @@ public class DownloadService extends Service { DBWriter.setFeedMedia(media).get(); - if (item != null && !DBTasks.isInQueue(DownloadService.this, item.getId())) { + if (item != null && UserPreferences.enqueueDownloadedEpisodes() && + !DBTasks.isInQueue(DownloadService.this, item.getId())) { DBWriter.addQueueItem(DownloadService.this, item).get(); } } catch (ExecutionException | InterruptedException e) { -- cgit v1.2.3 From 21605171fd3554763e46d9a64306ab4569f40ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Cabessa?= Date: Sat, 7 Jan 2017 14:57:12 +0100 Subject: don't pause while casting if headset is disconnected User was listening to a podcast with headset, then get back home and want to listen to the rest of the podcast on a chromecast. If he unplug the headset while the audio is casting, we should not pause. --- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/java/de') 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 39d79e521..0f7d7265e 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 @@ -1433,7 +1433,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { * Pauses playback if PREF_PAUSE_ON_HEADSET_DISCONNECT was set to true. */ private void pauseIfPauseOnDisconnect() { - if (UserPreferences.isPauseOnHeadsetDisconnect()) { + if (UserPreferences.isPauseOnHeadsetDisconnect() && !isCasting()) { if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { transientPause = true; } -- cgit v1.2.3 From a1201cc95f4d8b7d8f6ce4a89aa675ee7111ab58 Mon Sep 17 00:00:00 2001 From: orelogo Date: Sat, 25 Feb 2017 17:22:57 -0800 Subject: Improve duplicate removal run time by using a hash set --- .../antennapod/core/storage/FeedSearcher.java | 24 ++++++---------------- 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index 9d136273c..48e574069 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -4,7 +4,9 @@ import android.content.Context; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; @@ -51,15 +53,17 @@ public class FeedSearcher { task.run(); } try { + Set set = new HashSet<>(); + for (int i = 0; i < tasks.size(); i++) { FutureTask> task = tasks.get(i); List items = task.get(); for (FeedItem item : items) { - if (result.isEmpty() || !isDuplicate(result, item)) { + if (!set.contains(item.getId())) { // to prevent duplicate results result.add(new SearchResult(item, values[i], subtitles[i])); + set.add(item.getId()); } } - } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); @@ -67,20 +71,4 @@ public class FeedSearcher { Collections.sort(result, new SearchResultValueComparator()); return result; } - - /** - * Determines if the feed item is already in the search result list. - * - * @param result list of search results - * @param item feed item to validate - * @return true if the feed item is already in the results - */ - private static boolean isDuplicate(List result, FeedItem item) { - for (SearchResult resultItem : result) { - if (resultItem.getComponent().getId() == item.getId()) { - return true; - } - } - return false; - } } -- cgit v1.2.3 From c0da3df8929b8a5822724d216a655bb1038118de Mon Sep 17 00:00:00 2001 From: orelogo Date: Sat, 25 Feb 2017 17:23:46 -0800 Subject: Organize search results lexicographically in addition to by where the query was matched --- .../core/util/comparator/SearchResultValueComparator.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java index b16e0949d..d23901a45 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/SearchResultValueComparator.java @@ -1,14 +1,27 @@ package de.danoeh.antennapod.core.util.comparator; +import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.SearchResult; import java.util.Comparator; public class SearchResultValueComparator implements Comparator { + /** + * Compare items based, first, on where they were found (ie. title, chapters, or show notes). + * If they were found in the same section, then compare based on the title, in lexicographic + * order. This is still not ideal since, for example, "#12 Example A" would be considered + * before "#8 Example B" due to the fact that "8" has a larger unicode value than "1" + */ @Override public int compare(SearchResult lhs, SearchResult rhs) { - return rhs.getValue() - lhs.getValue(); + int value = rhs.getValue() - lhs.getValue(); + if (value == 0 && lhs.getComponent() instanceof FeedItem && rhs.getComponent() instanceof FeedItem) { + String lhsTitle = ((FeedItem) lhs.getComponent()).getTitle(); + String rhsTitle = ((FeedItem) rhs.getComponent()).getTitle(); + return lhsTitle.compareTo(rhsTitle); + } + return value; } } -- cgit v1.2.3 From a2e07e749b4274bc20546dcbd73ea690bf25dcb9 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 9 Apr 2017 20:25:35 +0200 Subject: Organize imports --- .../java/de/danoeh/antennapod/core/service/download/DownloadService.java | 1 - 1 file changed, 1 deletion(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 546a8c8d4..3277c2469 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -22,7 +22,6 @@ import android.util.Log; import android.webkit.URLUtil; import org.apache.commons.io.FileUtils; -import org.shredzone.flattr4j.model.User; import org.xml.sax.SAXException; import java.io.File; -- cgit v1.2.3