summaryrefslogtreecommitdiff
path: root/core/src/main/java
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2020-08-15 19:56:21 +0200
committerByteHamster <info@bytehamster.com>2020-08-15 19:56:34 +0200
commitb25e0933ab606ac45ef9c26a745f25845d3af3fc (patch)
tree0344f78cbc1bbf1148ea07c63bdd1212a412a2e7 /core/src/main/java
parent3c5e1138ca1c616dd7add9d567442cc0d9a510ac (diff)
parentd8674e8050fd98961f7eaa9fa844eb03d8bbfb48 (diff)
downloadAntennaPod-b25e0933ab606ac45ef9c26a745f25845d3af3fc.zip
Merge branch 'develop' into add-local-feeds
Diffstat (limited to 'core/src/main/java')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java132
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java30
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilterGroup.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java45
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java16
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/ProviderInstallerInterceptor.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/UserAgentInterceptor.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java73
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java145
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/handler/UnsupportedFeedtypeException.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java222
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/InvalidFeedException.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java14
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java2
50 files changed, 561 insertions, 388 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java
index 24a71ec96..efd53ab9d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/DownloadEvent.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.event;
+import androidx.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -19,6 +21,7 @@ public class DownloadEvent {
return new DownloadEvent(update);
}
+ @NonNull
@Override
public String toString() {
return "DownloadEvent{" +
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java
index 7428c5b00..5ab5decf9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/DownloadLogEvent.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.event;
+import androidx.annotation.NonNull;
+
public class DownloadLogEvent {
private DownloadLogEvent() {
@@ -9,6 +11,7 @@ public class DownloadLogEvent {
return new DownloadLogEvent();
}
+ @NonNull
@Override
public String toString() {
return "DownloadLogEvent";
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java b/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java
index f549940b7..10992408d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java
@@ -46,6 +46,7 @@ public class DownloaderUpdate {
this.mediaIds = mediaIds1.toArray();
}
+ @NonNull
@Override
public String toString() {
return "DownloaderUpdate{" +
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java
index 578007561..d3be8fac0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.event;
+import androidx.annotation.NonNull;
+
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -27,6 +29,7 @@ public class FavoritesEvent {
return new FavoritesEvent(Action.REMOVED, item);
}
+ @NonNull
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java
index 4b14a72d2..02559b2f5 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java
@@ -21,7 +21,7 @@ public class FeedItemEvent {
private final Action action;
@NonNull public final List<FeedItem> items;
- private FeedItemEvent(Action action, List<FeedItem> items) {
+ private FeedItemEvent(@NonNull Action action, @NonNull List<FeedItem> items) {
this.action = action;
this.items = items;
}
@@ -42,6 +42,7 @@ public class FeedItemEvent {
return updated(Arrays.asList(items));
}
+ @NonNull
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java
new file mode 100644
index 000000000..60c38a391
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java
@@ -0,0 +1,132 @@
+package de.danoeh.antennapod.core.export.favorites;
+
+import android.content.Context;
+import android.util.Log;
+
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.storage.DBReader;
+
+/** Writes saved favorites to file. */
+public class FavoritesWriter implements ExportWriter {
+ private static final String TAG = "FavoritesWriter";
+
+ private static final int PAGE_LIMIT = 100;
+
+ private static final String FAVORITE_TEMPLATE = "html-export-favorites-item-template.html";
+ private static final String FEED_TEMPLATE = "html-export-feed-template.html";
+ private static final String UTF_8 = "UTF-8";
+
+ @Override
+ public void writeDocument(List<Feed> feeds, Writer writer, Context context)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ Log.d(TAG, "Starting to write document");
+
+ InputStream templateStream = context.getAssets().open("html-export-template.html");
+ String template = IOUtils.toString(templateStream, UTF_8);
+ template = template.replaceAll("\\{TITLE\\}", "Favorites");
+ String[] templateParts = template.split("\\{FEEDS\\}");
+
+ InputStream favTemplateStream = context.getAssets().open(FAVORITE_TEMPLATE);
+ String favTemplate = IOUtils.toString(favTemplateStream, UTF_8);
+
+ InputStream feedTemplateStream = context.getAssets().open(FEED_TEMPLATE);
+ String feedTemplate = IOUtils.toString(feedTemplateStream, UTF_8);
+
+ Map<Long, List<FeedItem>> favoriteByFeed = getFeedMap(getFavorites());
+
+ writer.append(templateParts[0]);
+
+ for (Long feedId : favoriteByFeed.keySet()) {
+ List<FeedItem> favorites = favoriteByFeed.get(feedId);
+ writer.append("<li><div>\n");
+ writeFeed(writer, favorites.get(0).getFeed(), feedTemplate);
+
+ writer.append("<ul>\n");
+ for (FeedItem item : favorites) {
+ writeFavoriteItem(writer, item, favTemplate);
+ }
+ writer.append("</ul></div></li>\n");
+ }
+
+ writer.append(templateParts[1]);
+
+ Log.d(TAG, "Finished writing document");
+ }
+
+ private List<FeedItem> getFavorites() {
+ int page = 0;
+
+ List<FeedItem> favoritesList = new ArrayList<>();
+ List<FeedItem> favoritesPage;
+ do {
+ favoritesPage = DBReader.getFavoriteItemsList(page * PAGE_LIMIT, PAGE_LIMIT);
+ favoritesList.addAll(favoritesPage);
+ ++page;
+ } while (!favoritesPage.isEmpty() && favoritesPage.size() == PAGE_LIMIT);
+
+ // sort in descending order
+ Collections.sort(favoritesList, (lhs, rhs) -> rhs.getPubDate().compareTo(lhs.getPubDate()));
+
+ return favoritesList;
+ }
+
+ /**
+ * Group favorite episodes by feed, sorting them by publishing date in descending order.
+ *
+ * @param favoritesList {@code List} of all favorite episodes.
+ * @return A {@code Map} favorite episodes, keyed by feed ID.
+ */
+ private Map<Long, List<FeedItem>> getFeedMap(List<FeedItem> favoritesList) {
+ Map<Long, List<FeedItem>> feedMap = new TreeMap<>();
+
+ for (FeedItem item : favoritesList) {
+ List<FeedItem> feedEpisodes = feedMap.get(item.getFeedId());
+
+ if (feedEpisodes == null) {
+ feedEpisodes = new ArrayList<>();
+ feedMap.put(item.getFeedId(), feedEpisodes);
+ }
+
+ feedEpisodes.add(item);
+ }
+
+ return feedMap;
+ }
+
+ private void writeFeed(Writer writer, Feed feed, String feedTemplate) throws IOException {
+ String feedInfo = feedTemplate
+ .replace("{FEED_IMG}", feed.getImageUrl())
+ .replace("{FEED_TITLE}", feed.getTitle())
+ .replace("{FEED_LINK}", feed.getLink())
+ .replace("{FEED_WEBSITE}", feed.getDownload_url());
+
+ writer.append(feedInfo);
+ }
+
+ private void writeFavoriteItem(Writer writer, FeedItem item, String favoriteTemplate) throws IOException {
+ String favItem = favoriteTemplate
+ .replace("{FAV_TITLE}", item.getTitle().trim())
+ .replace("{FAV_WEBSITE}", item.getLink())
+ .replace("{FAV_MEDIA}", item.getMedia().getDownload_url());
+
+ writer.append(favItem);
+ }
+
+ @Override
+ public String fileExtension() {
+ return "html";
+ }
+}
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 93b66daed..3f34343ee 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
@@ -25,6 +25,7 @@ public class HtmlWriter implements ExportWriter {
InputStream templateStream = context.getAssets().open("html-export-template.html");
String template = IOUtils.toString(templateStream, "UTF-8");
+ template = template.replaceAll("\\{TITLE\\}", "Subscriptions");
String[] templateParts = template.split("\\{FEEDS\\}");
writer.append(templateParts[0]);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java
index 2610d253f..3edecd35c 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedComponent.java
@@ -50,7 +50,7 @@ public abstract class FeedComponent {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || !(o instanceof FeedComponent)) return false;
+ if (!(o instanceof FeedComponent)) return false;
FeedComponent that = (FeedComponent) o;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
index 15cdf92dc..044554451 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.feed;
+import androidx.annotation.NonNull;
+
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -18,6 +20,7 @@ public class FeedEvent {
this.feedId = feedId;
}
+ @NonNull
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
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 892592a4b..131cbe563 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,12 +1,15 @@
package de.danoeh.antennapod.core.feed;
import android.database.Cursor;
+
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
+import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@@ -24,7 +27,7 @@ import de.danoeh.antennapod.core.util.ShownotesProvider;
*
* @author daniel
*/
-public class FeedItem extends FeedComponent implements ShownotesProvider, ImageResource {
+public class FeedItem extends FeedComponent implements ShownotesProvider, ImageResource, Serializable {
/** tag that indicates this item is in the queue */
public static final String TAG_QUEUE = "Queue";
@@ -481,6 +484,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, ImageR
*/
public void removeTag(String tag) { tags.remove(tag); }
+ @NonNull
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
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 719383d23..d34e23506 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
@@ -1,8 +1,10 @@
package de.danoeh.antennapod.core.feed;
import android.text.TextUtils;
+import android.util.Log;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -11,17 +13,21 @@ import de.danoeh.antennapod.core.util.LongList;
import static de.danoeh.antennapod.core.feed.FeedItem.TAG_FAVORITE;
public class FeedItemFilter {
+
private final String[] mProperties;
private boolean showPlayed = false;
private boolean showUnplayed = false;
private boolean showPaused = false;
+ private boolean showNotPaused = false;
private boolean showQueued = false;
private boolean showNotQueued = false;
private boolean showDownloaded = false;
private boolean showNotDownloaded = false;
private boolean showHasMedia = false;
+ private boolean showNoMedia = false;
private boolean showIsFavorite = false;
+ private boolean showNotFavorite = false;
public FeedItemFilter(String properties) {
this(TextUtils.split(properties, ","));
@@ -29,15 +35,18 @@ public class FeedItemFilter {
public FeedItemFilter(String[] properties) {
this.mProperties = properties;
- for(String property : properties) {
+ for (String property : properties) {
// see R.arrays.feed_filter_values
- switch(property) {
+ switch (property) {
case "unplayed":
showUnplayed = true;
break;
case "paused":
showPaused = true;
break;
+ case "not_paused":
+ showNotPaused = true;
+ break;
case "played":
showPlayed = true;
break;
@@ -56,9 +65,17 @@ public class FeedItemFilter {
case "has_media":
showHasMedia = true;
break;
+ case "no_media":
+ showNoMedia = true;
+ break;
case "is_favorite":
showIsFavorite = true;
break;
+ case "not_favorite":
+ showNotFavorite = true;
+ break;
+ default:
+ break;
}
}
}
@@ -77,12 +94,15 @@ public class FeedItemFilter {
if (showQueued && showNotQueued) return result;
if (showDownloaded && showNotDownloaded) return result;
- final LongList queuedIds = DBReader.getQueueIDList();
- for(FeedItem item : items) {
+ final LongList queuedIds = DBReader.getQueueIDList();
+ for (FeedItem item : items) {
// If the item does not meet a requirement, skip it.
+
if (showPlayed && !item.isPlayed()) continue;
if (showUnplayed && item.isPlayed()) continue;
+
if (showPaused && item.getState() != FeedItem.State.IN_PROGRESS) continue;
+ if (showNotPaused && item.getState() == FeedItem.State.IN_PROGRESS) continue;
boolean queued = queuedIds.contains(item.getId());
if (showQueued && !queued) continue;
@@ -93,8 +113,10 @@ public class FeedItemFilter {
if (showNotDownloaded && downloaded) continue;
if (showHasMedia && !item.hasMedia()) continue;
+ if (showNoMedia && item.hasMedia()) continue;
if (showIsFavorite && !item.isTagged(TAG_FAVORITE)) continue;
+ if (showNotFavorite && item.isTagged(TAG_FAVORITE)) continue;
// If the item reaches here, it meets all criteria
result.add(item);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilterGroup.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilterGroup.java
new file mode 100644
index 000000000..fcbe2e4ab
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilterGroup.java
@@ -0,0 +1,36 @@
+package de.danoeh.antennapod.core.feed;
+
+import de.danoeh.antennapod.core.R;
+
+public enum FeedItemFilterGroup {
+ PLAYED(new ItemProperties(R.string.hide_played_episodes_label, "played"),
+ new ItemProperties(R.string.not_played, "unplayed")),
+ PAUSED(new ItemProperties(R.string.hide_paused_episodes_label, "paused"),
+ new ItemProperties(R.string.not_paused, "not_paused")),
+ FAVORITE(new ItemProperties(R.string.hide_is_favorite_label, "is_favorite"),
+ new ItemProperties(R.string.not_favorite, "not_favorite")),
+ MEDIA(new ItemProperties(R.string.has_media, "has_media"),
+ new ItemProperties(R.string.no_media, "no_media")),
+ QUEUED(new ItemProperties(R.string.queued_label, "queued"),
+ new ItemProperties(R.string.not_queued_label, "not_queued")),
+ DOWNLOADED(new ItemProperties(R.string.hide_downloaded_episodes_label, "downloaded"),
+ new ItemProperties(R.string.hide_not_downloaded_episodes_label, "not_downloaded"));
+
+ public final ItemProperties[] values;
+
+ FeedItemFilterGroup(ItemProperties... values) {
+ this.values = values;
+ }
+
+ public static class ItemProperties {
+
+ public final int displayName;
+ public final String filterId;
+
+ public ItemProperties(int displayName, String filterId) {
+ this.displayName = displayName;
+ this.filterId = filterId;
+ }
+
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
index 083e8c500..92e45376a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
@@ -482,7 +482,7 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public void onPlaybackStart() {
- startPosition = (position > 0) ? position : 0;
+ startPosition = Math.max(position, 0);
playedDurationWhenStarted = played_duration;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java
index 36da11eca..35a9d987b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java
@@ -28,8 +28,9 @@ import org.apache.commons.io.IOUtils;
public final class ChapterImageModelLoader implements ModelLoader<EmbeddedChapterImage, ByteBuffer> {
public static class Factory implements ModelLoaderFactory<EmbeddedChapterImage, ByteBuffer> {
+ @NonNull
@Override
- public ModelLoader<EmbeddedChapterImage, ByteBuffer> build(MultiModelLoaderFactory unused) {
+ public ModelLoader<EmbeddedChapterImage, ByteBuffer> build(@NonNull MultiModelLoaderFactory unused) {
return new ChapterImageModelLoader();
}
@@ -41,12 +42,15 @@ public final class ChapterImageModelLoader implements ModelLoader<EmbeddedChapte
@Nullable
@Override
- public LoadData<ByteBuffer> buildLoadData(EmbeddedChapterImage model, int width, int height, Options options) {
+ public LoadData<ByteBuffer> buildLoadData(@NonNull EmbeddedChapterImage model,
+ int width,
+ int height,
+ @NonNull Options options) {
return new LoadData<>(new ObjectKey(model), new EmbeddedImageFetcher(model));
}
@Override
- public boolean handles(EmbeddedChapterImage model) {
+ public boolean handles(@NonNull EmbeddedChapterImage model) {
return true;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
index d0301db2f..1f8ae5ad9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
@@ -21,7 +21,10 @@ public class FastBlurTransformation extends BitmapTransformation {
}
@Override
- protected Bitmap transform(BitmapPool pool, Bitmap source, int outWidth, int outHeight) {
+ protected Bitmap transform(@NonNull BitmapPool pool,
+ @NonNull Bitmap source,
+ int outWidth,
+ int outHeight) {
int targetWidth = outWidth / 3;
int targetHeight = (int) (1.0 * outHeight * targetWidth / outWidth);
Bitmap resized = ThumbnailUtils.extractThumbnail(source, targetWidth, targetHeight);
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 876251563..3488d125e 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
@@ -19,10 +19,14 @@ import org.json.JSONException;
import java.io.File;
import java.io.IOException;
import java.net.Proxy;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -64,6 +68,7 @@ public class UserPreferences {
private static final String PREF_SHOW_AUTO_DOWNLOAD_REPORT = "prefShowAutoDownloadReport";
public static final String PREF_BACK_BUTTON_BEHAVIOR = "prefBackButtonBehavior";
private static final String PREF_BACK_BUTTON_GO_TO_PAGE = "prefBackButtonGoToPage";
+ public static final String PREF_FILTER_FEED = "prefFeedFilter";
public static final String PREF_QUEUE_KEEP_SORTED = "prefQueueKeepSorted";
public static final String PREF_QUEUE_KEEP_SORTED_ORDER = "prefQueueKeepSortedOrder";
@@ -146,6 +151,8 @@ public class UserPreferences {
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;
+ public static final int FEED_FILTER_NONE = 0;
+ public static final int FEED_FILTER_COUNTER_ZERO = 1;
private static Context context;
private static SharedPreferences prefs;
@@ -414,7 +421,7 @@ public class UserPreferences {
return prefs.getBoolean(PREF_PLAYBACK_SKIP_SILENCE, false);
}
- public static float[] getPlaybackSpeedArray() {
+ public static List<Float> getPlaybackSpeedArray() {
return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null));
}
@@ -628,8 +635,7 @@ public class UserPreferences {
}
public static boolean isQueueLocked() {
- return prefs.getBoolean(PREF_QUEUE_LOCKED, false)
- || isQueueKeepSorted();
+ return prefs.getBoolean(PREF_QUEUE_LOCKED, false);
}
public static void setFastForwardSecs(int secs) {
@@ -662,10 +668,13 @@ public class UserPreferences {
.apply();
}
- public static void setPlaybackSpeedArray(String[] speeds) {
+ public static void setPlaybackSpeedArray(List<Float> speeds) {
+ DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US);
+ format.setDecimalSeparator('.');
+ DecimalFormat speedFormat = new DecimalFormat("0.00", format);
JSONArray jsonArray = new JSONArray();
- for (String speed : speeds) {
- jsonArray.put(speed);
+ for (float speed : speeds) {
+ jsonArray.put(speedFormat.format(speed));
}
prefs.edit()
.putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString())
@@ -775,13 +784,13 @@ public class UserPreferences {
}
}
- private static float[] readPlaybackSpeedArray(String valueFromPrefs) {
+ private static List<Float> readPlaybackSpeedArray(String valueFromPrefs) {
if (valueFromPrefs != null) {
try {
JSONArray jsonArray = new JSONArray(valueFromPrefs);
- float[] selectedSpeeds = new float[jsonArray.length()];
+ List<Float> selectedSpeeds = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
- selectedSpeeds[i] = (float) jsonArray.getDouble(i);
+ selectedSpeeds.add((float) jsonArray.getDouble(i));
}
return selectedSpeeds;
} catch (JSONException e) {
@@ -790,7 +799,7 @@ public class UserPreferences {
}
}
// If this preference hasn't been set yet, return the default options
- return new float[] { 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f };
+ return Arrays.asList(0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f);
}
public static String getMediaPlayer() {
@@ -826,8 +835,8 @@ public class UserPreferences {
public static VideoBackgroundBehavior getVideoBackgroundBehavior() {
switch (prefs.getString(PREF_VIDEO_BEHAVIOR, "pip")) {
case "stop": return VideoBackgroundBehavior.STOP;
- case "pip": return VideoBackgroundBehavior.PICTURE_IN_PICTURE;
case "continue": return VideoBackgroundBehavior.CONTINUE_PLAYING;
+ case "pip": //Deliberate fall-through
default: return VideoBackgroundBehavior.PICTURE_IN_PICTURE;
}
}
@@ -977,11 +986,11 @@ public class UserPreferences {
public static BackButtonBehavior getBackButtonBehavior() {
switch (prefs.getString(PREF_BACK_BUTTON_BEHAVIOR, "default")) {
- case "default": return BackButtonBehavior.DEFAULT;
case "drawer": return BackButtonBehavior.OPEN_DRAWER;
case "doubletap": return BackButtonBehavior.DOUBLE_TAP;
case "prompt": return BackButtonBehavior.SHOW_PROMPT;
case "page": return BackButtonBehavior.GO_TO_PAGE;
+ case "default": // Deliberate fall-through
default: return BackButtonBehavior.DEFAULT;
}
}
@@ -1052,4 +1061,16 @@ public class UserPreferences {
.putString(PREF_QUEUE_KEEP_SORTED_ORDER, sortOrder.name())
.apply();
}
+
+ public static int getFeedFilter() {
+ String value = prefs.getString(PREF_FILTER_FEED, "" + FEED_FILTER_NONE);
+ return Integer.parseInt(value);
+ }
+
+ public static void setFeedFilter(String value) {
+ prefs.edit()
+ .putString(PREF_FILTER_FEED, value)
+ .commit();
+ }
+
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
index 4562f1393..7585e9d33 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
@@ -103,12 +103,8 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
AppWidgetManager manager = AppWidgetManager.getInstance(this);
int[] widgetIds = manager.getAppWidgetIds(playerWidget);
RemoteViews views = new RemoteViews(getPackageName(), R.layout.player_widget);
- PendingIntent startMediaplayer = PendingIntent.getActivity(this, 0,
- PlaybackService.getPlayerActivityIntent(this), 0);
-
- final PendingIntent startAppPending = PendingIntent.getActivity(this, 0,
- PlaybackService.getPlayerActivityIntent(this),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ final PendingIntent startMediaPlayer = PendingIntent.getActivity(this, R.id.pending_intent_player_activity,
+ PlaybackService.getPlayerActivityIntent(this), PendingIntent.FLAG_UPDATE_CURRENT);
boolean nothingPlaying = false;
Playable media;
@@ -122,10 +118,10 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
}
if (media != null) {
- views.setOnClickPendingIntent(R.id.layout_left, startMediaplayer);
+ views.setOnClickPendingIntent(R.id.layout_left, startMediaPlayer);
try {
- Bitmap icon = null;
+ Bitmap icon;
int iconSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
icon = Glide.with(PlayerWidgetJobService.this)
.asBitmap()
@@ -170,8 +166,8 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
if (nothingPlaying) {
// start the app if they click anything
- views.setOnClickPendingIntent(R.id.layout_left, startAppPending);
- views.setOnClickPendingIntent(R.id.butPlay, startAppPending);
+ views.setOnClickPendingIntent(R.id.layout_left, startMediaPlayer);
+ views.setOnClickPendingIntent(R.id.butPlay, startMediaPlayer);
views.setViewVisibility(R.id.txtvProgress, View.GONE);
views.setViewVisibility(R.id.txtvTitle, View.GONE);
views.setViewVisibility(R.id.txtNoPlaying, View.VISIBLE);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/ProviderInstallerInterceptor.java b/core/src/main/java/de/danoeh/antennapod/core/service/ProviderInstallerInterceptor.java
new file mode 100644
index 000000000..4fa1fc3d7
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/ProviderInstallerInterceptor.java
@@ -0,0 +1,18 @@
+package de.danoeh.antennapod.core.service;
+
+import androidx.annotation.NonNull;
+import okhttp3.Interceptor;
+import okhttp3.Response;
+
+import java.io.IOException;
+
+public class ProviderInstallerInterceptor implements Interceptor {
+ public static Runnable installer = () -> { };
+
+ @Override
+ @NonNull
+ public Response intercept(Chain chain) throws IOException {
+ installer.run();
+ return chain.proceed(chain.request());
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/UserAgentInterceptor.java b/core/src/main/java/de/danoeh/antennapod/core/service/UserAgentInterceptor.java
index 5fcf8317d..3676347f7 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/UserAgentInterceptor.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/UserAgentInterceptor.java
@@ -7,10 +7,6 @@ import okhttp3.Response;
import java.io.IOException;
public class UserAgentInterceptor implements Interceptor {
-
- public UserAgentInterceptor() {
- }
-
@Override
public Response intercept(Chain chain) throws IOException {
return chain.proceed(chain.request().newBuilder()
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 e0c23bdac..9d0b3c5ad 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
@@ -32,6 +32,7 @@ import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.service.ProviderInstallerInterceptor;
import de.danoeh.antennapod.core.service.UserAgentInterceptor;
import de.danoeh.antennapod.core.storage.DBWriter;
import okhttp3.Cache;
@@ -116,6 +117,7 @@ public class AntennapodHttpClient {
}
return response;
});
+ builder.interceptors().add(new ProviderInstallerInterceptor());
builder.interceptors().add(new BasicAuthorizationInterceptor());
builder.networkInterceptors().add(new UserAgentInterceptor());
@@ -154,8 +156,8 @@ public class AntennapodHttpClient {
// workaround for Android 4.x for certain web sites.
// see: https://github.com/square/okhttp/issues/4053#issuecomment-402579554
- List<CipherSuite> cipherSuites = new ArrayList<>();
- cipherSuites.addAll(ConnectionSpec.MODERN_TLS.cipherSuites());
+ List<CipherSuite> cipherSuites = new ArrayList<>(
+ ConnectionSpec.MODERN_TLS.cipherSuites());
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
index 78c4d3f48..3f503c6b4 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
@@ -115,7 +115,7 @@ public class DownloadRequest implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || !(o instanceof DownloadRequest)) return false;
+ if (!(o instanceof DownloadRequest)) return false;
DownloadRequest that = (DownloadRequest) o;
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 28523ef0a..e44aa716a 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
@@ -17,6 +17,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.sync.SyncService;
import org.apache.commons.io.FileUtils;
import org.greenrobot.eventbus.EventBus;
@@ -87,8 +88,6 @@ public class DownloadService extends Service {
public static final String EXTRA_CLEANUP_MEDIA = "cleanupMedia";
- public static final int NOTIFICATION_ID = 2;
-
/**
* Contains all completed downloads that have not been included in the report yet.
*/
@@ -165,7 +164,7 @@ public class DownloadService extends Service {
if (intent != null && intent.getParcelableArrayListExtra(EXTRA_REQUESTS) != null) {
Notification notification = notificationManager.updateNotifications(
requester.getNumberOfDownloads(), downloads);
- startForeground(NOTIFICATION_ID, notification);
+ startForeground(R.id.notification_downloading, notification);
syncExecutor.execute(() -> onDownloadQueued(intent));
} else if (numberOfDownloads.get() == 0) {
stopSelf();
@@ -191,7 +190,7 @@ public class DownloadService extends Service {
Notification notification = notificationManager.updateNotifications(
requester.getNumberOfDownloads(), downloads);
- startForeground(NOTIFICATION_ID, notification);
+ startForeground(R.id.notification_downloading, notification);
}
@Override
@@ -229,7 +228,7 @@ public class DownloadService extends Service {
stopForeground(true);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- nm.cancel(NOTIFICATION_ID);
+ nm.cancel(R.id.notification_downloading);
// if this was the initial gpodder sync, i.e. we just synced the feeds successfully,
// it is now time to sync the episode actions
@@ -480,12 +479,9 @@ public class DownloadService extends Service {
}
handler.post(() -> {
downloads.add(downloader);
+ downloadExecutor.submit(downloader);
postDownloaders();
});
- // Needs to be done after postDownloaders() because otherwise,
- // it might take long before the progress bar circle starts spinning
- ClientConfig.installSslProvider(this);
- handler.post(() -> downloadExecutor.submit(downloader));
}
handler.post(this::queryDownloads);
}
@@ -566,7 +562,7 @@ public class DownloadService extends Service {
setupNotificationUpdater();
Notification notification = notificationManager.updateNotifications(
requester.getNumberOfDownloads(), downloads);
- startForeground(NOTIFICATION_ID, notification);
+ startForeground(R.id.notification_downloading, notification);
}
}
@@ -642,7 +638,7 @@ public class DownloadService extends Service {
Notification n = notificationManager.updateNotifications(requester.getNumberOfDownloads(), downloads);
if (n != null) {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- nm.notify(NOTIFICATION_ID, n);
+ nm.notify(R.id.notification_downloading, n);
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java
index f487193f3..64666d25d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java
@@ -17,8 +17,6 @@ import java.util.List;
public class DownloadServiceNotification {
private static final String TAG = "DownloadSvcNotification";
- private static final int REPORT_ID = 3;
- private static final int AUTO_REPORT_ID = 4;
private final Context context;
private NotificationCompat.Builder notificationCompatBuilder;
@@ -147,14 +145,14 @@ public class DownloadServiceNotification {
titleId = R.string.auto_download_report_title;
iconId = R.drawable.ic_notification_auto_download_complete;
intent = ClientConfig.downloadServiceCallbacks.getAutoDownloadReportNotificationContentIntent(context);
- id = AUTO_REPORT_ID;
+ id = R.id.notification_auto_download_report;
content = createAutoDownloadNotificationContent(reportQueue);
} else {
channelId = NotificationUtils.CHANNEL_ID_ERROR;
titleId = R.string.download_report_title;
iconId = R.drawable.ic_notification_sync_error;
intent = ClientConfig.downloadServiceCallbacks.getReportNotificationContentIntent(context);
- id = REPORT_ID;
+ id = R.id.notification_download_report;
content = String.format(context.getString(R.string.download_report_content), successfulDownloads, failedDownloads);
}
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 54b8d321a..61608992b 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
@@ -65,11 +65,12 @@ public class HttpDownloader extends Downloader {
final URI uri = URIUtil.getURIFromRequestUrl(request.getSource());
Request.Builder httpReq = new Request.Builder().url(uri.toURL());
httpReq.tag(request);
+ httpReq.cacheControl(new CacheControl.Builder().noStore().build());
+
if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
// set header explicitly so that okhttp doesn't do transparent gzip
Log.d(TAG, "addHeader(\"Accept-Encoding\", \"identity\")");
httpReq.addHeader("Accept-Encoding", "identity");
- httpReq.cacheControl(new CacheControl.Builder().noStore().build());
}
if (!TextUtils.isEmpty(request.getLastModified())) {
@@ -189,7 +190,7 @@ public class HttpDownloader extends Downloader {
}
byte[] buffer = new byte[BUFFER_SIZE];
- int count = 0;
+ int count;
request.setStatusMsg(R.string.download_running);
Log.d(TAG, "Getting size of download");
request.setSize(responseBody.contentLength() + request.getSoFar());
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
index 05e602db8..c50162788 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
@@ -49,10 +49,7 @@ public class FeedParserTask implements Callable<FeedHandlerResult> {
try {
result = feedHandler.parseFeed(feed);
Log.d(TAG, feed.getTitle() + " parsed");
- if (!checkFeedData(feed)) {
- throw new InvalidFeedException();
- }
-
+ checkFeedData(feed);
} catch (SAXException | IOException | ParserConfigurationException e) {
successful = false;
e.printStackTrace();
@@ -95,23 +92,17 @@ public class FeedParserTask implements Callable<FeedHandlerResult> {
/**
* Checks if the feed was parsed correctly.
*/
- private boolean checkFeedData(Feed feed) {
+ private void checkFeedData(Feed feed) throws InvalidFeedException {
if (feed.getTitle() == null) {
- Log.e(TAG, "Feed has no title.");
- return false;
- }
- if (!hasValidFeedItems(feed)) {
- Log.e(TAG, "Feed has invalid items");
- return false;
+ throw new InvalidFeedException("Feed has no title");
}
- return true;
+ checkFeedItems(feed);
}
- private boolean hasValidFeedItems(Feed feed) {
+ private void checkFeedItems(Feed feed) throws InvalidFeedException {
for (FeedItem item : feed.getItems()) {
if (item.getTitle() == null) {
- Log.e(TAG, "Item has no title");
- return false;
+ throw new InvalidFeedException("Item has no title: " + item);
}
if (item.getPubDate() == null) {
Log.e(TAG, "Item has no pubDate. Using current time as pubDate");
@@ -121,7 +112,6 @@ public class FeedParserTask implements Callable<FeedHandlerResult> {
item.setPubDate(new Date());
}
}
- return true;
}
public DownloadStatus getDownloadStatus() {
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 33a2a72ff..111e2d37c 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
@@ -79,6 +79,7 @@ import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import io.reactivex.Observable;
+import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import org.greenrobot.eventbus.EventBus;
@@ -204,9 +205,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
*/
private static volatile boolean isCasting = false;
- private static final int NOTIFICATION_ID = 1;
- private static final int NOTIFICATION_ID_STREAMING = 2;
-
private PlaybackServiceMediaPlayer mediaPlayer;
private PlaybackServiceTaskManager taskManager;
private PlaybackServiceFlavorHelper flavorHelper;
@@ -271,7 +269,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
stateManager = new PlaybackServiceStateManager(this);
notificationBuilder = new PlaybackServiceNotificationBuilder(this);
- stateManager.startForeground(NOTIFICATION_ID, notificationBuilder.build());
registerReceiver(autoStateUpdated, new IntentFilter("com.google.android.gms.car.media.STATUS"));
registerReceiver(headsetDisconnected, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
@@ -307,18 +304,16 @@ public class PlaybackService extends MediaBrowserServiceCompat {
npe.printStackTrace();
}
- List<MediaSessionCompat.QueueItem> queueItems = new ArrayList<>();
- try {
+ Single.<List<MediaSessionCompat.QueueItem>>create(emitter -> {
+ List<MediaSessionCompat.QueueItem> queueItems = new ArrayList<>();
for (FeedItem feedItem : taskManager.getQueue()) {
if (feedItem.getMedia() != null) {
MediaDescriptionCompat mediaDescription = feedItem.getMedia().getMediaItem().getDescription();
queueItems.add(new MediaSessionCompat.QueueItem(mediaDescription, feedItem.getId()));
}
}
- mediaSession.setQueue(queueItems);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ emitter.onSuccess(queueItems);
+ }).subscribe(queueItems -> mediaSession.setQueue(queueItems), Throwable::printStackTrace);
flavorHelper.initializeMediaPlayer(PlaybackService.this);
mediaSession.setActive(true);
@@ -334,7 +329,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
if (notificationBuilder.getPlayerStatus() == PlayerStatus.PLAYING) {
notificationBuilder.setPlayerStatus(PlayerStatus.STOPPED);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
- notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
+ notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
}
stateManager.stopForeground(!UserPreferences.isPersistNotify());
isRunning = false;
@@ -424,7 +419,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
e.printStackTrace();
}
} else if (parentId.startsWith("FeedId:")) {
- Long feedId = Long.parseLong(parentId.split(":")[1]);
+ long feedId = Long.parseLong(parentId.split(":")[1]);
List<FeedItem> feedItems = DBReader.getFeedItemList(DBReader.getFeed(feedId));
for (FeedItem feedItem : feedItems) {
if (feedItem.getMedia() != null && feedItem.getMedia().getMediaItem() != null) {
@@ -450,9 +445,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "OnStartCommand called");
- stateManager.startForeground(NOTIFICATION_ID, notificationBuilder.build());
+ stateManager.startForeground(R.id.notification_playing, notificationBuilder.build());
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
- notificationManager.cancel(NOTIFICATION_ID_STREAMING);
+ notificationManager.cancel(R.id.notification_streaming_confirmation);
final int keycode = intent.getIntExtra(MediaButtonReceiver.EXTRA_KEYCODE, -1);
final boolean castDisconnect = intent.getBooleanExtra(EXTRA_CAST_DISCONNECT, false);
@@ -542,9 +537,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
intentAllowThisTime.putExtra(EXTRA_ALLOW_STREAM_THIS_TIME, true);
PendingIntent pendingIntentAllowThisTime;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- pendingIntentAllowThisTime = PendingIntent.getForegroundService(this, 0, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT);
+ pendingIntentAllowThisTime = PendingIntent.getForegroundService(this,
+ R.id.pending_intent_allow_stream_this_time, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT);
} else {
- pendingIntentAllowThisTime = PendingIntent.getService(this, 0, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT);
+ pendingIntentAllowThisTime = PendingIntent.getService(this,
+ R.id.pending_intent_allow_stream_this_time, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT);
}
Intent intentAlwaysAllow = new Intent(intentAllowThisTime);
@@ -552,12 +549,15 @@ public class PlaybackService extends MediaBrowserServiceCompat {
intentAlwaysAllow.putExtra(EXTRA_ALLOW_STREAM_ALWAYS, true);
PendingIntent pendingIntentAlwaysAllow;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- pendingIntentAlwaysAllow = PendingIntent.getForegroundService(this, 0, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT);
+ pendingIntentAlwaysAllow = PendingIntent.getForegroundService(this,
+ R.id.pending_intent_allow_stream_always, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT);
} else {
- pendingIntentAlwaysAllow = PendingIntent.getService(this, 0, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT);
+ pendingIntentAlwaysAllow = PendingIntent.getService(this,
+ R.id.pending_intent_allow_stream_always, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT);
}
- NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NotificationUtils.CHANNEL_ID_USER_ACTION)
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this,
+ NotificationUtils.CHANNEL_ID_USER_ACTION)
.setSmallIcon(R.drawable.ic_stream_white)
.setContentTitle(getString(R.string.confirm_mobile_streaming_notification_title))
.setContentText(getString(R.string.confirm_mobile_streaming_notification_message))
@@ -573,7 +573,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
pendingIntentAlwaysAllow)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
- notificationManager.notify(NOTIFICATION_ID_STREAMING, builder.build());
+ notificationManager.notify(R.id.notification_streaming_confirmation, builder.build());
}
/**
@@ -711,9 +711,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
@Override
- public void onSleepTimerAlmostExpired() {
- float leftVolume = 0.1f * UserPreferences.getLeftVolume();
- float rightVolume = 0.1f * UserPreferences.getRightVolume();
+ public void onSleepTimerAlmostExpired(long timeLeft) {
+ final float[] multiplicators = {0.1f, 0.2f, 0.3f, 0.3f, 0.3f, 0.4f, 0.4f, 0.4f, 0.6f, 0.8f};
+ float multiplicator = multiplicators[Math.max(0, (int) timeLeft / 1000)];
+ Log.d(TAG, "onSleepTimerAlmostExpired: " + multiplicator);
+ float leftVolume = multiplicator * UserPreferences.getLeftVolume();
+ float rightVolume = multiplicator * UserPreferences.getRightVolume();
mediaPlayer.setVolume(leftVolume, rightVolume);
}
@@ -1140,13 +1143,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
case INITIALIZING:
state = PlaybackStateCompat.STATE_CONNECTING;
break;
- case INITIALIZED:
- case INDETERMINATE:
- state = PlaybackStateCompat.STATE_NONE;
- break;
case ERROR:
state = PlaybackStateCompat.STATE_ERROR;
break;
+ case INITIALIZED: // Deliberate fall-through
+ case INDETERMINATE:
default:
state = PlaybackStateCompat.STATE_NONE;
break;
@@ -1158,7 +1159,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
long capabilities = PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_REWIND
| PlaybackStateCompat.ACTION_FAST_FORWARD
- | PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
+ | PlaybackStateCompat.ACTION_SKIP_TO_NEXT
+ | PlaybackStateCompat.ACTION_SEEK_TO;
if (useSkipToPreviousForRewindInLockscreen()) {
// Workaround to fool Android so that Lockscreen will expose a skip-to-previous button,
@@ -1238,9 +1240,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
}
if (!Thread.currentThread().isInterrupted() && stateManager.hasReceivedValidStartCommand()) {
- mediaSession.setSessionActivity(PendingIntent.getActivity(this, 0,
- PlaybackService.getPlayerActivityIntent(this),
- PendingIntent.FLAG_UPDATE_CURRENT));
+ mediaSession.setSessionActivity(PendingIntent.getActivity(this, R.id.pending_intent_player_activity,
+ PlaybackService.getPlayerActivityIntent(this), PendingIntent.FLAG_UPDATE_CURRENT));
try {
mediaSession.setMetadata(builder.build());
} catch (OutOfMemoryError e) {
@@ -1289,7 +1290,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
notificationBuilder.updatePosition(getCurrentPosition(), getCurrentPlaybackSpeed());
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
- notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
+ notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
startForegroundIfPlaying(playerStatus);
if (!notificationBuilder.isIconCached()) {
@@ -1297,7 +1298,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
Log.d(TAG, "Loading notification icon");
notificationBuilder.loadIcon();
if (!Thread.currentThread().isInterrupted()) {
- notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
+ notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
}
});
notificationSetupThread.start();
@@ -1309,12 +1310,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
if (stateManager.hasReceivedValidStartCommand()) {
if (isCasting || status == PlayerStatus.PLAYING || status == PlayerStatus.PREPARING
|| status == PlayerStatus.SEEKING) {
- stateManager.startForeground(NOTIFICATION_ID, notificationBuilder.build());
+ stateManager.startForeground(R.id.notification_playing, notificationBuilder.build());
Log.d(TAG, "foreground");
} else {
stateManager.stopForeground(false);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
- notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
+ notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
}
}
}
@@ -1717,7 +1718,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
notificationBuilder.updatePosition(getCurrentPosition(), getCurrentPlaybackSpeed());
NotificationManager notificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
- notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
+ notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
}
skipEndingIfNecessary();
});
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java
index 174b43846..3239f3378 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java
@@ -131,7 +131,7 @@ public class PlaybackServiceNotificationBuilder {
}
} else {
notification.setContentTitle(context.getString(R.string.app_name));
- notification.setContentText("Service is running");
+ notification.setContentText("Loading. If this does not go away, play any episode and contact us.");
}
notification.setContentIntent(getPlayerActivityPendingIntent());
@@ -146,8 +146,8 @@ public class PlaybackServiceNotificationBuilder {
}
private PendingIntent getPlayerActivityPendingIntent() {
- return PendingIntent.getActivity(context, 0, PlaybackService.getPlayerActivityIntent(context),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ return PendingIntent.getActivity(context, R.id.pending_intent_player_activity,
+ PlaybackService.getPlayerActivityIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);
}
private void addActions(NotificationCompat.Builder notification, MediaSessionCompat.Token mediaSessionToken,
@@ -183,15 +183,14 @@ public class PlaybackServiceNotificationBuilder {
notification.addAction(R.drawable.ic_notification_pause, //pause action
context.getString(R.string.pause_label),
pauseButtonPendingIntent);
- compactActionList.add(numActions++);
} else {
PendingIntent playButtonPendingIntent = getPendingIntentForMediaAction(
KeyEvent.KEYCODE_MEDIA_PLAY, numActions);
notification.addAction(R.drawable.ic_notification_play, //play action
context.getString(R.string.play_label),
playButtonPendingIntent);
- compactActionList.add(numActions++);
}
+ compactActionList.add(numActions++);
// ff follows play, then we have skip (if it's present)
PendingIntent ffButtonPendingIntent = getPendingIntentForMediaAction(
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
index e71c1dfa7..55212cd46 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
@@ -316,7 +316,8 @@ public class PlaybackServiceTaskManager {
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(() -> callback.onChapterLoaded(media));
+ .subscribe(() -> callback.onChapterLoaded(media),
+ throwable -> Log.d(TAG, "Error loading chapters: " + Log.getStackTraceString(throwable)));
}
}
@@ -359,7 +360,8 @@ public class PlaybackServiceTaskManager {
class SleepTimer implements Runnable {
private static final String TAG = "SleepTimer";
private static final long UPDATE_INTERVAL = 1000L;
- private static final long NOTIFICATION_THRESHOLD = 10000;
+ public static final long NOTIFICATION_THRESHOLD = 10000;
+ private boolean hasVibrated = false;
private final long waitingTime;
private long timeLeft;
private ShakeListener shakeListener;
@@ -389,7 +391,6 @@ public class PlaybackServiceTaskManager {
@Override
public void run() {
Log.d(TAG, "Starting");
- boolean notifiedAlmostExpired = false;
long lastTick = System.currentTimeMillis();
while (timeLeft > 0) {
try {
@@ -404,19 +405,19 @@ public class PlaybackServiceTaskManager {
timeLeft -= now - lastTick;
lastTick = now;
- if (timeLeft < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) {
+ if (timeLeft < NOTIFICATION_THRESHOLD) {
Log.d(TAG, "Sleep timer is about to expire");
- if (SleepTimerPreferences.vibrate()) {
+ if (SleepTimerPreferences.vibrate() && !hasVibrated) {
Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (v != null) {
v.vibrate(500);
+ hasVibrated = true;
}
}
if (shakeListener == null && SleepTimerPreferences.shakeToReset()) {
shakeListener = new ShakeListener(context, this);
}
- postCallback(callback::onSleepTimerAlmostExpired);
- notifiedAlmostExpired = true;
+ postCallback(() -> callback.onSleepTimerAlmostExpired(timeLeft));
}
if (timeLeft <= 0) {
Log.d(TAG, "Sleep timer expired");
@@ -424,6 +425,7 @@ public class PlaybackServiceTaskManager {
shakeListener.pause();
shakeListener = null;
}
+ hasVibrated = false;
if (!Thread.currentThread().isInterrupted()) {
postCallback(callback::onSleepTimerExpired);
} else {
@@ -460,7 +462,7 @@ public class PlaybackServiceTaskManager {
public interface PSTMCallback {
void positionSaverTick();
- void onSleepTimerAlmostExpired();
+ void onSleepTimerAlmostExpired(long timeLeft);
void onSleepTimerExpired();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java
index b0b6e164d..b967577af 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java
@@ -58,7 +58,6 @@ class ShakeListener implements SensorEventListener
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
- return;
}
} \ No newline at end of file
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 c30f46315..0de67b306 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
@@ -72,19 +72,13 @@ public final class DBReader {
@NonNull
private static List<Feed> getFeedList(PodDBAdapter adapter) {
- Cursor cursor = null;
- try {
- cursor = adapter.getAllFeedsCursor();
+ try (Cursor cursor = adapter.getAllFeedsCursor()) {
List<Feed> feeds = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
Feed feed = extractFeedFromCursorRow(cursor);
feeds.add(feed);
}
return feeds;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -96,18 +90,13 @@ public final class DBReader {
public static List<String> getFeedListDownloadUrls() {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getFeedCursorDownloadUrls();
+ try (Cursor cursor = adapter.getFeedCursorDownloadUrls()) {
List<String> result = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
result.add(cursor.getString(1));
}
return result;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -172,9 +161,7 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getAllItemsOfFeedCursor(feed);
+ try (Cursor cursor = adapter.getAllItemsOfFeedCursor(feed)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
Collections.sort(items, new FeedItemPubdateComparator());
for (FeedItem item : items) {
@@ -182,9 +169,6 @@ public final class DBReader {
}
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -226,16 +210,10 @@ public final class DBReader {
@NonNull
static List<FeedItem> getQueue(PodDBAdapter adapter) {
Log.d(TAG, "getQueue()");
- Cursor cursor = null;
- try {
- cursor = adapter.getQueueCursor();
+ try (Cursor cursor = adapter.getQueueCursor()) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -257,18 +235,12 @@ public final class DBReader {
}
private static LongList getQueueIDList(PodDBAdapter adapter) {
- Cursor cursor = null;
- try {
- cursor = adapter.getQueueIDCursor();
+ try (Cursor cursor = adapter.getQueueIDCursor()) {
LongList queueIds = new LongList(cursor.getCount());
while (cursor.moveToNext()) {
queueIds.add(cursor.getLong(0));
}
return queueIds;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -302,17 +274,12 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getDownloadedItemsCursor();
+ try (Cursor cursor = adapter.getDownloadedItemsCursor()) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
Collections.sort(items, new FeedItemPubdateComparator());
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -328,16 +295,11 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getPlayedItemsCursor();
+ try (Cursor cursor = adapter.getPlayedItemsCursor()) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -355,16 +317,11 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getNewItemsCursor(offset, limit);
+ try (Cursor cursor = adapter.getNewItemsCursor(offset, limit)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -381,16 +338,11 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getFavoritesCursor(offset, limit);
+ try (Cursor cursor = adapter.getFavoritesCursor(offset, limit)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -400,18 +352,13 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getFavoritesCursor(0, Integer.MAX_VALUE);
+ try (Cursor cursor = adapter.getFavoritesCursor(0, Integer.MAX_VALUE)) {
LongList favoriteIDs = new LongList(cursor.getCount());
while (cursor.moveToNext()) {
favoriteIDs.add(cursor.getLong(0));
}
return favoriteIDs;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -428,16 +375,11 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getRecentlyPublishedItemsCursor(offset, limit);
+ try (Cursor cursor = adapter.getRecentlyPublishedItemsCursor(offset, limit)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
loadAdditionalFeedItemListData(items);
return items;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -492,9 +434,7 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE);
+ try (Cursor cursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE)) {
List<DownloadStatus> downloadLog = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
downloadLog.add(DownloadStatus.fromCursor(cursor));
@@ -502,9 +442,6 @@ public final class DBReader {
Collections.sort(downloadLog, new DownloadStatusComparator());
return downloadLog;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -521,9 +458,7 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feedId);
+ try (Cursor cursor = adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feedId)) {
List<DownloadStatus> downloadLog = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
downloadLog.add(DownloadStatus.fromCursor(cursor));
@@ -531,9 +466,6 @@ public final class DBReader {
Collections.sort(downloadLog, new DownloadStatusComparator());
return downloadLog;
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -560,9 +492,7 @@ public final class DBReader {
@Nullable
static Feed getFeed(final long feedId, PodDBAdapter adapter) {
Feed feed = null;
- Cursor cursor = null;
- try {
- cursor = adapter.getFeedCursor(feedId);
+ try (Cursor cursor = adapter.getFeedCursor(feedId)) {
if (cursor.moveToNext()) {
feed = extractFeedFromCursorRow(cursor);
feed.setItems(getFeedItemList(feed));
@@ -570,10 +500,6 @@ public final class DBReader {
Log.e(TAG, "getFeed could not find feed with id " + feedId);
}
return feed;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -582,9 +508,7 @@ public final class DBReader {
Log.d(TAG, "Loading feeditem with id " + itemId);
FeedItem item = null;
- Cursor cursor = null;
- try {
- cursor = adapter.getFeedItemCursor(Long.toString(itemId));
+ try (Cursor cursor = adapter.getFeedItemCursor(Long.toString(itemId))) {
if (cursor.moveToNext()) {
List<FeedItem> list = extractItemlistFromCursor(adapter, cursor);
if (!list.isEmpty()) {
@@ -593,10 +517,6 @@ public final class DBReader {
}
}
return item;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -631,9 +551,7 @@ public final class DBReader {
@Nullable
private static FeedItem getFeedItemByUrl(final String podcastUrl, final String episodeUrl, PodDBAdapter adapter) {
Log.d(TAG, "Loading feeditem with podcast url " + podcastUrl + " and episode url " + episodeUrl);
- Cursor cursor = null;
- try {
- cursor = adapter.getFeedItemCursor(podcastUrl, episodeUrl);
+ try (Cursor cursor = adapter.getFeedItemCursor(podcastUrl, episodeUrl)) {
if (!cursor.moveToNext()) {
return null;
}
@@ -642,10 +560,6 @@ public final class DBReader {
return list.get(0);
}
return null;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
}
@@ -668,10 +582,8 @@ public final class DBReader {
}
private static String getImageAuthentication(final String imageUrl, PodDBAdapter adapter) {
- String credentials = null;
- Cursor cursor = null;
- try {
- cursor = adapter.getImageAuthenticationCursor(imageUrl);
+ String credentials;
+ try (Cursor cursor = adapter.getImageAuthenticationCursor(imageUrl)) {
if (cursor.moveToFirst()) {
String username = cursor.getString(0);
String password = cursor.getString(1);
@@ -683,10 +595,6 @@ public final class DBReader {
} else {
credentials = "";
}
- } finally {
- if (cursor != null) {
- cursor.close();
- }
}
return credentials;
}
@@ -720,9 +628,7 @@ public final class DBReader {
Log.d(TAG, "loadDescriptionOfFeedItem() called with: " + "item = [" + item + "]");
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- Cursor cursor = null;
- try {
- cursor = adapter.getDescriptionOfItem(item);
+ try (Cursor cursor = adapter.getDescriptionOfItem(item)) {
if (cursor.moveToFirst()) {
int indexDescription = cursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION);
String description = cursor.getString(indexDescription);
@@ -732,9 +638,6 @@ public final class DBReader {
item.setContentEncoded(contentEncoded);
}
} finally {
- if (cursor != null) {
- cursor.close();
- }
adapter.close();
}
}
@@ -898,6 +801,16 @@ public final class DBReader {
}
final LongIntMap feedCounters = adapter.getFeedCounters(feedIds);
+ int feedFilter = UserPreferences.getFeedFilter();
+ if (feedFilter == UserPreferences.FEED_FILTER_COUNTER_ZERO) {
+ for (int i = feeds.size() - 1; i >= 0; i--) {
+ if (feedCounters.get(feeds.get(i).getId()) <= 0) {
+ feedCounters.delete(feeds.get(i).getId());
+ feeds.remove(i);
+ }
+ }
+ }
+
Comparator<Feed> comparator;
int feedOrder = UserPreferences.getFeedOrder();
if (feedOrder == UserPreferences.FEED_ORDER_COUNTER) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
index 6f9e6b056..e3121caa2 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
@@ -274,7 +274,7 @@ public class DownloadRequester implements DownloadStateProvider {
}
File dest;
- if (feedmedia.getFile_url() != null) {
+ if (feedmedia.getFile_url() != null && new File(feedmedia.getFile_url()).exists()) {
dest = new File(feedmedia.getFile_url());
} else {
dest = new File(getMediafilePath(feedmedia), getMediafilename(feedmedia));
@@ -340,7 +340,7 @@ public class DownloadRequester implements DownloadStateProvider {
/**
* Checks if feedfile is in the downloads list
*/
- public synchronized boolean isDownloadingFile(FeedFile item) {
+ public synchronized boolean isDownloadingFile(@NonNull FeedFile item) {
return item.getDownload_url() != null && downloads.containsKey(item.getDownload_url());
}
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 a2247a3db..142763d75 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
@@ -1236,7 +1236,7 @@ public class PodDBAdapter {
public Cursor searchItems(long feedID, String searchQuery) {
String preparedQuery = prepareSearchQuery(searchQuery);
- String queryFeedId = "";
+ String queryFeedId;
if (feedID != 0) {
// search items in specific feed
queryFeedId = KEY_FEED + " = " + feedID;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
index 6985e4421..4c89ebc19 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
@@ -488,8 +488,8 @@ public class SyncService extends Worker {
Intent intent = getApplicationContext().getPackageManager().getLaunchIntentForPackage(
getApplicationContext().getPackageName());
- PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
+ R.id.pending_intent_sync_error, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(getApplicationContext(),
NotificationUtils.CHANNEL_ID_ERROR)
.setContentTitle(getApplicationContext().getString(R.string.gpodnetsync_error_title))
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
index eae7a08af..62c8ce5f3 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
@@ -21,7 +21,6 @@ import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
-import org.apache.commons.io.Charsets;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -34,6 +33,7 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
@@ -505,7 +505,7 @@ public class GpodnetService implements ISyncService {
RequestBody requestBody = RequestBody.create(TEXT, "");
Request request = new Request.Builder().url(url).post(requestBody).build();
try {
- String credential = Credentials.basic(username, password, Charsets.UTF_8);
+ String credential = Credentials.basic(username, password, Charset.forName("UTF-8"));
Request authRequest = request.newBuilder().header("Authorization", credential).build();
Response response = httpClient.newCall(authRequest).execute();
checkStatusCode(response);
@@ -519,8 +519,8 @@ public class GpodnetService implements ISyncService {
private String executeRequest(@NonNull Request.Builder requestB) throws GpodnetServiceException {
Request request = requestB.build();
- String responseString = null;
- Response response = null;
+ String responseString;
+ Response response;
ResponseBody body = null;
try {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java
index 6154ccc84..798be8d96 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.sync.model;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.core.util.ObjectsCompat;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.util.DateUtils;
@@ -179,6 +180,7 @@ public class EpisodeAction {
return obj;
}
+ @NonNull
@Override
public String toString() {
return "EpisodeAction{"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java
index 77942ffa0..90af585af 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java
@@ -23,6 +23,7 @@ public class EpisodeActionChanges {
return this.timestamp;
}
+ @NonNull
@Override
public String toString() {
return "EpisodeActionGetResponse{"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/UnsupportedFeedtypeException.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/UnsupportedFeedtypeException.java
index c9f9f19c8..11588967a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/UnsupportedFeedtypeException.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/UnsupportedFeedtypeException.java
@@ -36,6 +36,9 @@ public class UnsupportedFeedtypeException extends Exception {
if (message != null) {
return message;
} else if (type == TypeGetter.Type.INVALID) {
+ if ("html".equals(rootElement)) {
+ return "The server returned a website, not a podcast feed";
+ }
return "Invalid type";
} else {
return "Type " + type + " not supported";
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 638383223..30b01f0bc 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
@@ -14,114 +14,118 @@ import de.danoeh.antennapod.core.syndication.util.SyndTypeUtils;
/** Processes tags from the http://search.yahoo.com/mrss/ namespace. */
public class NSMedia extends Namespace {
- private static final String TAG = "NSMedia";
-
- public static final String NSTAG = "media";
- public static final String NSURI = "http://search.yahoo.com/mrss/";
-
- private static final String CONTENT = "content";
- private static final String DOWNLOAD_URL = "url";
- private static final String SIZE = "fileSize";
- 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";
-
- private static final String DESCRIPTION = "description";
- private static final String DESCRIPTION_TYPE = "type";
-
- @Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
- if (CONTENT.equals(localName)) {
- String url = attributes.getValue(DOWNLOAD_URL);
- String type = attributes.getValue(MIME_TYPE);
- String defaultStr = attributes.getValue(DEFAULT);
- String medium = attributes.getValue(MEDIUM);
- boolean validTypeMedia = false;
- boolean validTypeImage = false;
-
- boolean isDefault = "true".equals(defaultStr);
-
- if (MEDIUM_AUDIO.equals(medium) || MEDIUM_VIDEO.equals(medium)) {
- validTypeMedia = true;
- } else if (MEDIUM_IMAGE.equals(medium)) {
- validTypeImage = true;
- } else {
- 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 && validTypeMedia) {
- long size = 0;
- String sizeStr = attributes.getValue(SIZE);
- try {
- size = Long.parseLong(sizeStr);
- } catch (NumberFormatException e) {
- Log.e(TAG, "Size \"" + sizeStr + "\" could not be parsed.");
- }
-
- int durationMs = 0;
- String durationStr = attributes.getValue(DURATION);
- if (!TextUtils.isEmpty(durationStr)) {
- try {
- long duration = Long.parseLong(durationStr);
- durationMs = (int) TimeUnit.MILLISECONDS.convert(duration, TimeUnit.SECONDS);
- } catch (NumberFormatException e) {
- Log.e(TAG, "Duration \"" + durationStr + "\" could not be parsed");
- }
- }
- FeedMedia media = new FeedMedia(state.getCurrentItem(), url, size, type);
- if (durationMs > 0) {
- media.setDuration(durationMs);
- }
- state.getCurrentItem().setMedia(media);
- } else if (state.getCurrentItem() != null && url != null && validTypeImage) {
- state.getCurrentItem().setImageUrl(url);
- }
- } else if (IMAGE.equals(localName)) {
- String url = attributes.getValue(IMAGE_URL);
- if (url != null) {
- if (state.getCurrentItem() != null) {
- state.getCurrentItem().setImageUrl(url);
- } else {
- if (state.getFeed().getImageUrl() == null) {
- state.getFeed().setImageUrl(url);
- }
- }
- }
- } else if (DESCRIPTION.equals(localName)) {
- String type = attributes.getValue(DESCRIPTION_TYPE);
- return new AtomText(localName, this, type);
- }
- return new SyndElement(localName, this);
- }
-
- @Override
- public void handleElementEnd(String localName, HandlerState state) {
- if (DESCRIPTION.equals(localName)) {
- String content = state.getContentBuf().toString();
- if (state.getCurrentItem() != null && content != null &&
- state.getCurrentItem().getDescription() == null) {
- state.getCurrentItem().setDescription(content);
- }
- }
- }
+ private static final String TAG = "NSMedia";
+
+ public static final String NSTAG = "media";
+ public static final String NSURI = "http://search.yahoo.com/mrss/";
+
+ private static final String CONTENT = "content";
+ private static final String DOWNLOAD_URL = "url";
+ private static final String SIZE = "fileSize";
+ 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";
+
+ private static final String DESCRIPTION = "description";
+ private static final String DESCRIPTION_TYPE = "type";
+
+ @Override
+ public SyndElement handleElementStart(String localName, HandlerState state,
+ Attributes attributes) {
+ if (CONTENT.equals(localName)) {
+ String url = attributes.getValue(DOWNLOAD_URL);
+ String type = attributes.getValue(MIME_TYPE);
+ String defaultStr = attributes.getValue(DEFAULT);
+ String medium = attributes.getValue(MEDIUM);
+ boolean validTypeMedia = false;
+ boolean validTypeImage = false;
+
+ boolean isDefault = "true".equals(defaultStr);
+
+ if (MEDIUM_AUDIO.equals(medium)) {
+ validTypeMedia = true;
+ type = "audio/*";
+ } else if (MEDIUM_VIDEO.equals(medium)) {
+ validTypeMedia = true;
+ type = "video/*";
+ } else if (MEDIUM_IMAGE.equals(medium)) {
+ validTypeImage = true;
+ type = "image/*";
+ } else {
+ 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 && validTypeMedia) {
+ long size = 0;
+ String sizeStr = attributes.getValue(SIZE);
+ try {
+ size = Long.parseLong(sizeStr);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Size \"" + sizeStr + "\" could not be parsed.");
+ }
+
+ int durationMs = 0;
+ String durationStr = attributes.getValue(DURATION);
+ if (!TextUtils.isEmpty(durationStr)) {
+ try {
+ long duration = Long.parseLong(durationStr);
+ durationMs = (int) TimeUnit.MILLISECONDS.convert(duration, TimeUnit.SECONDS);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Duration \"" + durationStr + "\" could not be parsed");
+ }
+ }
+ FeedMedia media = new FeedMedia(state.getCurrentItem(), url, size, type);
+ if (durationMs > 0) {
+ media.setDuration(durationMs);
+ }
+ state.getCurrentItem().setMedia(media);
+ } else if (state.getCurrentItem() != null && url != null && validTypeImage) {
+ state.getCurrentItem().setImageUrl(url);
+ }
+ } else if (IMAGE.equals(localName)) {
+ String url = attributes.getValue(IMAGE_URL);
+ if (url != null) {
+ if (state.getCurrentItem() != null) {
+ state.getCurrentItem().setImageUrl(url);
+ } else {
+ if (state.getFeed().getImageUrl() == null) {
+ state.getFeed().setImageUrl(url);
+ }
+ }
+ }
+ } else if (DESCRIPTION.equals(localName)) {
+ String type = attributes.getValue(DESCRIPTION_TYPE);
+ return new AtomText(localName, this, type);
+ }
+ return new SyndElement(localName, this);
+ }
+
+ @Override
+ public void handleElementEnd(String localName, HandlerState state) {
+ if (DESCRIPTION.equals(localName)) {
+ String content = state.getContentBuf().toString();
+ if (state.getCurrentItem() != null && content != null
+ && state.getCurrentItem().getDescription() == null) {
+ state.getCurrentItem().setDescription(content);
+ }
+ }
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java
index e85d5fae1..0c0561279 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java
@@ -1,7 +1,7 @@
package de.danoeh.antennapod.core.syndication.namespace.atom;
-import android.os.Build;
-import android.text.Html;
+import androidx.core.text.HtmlCompat;
+
import de.danoeh.antennapod.core.syndication.namespace.Namespace;
import de.danoeh.antennapod.core.syndication.namespace.SyndElement;
@@ -24,11 +24,7 @@ public class AtomText extends SyndElement {
if (type == null) {
return content;
} else if (type.equals(TYPE_HTML)) {
- if (Build.VERSION.SDK_INT >= 24) {
- return Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY).toString();
- } else {
- return Html.fromHtml(content).toString();
- }
+ return HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY).toString();
} else if (type.equals(TYPE_XHTML)) {
return content;
} else { // Handle as text by default
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 7aa5a90e7..7e4350fd4 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
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.syndication.namespace.atom;
import android.text.TextUtils;
import android.util.Log;
+import de.danoeh.antennapod.core.syndication.util.SyndStringUtils;
import org.xml.sax.Attributes;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -163,12 +164,13 @@ public class NSAtom extends Namespace {
if (state.getTagstack().size() >= 2) {
AtomText textElement = null;
- String content;
+ String contentRaw;
if (state.getContentBuf() != null) {
- content = state.getContentBuf().toString();
+ contentRaw = state.getContentBuf().toString();
} else {
- content = "";
+ contentRaw = "";
}
+ String content = SyndStringUtils.trimAllWhitespace(contentRaw);
SyndElement topElement = state.getTagstack().peek();
String top = topElement.getName();
SyndElement secondElement = state.getSecondTag();
@@ -181,9 +183,9 @@ public class NSAtom extends Namespace {
if (ID.equals(top)) {
if (FEED.equals(second) && state.getFeed() != null) {
- state.getFeed().setFeedIdentifier(content);
+ state.getFeed().setFeedIdentifier(contentRaw);
} else if (ENTRY.equals(second) && state.getCurrentItem() != null) {
- state.getCurrentItem().setItemIdentifier(content);
+ state.getCurrentItem().setItemIdentifier(contentRaw);
}
} else if (TITLE.equals(top) && textElement != null) {
if (FEED.equals(second) && state.getFeed() != null) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java
index 4fd54156b..859666464 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java
@@ -6,6 +6,8 @@ import android.net.Uri;
import androidx.annotation.NonNull;
import android.util.Log;
+import java.net.URLConnection;
+import de.danoeh.antennapod.core.ClientConfig;
import org.apache.commons.io.IOUtils;
import java.io.BufferedInputStream;
@@ -85,7 +87,9 @@ public class ChapterUtils {
in = new CountingInputStream(context.getContentResolver().openInputStream(uri));
} else {
URL url = new URL(p.getStreamUrl());
- in = new CountingInputStream(url.openStream());
+ URLConnection urlConnection = url.openConnection();
+ urlConnection.setRequestProperty("User-Agent", ClientConfig.USER_AGENT);
+ in = new CountingInputStream(urlConnection.getInputStream());
}
List<Chapter> chapters = readChaptersFrom(in);
if (!chapters.isEmpty()) {
@@ -159,7 +163,9 @@ public class ChapterUtils {
input = context.getContentResolver().openInputStream(uri);
} else {
URL url = new URL(media.getStreamUrl());
- input = url.openStream();
+ URLConnection urlConnection = url.openConnection();
+ urlConnection.setRequestProperty("User-Agent", ClientConfig.USER_AGENT);
+ input = urlConnection.getInputStream();
}
if (input != null) {
readOggChaptersFromInputStream(media, input);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java b/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java
index 220a783f3..2a387b7b0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java
@@ -4,6 +4,7 @@ import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
@@ -29,6 +30,7 @@ public class FileNameGenerator {
* characters of the given string.
*/
public static String generateFileName(String string) {
+ string = StringUtils.stripAccents(string);
StringBuilder buf = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/InvalidFeedException.java b/core/src/main/java/de/danoeh/antennapod/core/util/InvalidFeedException.java
index ebde1e412..a45136432 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/InvalidFeedException.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/InvalidFeedException.java
@@ -6,6 +6,7 @@ package de.danoeh.antennapod.core.util;
public class InvalidFeedException extends Exception {
private static final long serialVersionUID = 1L;
- public InvalidFeedException() {
+ public InvalidFeedException(String message) {
+ super(message);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java
index 366f86707..813c6d0f7 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java
@@ -39,7 +39,7 @@ public class RewindAfterPauseUtils {
int newPosition = currentPosition - (int) rewindTime;
- return newPosition > 0 ? newPosition : 0;
+ return Math.max(newPosition, 0);
} else {
return currentPosition;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java
index e1dffef97..ac7f4848c 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java
@@ -41,7 +41,7 @@ public final class URLChecker {
String lowerCaseUrl = url.toLowerCase(); // protocol names are case insensitive
if (lowerCaseUrl.startsWith("feed://")) {
if (BuildConfig.DEBUG) Log.d(TAG, "Replacing feed:// with http://");
- return url.replaceFirst("feed://", "http://");
+ return prepareURL(url.substring("feed://".length()));
} else if (lowerCaseUrl.startsWith("pcast://")) {
if (BuildConfig.DEBUG) Log.d(TAG, "Removing pcast://");
return prepareURL(url.substring("pcast://".length()));
@@ -50,7 +50,7 @@ public final class URLChecker {
return prepareURL(url.substring("pcast:".length()));
} else if (lowerCaseUrl.startsWith("itpc")) {
if (BuildConfig.DEBUG) Log.d(TAG, "Replacing itpc:// with http://");
- return url.replaceFirst("itpc://", "http://");
+ return prepareURL(url.substring("itpc://".length()));
} else if (lowerCaseUrl.startsWith(AP_SUBSCRIBE)) {
if (BuildConfig.DEBUG) Log.d(TAG, "Removing antennapod-subscribe://");
return prepareURL(url.substring(AP_SUBSCRIBE.length()));
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java
index 8bd23c2ed..920a1ef8a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/ChapterStartTimeComparator.java
@@ -8,13 +8,7 @@ public class ChapterStartTimeComparator implements Comparator<Chapter> {
@Override
public int compare(Chapter lhs, Chapter rhs) {
- if (lhs.getStart() == rhs.getStart()) {
- return 0;
- } else if (lhs.getStart() < rhs.getStart()) {
- return -1;
- } else {
- return 1;
- }
+ return Long.compare(lhs.getStart(), rhs.getStart());
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java b/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
index 991089910..a8ca43ccb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
@@ -118,9 +118,8 @@ public class AutoUpdateManager {
*/
public static void runImmediate(@NonNull Context context) {
Log.d(TAG, "Run auto update immediately in background.");
- new Thread(() -> {
- DBTasks.refreshAllFeeds(context.getApplicationContext(), true);
- }, "ManualRefreshAllFeeds").start();
+ new Thread(() -> DBTasks.refreshAllFeeds(
+ context.getApplicationContext(), true), "ManualRefreshAllFeeds").start();
}
public static void disableAutoUpdate(Context context) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
index 4b3ffa389..aec53da4c 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
@@ -6,6 +6,7 @@ import android.preference.PreferenceManager;
import android.util.Log;
import android.view.SurfaceHolder;
+import de.danoeh.antennapod.core.ClientConfig;
import org.antennapod.audio.MediaPlayer;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@@ -17,7 +18,7 @@ public class AudioPlayer extends MediaPlayer implements IPlayer {
private static final String TAG = "AudioPlayer";
public AudioPlayer(Context context) {
- super(context);
+ super(context, true, ClientConfig.USER_AGENT);
PreferenceManager.getDefaultSharedPreferences(context)
.registerOnSharedPreferenceChangeListener((sharedPreferences, key) -> {
if (key.equals(UserPreferences.PREF_MEDIA_PLAYER)) {
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 0b849aa1f..d47d26af9 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
@@ -508,6 +508,13 @@ public class PlaybackController {
playbackService.setStartWhenPrepared(true);
playbackService.prepare();
break;
+ default:
+ new PlaybackServiceStarter(activity, media)
+ .startWhenPrepared(true)
+ .streamIfLastWasStream()
+ .start();
+ Log.w(TAG, "Play/Pause button was pressed and PlaybackService state was unknown");
+ break;
}
}
@@ -592,6 +599,13 @@ public class PlaybackController {
}
public void setPlaybackSpeed(float speed) {
+ PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(speed);
+ if (getMedia() != null && getMedia().getMediaType() == MediaType.VIDEO) {
+ UserPreferences.setVideoPlaybackSpeed(speed);
+ } else {
+ UserPreferences.setPlaybackSpeed(speed);
+ }
+
if (playbackService != null) {
playbackService.setSpeed(speed);
} else {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java
index cdf171299..9277af6e6 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/OggInputStream.java
@@ -39,7 +39,7 @@ class OggInputStream extends InputStream {
private void readOggPage() throws IOException {
// find OggS
int[] buffer = new int[4];
- int c = 0;
+ int c;
boolean isInOggS = false;
while ((c = input.read()) != -1) {
switch (c) {