summaryrefslogtreecommitdiff
path: root/core/src/main/java/de/danoeh/antennapod
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2021-01-02 16:58:43 +0100
committerByteHamster <info@bytehamster.com>2021-01-02 16:58:43 +0100
commit3ed33794327f547c8892d30958a78770dae56d45 (patch)
tree29095e84b7e8051e6e4bd58e6d7d66578807e614 /core/src/main/java/de/danoeh/antennapod
parentc9635473cb69acfb883f70868f6a8e04670241b1 (diff)
parentd1426f97740103d548db007e3ad2c918d90f8bf0 (diff)
downloadAntennaPod-3ed33794327f547c8892d30958a78770dae56d45.zip
Merge branch 'develop' into folders
Diffstat (limited to 'core/src/main/java/de/danoeh/antennapod')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/DBTasksCallbacks.java20
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/DownloadServiceCallbacks.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/PlaybackServiceCallbacks.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java61
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java16
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java88
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/util/PlaybackSpeedUtils.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java30
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FailedDownloadHandler.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java55
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java32
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java14
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java45
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java15
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/LangUtils.java124
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java123
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java81
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java1
37 files changed, 369 insertions, 433 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/DBTasksCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/DBTasksCallbacks.java
deleted file mode 100644
index 11a6b2c9f..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/DBTasksCallbacks.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.danoeh.antennapod.core;
-
-import de.danoeh.antennapod.core.storage.AutomaticDownloadAlgorithm;
-import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
-
-/**
- * Callbacks for the DBTasks class of the storage module.
- */
-public interface DBTasksCallbacks {
-
- /**
- * Returns the client's implementation of the AutomaticDownloadAlgorithm interface.
- */
- AutomaticDownloadAlgorithm getAutomaticDownloadAlgorithm();
-
- /**
- * Returns the client's implementation of the EpisodeCacheCleanupAlgorithm interface.
- */
- EpisodeCleanupAlgorithm getEpisodeCacheCleanupAlgorithm();
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/DownloadServiceCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/DownloadServiceCallbacks.java
index ad3fb8d42..ae9b47629 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/DownloadServiceCallbacks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/DownloadServiceCallbacks.java
@@ -37,7 +37,7 @@ public interface DownloadServiceCallbacks {
* <p/>
* The PendingIntent takes users to an activity where they can look at all successful and failed downloads.
*
- * @return A non-null PendingIntent for the notification or null if shouldCreateReport()==false
+ * @return A non-null PendingIntent for the notification
*/
PendingIntent getReportNotificationContentIntent(Context context);
@@ -47,14 +47,8 @@ public interface DownloadServiceCallbacks {
* <p/>
* The PendingIntent takes users to an activity where they can look at their episode queue.
*
- * @return A non-null PendingIntent for the notification or null if shouldCreateReport()==false
+ * @return A non-null PendingIntent for the notification
*/
PendingIntent getAutoDownloadReportNotificationContentIntent(Context context);
-
- /**
- * Returns true if the DownloadService should create a report that shows the number of failed
- * downloads when the service shuts down.
- */
- boolean shouldCreateReport();
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/PlaybackServiceCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/PlaybackServiceCallbacks.java
index 194ee65ae..3dcaac4dc 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/PlaybackServiceCallbacks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/PlaybackServiceCallbacks.java
@@ -19,11 +19,4 @@ public interface PlaybackServiceCallbacks {
* @return A non-null activity intent.
*/
Intent getPlayerActivityIntent(Context context, MediaType mediaType, boolean remotePlayback);
-
- /**
- * Returns true if the PlaybackService should load new episodes from the queue when playback ends
- * and false if the PlaybackService should ignore the queue and load no more episodes when playback
- * finishes.
- */
- boolean useQueue();
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java
deleted file mode 100644
index 4504b2e7f..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package de.danoeh.antennapod.core.asynctask;
-
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.os.AsyncTask;
-
-import java.util.concurrent.ExecutionException;
-
-import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.service.playback.PlaybackService;
-import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.util.IntentUtils;
-
-/** Removes a feed in the background. */
-public class FeedRemover extends AsyncTask<Void, Void, Void> {
- private final Context context;
- private ProgressDialog dialog;
- private final Feed feed;
- public boolean skipOnCompletion = false;
-
- public FeedRemover(Context context, Feed feed) {
- super();
- this.context = context;
- this.feed = feed;
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- try {
- DBWriter.deleteFeed(context, feed.getId()).get();
- } catch (InterruptedException | ExecutionException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- if(dialog != null && dialog.isShowing()) {
- dialog.dismiss();
- }
- if(skipOnCompletion) {
- IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SKIP_CURRENT_EPISODE);
- }
- }
-
- @Override
- protected void onPreExecute() {
- dialog = new ProgressDialog(context);
- dialog.setMessage(context.getString(R.string.feed_remover_msg));
- dialog.setIndeterminate(true);
- dialog.setCancelable(false);
- dialog.show();
- }
-
- public void executeAsync() {
- executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java
index 4c11d0489..c05e2e9f1 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java
@@ -20,6 +20,7 @@ import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.math.BigInteger;
+import java.nio.charset.Charset;
import java.security.DigestInputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
@@ -34,7 +35,6 @@ import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.util.LangUtils;
public class OpmlBackupAgent extends BackupAgentHelper {
private static final String OPML_BACKUP_KEY = "opml";
@@ -73,9 +73,9 @@ public class OpmlBackupAgent extends BackupAgentHelper {
try {
digester = MessageDigest.getInstance("MD5");
writer = new OutputStreamWriter(new DigestOutputStream(byteStream, digester),
- LangUtils.UTF_8);
+ Charset.forName("UTF-8"));
} catch (NoSuchAlgorithmException e) {
- writer = new OutputStreamWriter(byteStream, LangUtils.UTF_8);
+ writer = new OutputStreamWriter(byteStream, Charset.forName("UTF-8"));
}
try {
@@ -138,9 +138,9 @@ public class OpmlBackupAgent extends BackupAgentHelper {
try {
digester = MessageDigest.getInstance("MD5");
reader = new InputStreamReader(new DigestInputStream(data, digester),
- LangUtils.UTF_8);
+ Charset.forName("UTF-8"));
} catch (NoSuchAlgorithmException e) {
- reader = new InputStreamReader(data, LangUtils.UTF_8);
+ reader = new InputStreamReader(data, Charset.forName("UTF-8"));
}
try {
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 e8e478a86..787f0e5e7 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,10 +1,8 @@
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;
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 88945b930..4857e899d 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
@@ -5,6 +5,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.media.MediaMetadataRetriever;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Nullable;
@@ -165,13 +166,20 @@ public class FeedMedia extends FeedFile implements Playable {
*/
public MediaBrowserCompat.MediaItem getMediaItem() {
Playable p = this;
- MediaDescriptionCompat description = new MediaDescriptionCompat.Builder()
+ MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder()
.setMediaId(String.valueOf(id))
.setTitle(p.getEpisodeTitle())
.setDescription(p.getFeedTitle())
- .setSubtitle(p.getFeedTitle())
- .build();
- return new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
+ .setSubtitle(p.getFeedTitle());
+ if (item != null) {
+ // getImageLocation() also loads embedded images, which we can not send to external devices
+ if (item.getImageUrl() != null) {
+ builder.setIconUri(Uri.parse(item.getImageUrl()));
+ } else if (item.getFeed() != null && item.getFeed().getImageLocation() != null) {
+ builder.setIconUri(Uri.parse(item.getFeed().getImageLocation()));
+ }
+ }
+ return new MediaBrowserCompat.MediaItem(builder.build(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
}
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
index 971808eb4..4e59fd750 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
@@ -10,6 +10,7 @@ import androidx.documentfile.provider.DocumentFile;
import org.apache.commons.lang3.StringUtils;
+import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -22,7 +23,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
-import java.util.concurrent.ExecutionException;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
@@ -35,16 +35,28 @@ import de.danoeh.antennapod.core.util.DownloadError;
public class LocalFeedUpdater {
public static void updateFeed(Feed feed, Context context) {
+ try {
+ tryUpdateFeed(feed, context);
+
+ if (mustReportDownloadSuccessful(feed)) {
+ reportSuccess(feed);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ reportError(feed, e.getMessage());
+ }
+ }
+
+ private static void tryUpdateFeed(Feed feed, Context context) throws IOException {
String uriString = feed.getDownload_url().replace(Feed.PREFIX_LOCAL_FOLDER, "");
DocumentFile documentFolder = DocumentFile.fromTreeUri(context, Uri.parse(uriString));
if (documentFolder == null) {
- reportError(feed, "Unable to retrieve document tree."
+ throw new IOException("Unable to retrieve document tree. "
+ "Try re-connecting the folder on the podcast info page.");
- return;
}
if (!documentFolder.exists() || !documentFolder.canRead()) {
- reportError(feed, "Cannot read local directory. Try re-connecting the folder on the podcast info page.");
- return;
+ throw new IOException("Cannot read local directory. "
+ + "Try re-connecting the folder on the podcast info page.");
}
if (feed.getItems() == null) {
@@ -97,25 +109,17 @@ public class LocalFeedUpdater {
// set default feed image
feed.setImageUrl(getDefaultIconUrl(context));
}
- if (feed.getPreferences().getAutoDownload()) {
- feed.getPreferences().setAutoDownload(false);
- feed.getPreferences().setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NO);
- try {
- DBWriter.setFeedPreferences(feed.getPreferences()).get();
- } catch (ExecutionException | InterruptedException e) {
- e.printStackTrace();
- }
- }
+
+ feed.getPreferences().setAutoDownload(false);
+ feed.getPreferences().setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NO);
+ feed.setDescription(context.getString(R.string.local_feed_description));
+ feed.setAuthor(context.getString(R.string.local_folder));
// update items, delete items without existing file;
// only delete items if the folder contains at least one element to avoid accidentally
// deleting played state or position in case the folder is temporarily unavailable.
boolean removeUnlistedItems = (newItems.size() >= 1);
DBTasks.updateFeed(context, feed, removeUnlistedItems);
-
- if (mustReportDownloadSuccessful(feed)) {
- reportSuccess(feed);
- }
}
/**
@@ -139,46 +143,50 @@ public class LocalFeedUpdater {
}
private static FeedItem createFeedItem(Feed feed, DocumentFile file, Context context) {
- String uuid = UUID.randomUUID().toString();
+ FeedItem item = new FeedItem(0, file.getName(), UUID.randomUUID().toString(),
+ file.getName(), new Date(file.lastModified()), FeedItem.UNPLAYED, feed);
+ item.setAutoDownload(false);
+
+ long size = file.length();
+ FeedMedia media = new FeedMedia(0, item, 0, 0, size, file.getType(),
+ file.getUri().toString(), file.getUri().toString(), false, null, 0, 0);
+ item.setMedia(media);
+
+ try {
+ loadMetadata(item, file, context);
+ } catch (Exception e) {
+ item.setDescription(e.getMessage());
+ }
+
+ return item;
+ }
+ private static void loadMetadata(FeedItem item, DocumentFile file, Context context) throws Exception {
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(context, file.getUri());
- String dateStr = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
- Date date = null;
+ String dateStr = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
if (!TextUtils.isEmpty(dateStr)) {
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.getDefault());
- date = simpleDateFormat.parse(dateStr);
+ item.setPubDate(simpleDateFormat.parse(dateStr));
} catch (ParseException parseException) {
- date = DateUtils.parse(dateStr);
- if (date == null) {
- date = new Date(file.lastModified());
+ Date date = DateUtils.parse(dateStr);
+ if (date != null) {
+ item.setPubDate(date);
}
}
- } else {
- date = new Date(file.lastModified());
}
- FeedItem item = new FeedItem(0, file.getName(), uuid, file.getName(), date,
- FeedItem.UNPLAYED, feed);
- item.setAutoDownload(false);
-
- String durationStr = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
String title = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
if (!TextUtils.isEmpty(title)) {
item.setTitle(title);
}
- //add the media to the item
- long duration = Long.parseLong(durationStr);
- long size = file.length();
- FeedMedia media = new FeedMedia(0, item, (int) duration, 0, size, file.getType(),
- file.getUri().toString(), file.getUri().toString(), false, null, 0, 0);
- media.setHasEmbeddedPicture(mediaMetadataRetriever.getEmbeddedPicture() != null);
- item.setMedia(media);
+ String durationStr = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
+ item.getMedia().setDuration((int) Long.parseLong(durationStr));
- return item;
+ item.getMedia().setHasEmbeddedPicture(mediaMetadataRetriever.getEmbeddedPicture() != null);
}
private static void reportError(Feed feed, String reasonDetailed) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/util/PlaybackSpeedUtils.java b/core/src/main/java/de/danoeh/antennapod/core/feed/util/PlaybackSpeedUtils.java
index 0d5ecbb71..d6740994d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/util/PlaybackSpeedUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/util/PlaybackSpeedUtils.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.core.feed.util;
+import android.util.Log;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
@@ -14,6 +15,7 @@ import static de.danoeh.antennapod.core.feed.FeedPreferences.SPEED_USE_GLOBAL;
* Utility class to use the appropriate playback speed based on {@link PlaybackPreferences}
*/
public final class PlaybackSpeedUtils {
+ private static final String TAG = "PlaybackSpeedUtils";
private PlaybackSpeedUtils() {
}
@@ -33,8 +35,10 @@ public final class PlaybackSpeedUtils {
FeedItem item = ((FeedMedia) media).getItem();
if (item != null) {
Feed feed = item.getFeed();
- if (feed != null) {
+ if (feed != null && feed.getPreferences() != null) {
playbackSpeed = feed.getPreferences().getFeedPlaybackSpeed();
+ } else {
+ Log.d(TAG, "Can not get feed specific playback speed: " + feed);
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java
index ab4247cef..b3adc567e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java
@@ -10,7 +10,6 @@ import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
import com.bumptech.glide.load.model.StringLoader;
-import com.bumptech.glide.load.model.UriLoader;
import com.bumptech.glide.module.AppGlideModule;
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
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 35a9d987b..519d625e2 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
@@ -10,17 +10,13 @@ import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
import com.bumptech.glide.signature.ObjectKey;
-import de.danoeh.antennapod.core.ClientConfig;
-import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.net.URL;
import java.nio.ByteBuffer;
-import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.io.IOUtils;
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 56dd95fe6..ed9c519a6 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
@@ -301,10 +301,30 @@ public class UserPreferences {
* @return {@code true} if download reports are shown, {@code false} otherwise
*/
public static boolean showDownloadReport() {
+ if (Build.VERSION.SDK_INT >= 26) {
+ return true; // System handles notification preferences
+ }
+ return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true);
+ }
+
+ /**
+ * Used for migration of the preference to system notification channels.
+ */
+ public static boolean getShowDownloadReportRaw() {
return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true);
}
public static boolean showAutoDownloadReport() {
+ if (Build.VERSION.SDK_INT >= 26) {
+ return true; // System handles notification preferences
+ }
+ return prefs.getBoolean(PREF_SHOW_AUTO_DOWNLOAD_REPORT, false);
+ }
+
+ /**
+ * Used for migration of the preference to system notification channels.
+ */
+ public static boolean getShowAutoDownloadReportRaw() {
return prefs.getBoolean(PREF_SHOW_AUTO_DOWNLOAD_REPORT, false);
}
@@ -728,6 +748,16 @@ public class UserPreferences {
}
public static boolean gpodnetNotificationsEnabled() {
+ if (Build.VERSION.SDK_INT >= 26) {
+ return true; // System handles notification preferences
+ }
+ return prefs.getBoolean(PREF_GPODNET_NOTIFICATIONS, true);
+ }
+
+ /**
+ * Used for migration of the preference to system notification channels.
+ */
+ public static boolean getGpodnetNotificationsEnabledRaw() {
return prefs.getBoolean(PREF_GPODNET_NOTIFICATIONS, true);
}
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 de106a01e..5a2c653d6 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
@@ -39,7 +39,6 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.feed.Feed;
@@ -168,6 +167,7 @@ public class DownloadService extends Service {
startForeground(R.id.notification_downloading, notification);
syncExecutor.execute(() -> onDownloadQueued(intent));
} else if (numberOfDownloads.get() == 0) {
+ stopForeground(true);
stopSelf();
} else {
Log.d(TAG, "onStartCommand: Unknown intent");
@@ -205,8 +205,7 @@ public class DownloadService extends Service {
isRunning = false;
boolean showAutoDownloadReport = UserPreferences.showAutoDownloadReport();
- if (ClientConfig.downloadServiceCallbacks.shouldCreateReport()
- && (UserPreferences.showDownloadReport() || showAutoDownloadReport)) {
+ if (UserPreferences.showDownloadReport() || showAutoDownloadReport) {
notificationManager.updateReport(reportQueue, showAutoDownloadReport);
reportQueue.clear();
}
@@ -429,7 +428,7 @@ public class DownloadService extends Service {
+ ", cleanupMedia=" + cleanupMedia);
if (cleanupMedia) {
- ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm()
+ UserPreferences.getEpisodeCleanupAlgorithm()
.makeRoomForEpisodes(getApplicationContext(), requests.size());
}
@@ -553,6 +552,7 @@ public class DownloadService extends Service {
if (numberOfDownloads.get() <= 0 && DownloadRequester.getInstance().hasNoDownloads()) {
Log.d(TAG, "Number of downloads is " + numberOfDownloads.get() + ", attempting shutdown");
+ stopForeground(true);
stopSelf();
if (notificationUpdater != null) {
notificationUpdater.run();
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 0715d50dd..fb6009c02 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
@@ -148,7 +148,7 @@ public class DownloadServiceNotification {
id = R.id.notification_auto_download_report;
content = createAutoDownloadNotificationContent(reportQueue);
} else {
- channelId = NotificationUtils.CHANNEL_ID_ERROR;
+ channelId = NotificationUtils.CHANNEL_ID_DOWNLOAD_ERROR;
titleId = R.string.download_report_title;
iconId = R.drawable.ic_notification_sync_error;
intent = ClientConfig.downloadServiceCallbacks.getReportNotificationContentIntent(context);
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 65b7ed7d1..393592cf9 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
@@ -4,7 +4,6 @@ import androidx.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
-import de.danoeh.antennapod.core.service.BasicAuthorizationInterceptor;
import okhttp3.CacheControl;
import org.apache.commons.io.IOUtils;
@@ -21,14 +20,12 @@ import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Date;
-import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.core.util.URIUtil;
-import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FailedDownloadHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FailedDownloadHandler.java
index 041d26bd4..386e5e6f7 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FailedDownloadHandler.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FailedDownloadHandler.java
@@ -3,7 +3,6 @@ package de.danoeh.antennapod.core.service.download.handler;
import android.util.Log;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBWriter;
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
index ae5d62872..325b04e9a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.core.service.playback;
import android.content.Context;
-import android.media.AudioAttributes;
import android.media.AudioManager;
import android.os.PowerManager;
import androidx.annotation.NonNull;
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 60075dda6..c1500d78b 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
@@ -7,6 +7,7 @@ import android.app.UiModeManager;
import android.bluetooth.BluetoothA2dp;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -51,7 +52,6 @@ import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.event.MessageEvent;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.event.ServiceEvent;
@@ -149,7 +149,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
public static final String ACTION_PAUSE_PLAY_CURRENT_EPISODE = "action.de.danoeh.antennapod.core.service.pausePlayCurrentEpisode";
/**
- * Custom action used by Android Wear
+ * Custom action used by Android Wear, Android Auto
*/
private static final String CUSTOM_ACTION_FAST_FORWARD = "action.de.danoeh.antennapod.core.service.fastForward";
private static final String CUSTOM_ACTION_REWIND = "action.de.danoeh.antennapod.core.service.rewind";
@@ -370,9 +370,26 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
private MediaBrowserCompat.MediaItem createBrowsableMediaItemForRoot() {
+ Uri uri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(getResources().getResourcePackageName(R.drawable.ic_playlist_black))
+ .appendPath(getResources().getResourceTypeName(R.drawable.ic_playlist_black))
+ .appendPath(getResources().getResourceEntryName(R.drawable.ic_playlist_black))
+ .build();
+
+ String subtitle = "";
+ try {
+ int count = taskManager.getQueue().size();
+ subtitle = getResources().getQuantityString(R.plurals.num_episodes, count, count);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
MediaDescriptionCompat description = new MediaDescriptionCompat.Builder()
+ .setIconUri(uri)
.setMediaId(getResources().getString(R.string.queue_label))
.setTitle(getResources().getString(R.string.queue_label))
+ .setSubtitle(subtitle)
.build();
return new MediaBrowserCompat.MediaItem(description,
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);
@@ -517,11 +534,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
playableLoaded -> {
- mediaPlayer.playMediaObject(playable, stream, startWhenPrepared,
+ mediaPlayer.playMediaObject(playableLoaded, stream, startWhenPrepared,
prepareImmediately);
- addPlayableToQueue(playable);
+ addPlayableToQueue(playableLoaded);
}, error -> {
Log.d(TAG, "Playable was not found. Stopping service.");
+ error.printStackTrace();
stateManager.stopService();
});
return Service.START_NOT_STICKY;
@@ -729,6 +747,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
addPlayableToQueue(playable);
}, error -> {
Log.d(TAG, "Playable was not loaded from preferences. Stopping service.");
+ error.printStackTrace();
stateManager.stopService();
});
}
@@ -971,10 +990,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
Log.d(TAG, "getNextInQueue(), but playable not an instance of FeedMedia, so not proceeding");
return null;
}
- if (!ClientConfig.playbackServiceCallbacks.useQueue()) {
- Log.d(TAG, "getNextInQueue(), but queue not in use by this app");
- return null;
- }
Log.d(TAG, "getNextInQueue()");
FeedMedia media = (FeedMedia) currentMedia;
try {
@@ -1022,6 +1037,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
*/
private void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
Log.d(TAG, "Playback ended");
+ PlaybackPreferences.clearCurrentlyPlayingTemporaryPlaybackSpeed();
if (stopPlaying) {
taskManager.cancelPositionSaver();
cancelPositionObserver();
@@ -1060,7 +1076,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
*/
private void onPostPlayback(final Playable playable, boolean ended, boolean skipped,
boolean playingNext) {
- PlaybackPreferences.clearCurrentlyPlayingTemporaryPlaybackSpeed();
if (playable == null) {
Log.e(TAG, "Cannot do post-playback processing: media was null");
return;
@@ -1206,6 +1221,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
sessionState.setState(state, getCurrentPosition(), getCurrentPlaybackSpeed());
long capabilities = PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_REWIND
+ | PlaybackStateCompat.ACTION_PAUSE
| PlaybackStateCompat.ACTION_FAST_FORWARD
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
| PlaybackStateCompat.ACTION_SEEK_TO;
@@ -1236,17 +1252,24 @@ public class PlaybackService extends MediaBrowserServiceCompat {
CUSTOM_ACTION_FAST_FORWARD,
getString(R.string.fast_forward_label), R.drawable.ic_notification_fast_forward)
.build());
+ } else {
+ // This would give the PIP of videos a play button
+ capabilities = capabilities | PlaybackStateCompat.ACTION_PLAY;
+ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_WATCH) {
+ flavorHelper.sessionStateAddActionForWear(sessionState,
+ CUSTOM_ACTION_REWIND,
+ getString(R.string.rewind_label),
+ android.R.drawable.ic_media_rew);
+ flavorHelper.sessionStateAddActionForWear(sessionState,
+ CUSTOM_ACTION_FAST_FORWARD,
+ getString(R.string.fast_forward_label),
+ android.R.drawable.ic_media_ff);
+ flavorHelper.mediaSessionSetExtraForWear(mediaSession);
+ }
}
sessionState.setActions(capabilities);
- flavorHelper.sessionStateAddActionForWear(sessionState,
- CUSTOM_ACTION_REWIND, getString(R.string.rewind_label), android.R.drawable.ic_media_rew);
- flavorHelper.sessionStateAddActionForWear(sessionState,
- CUSTOM_ACTION_FAST_FORWARD, getString(R.string.fast_forward_label), android.R.drawable.ic_media_ff);
-
- flavorHelper.mediaSessionSetExtraForWear(mediaSession);
-
mediaSession.setPlaybackState(sessionState.build());
}
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 632ac07ea..9d249620d 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
@@ -69,7 +69,7 @@ public class PlaybackServiceNotificationBuilder {
}
public void loadIcon() {
- int iconSize = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
+ int iconSize = (int) (128 * context.getResources().getDisplayMetrics().density);
try {
icon = Glide.with(context)
.asBitmap()
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java b/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java
index 720d6a9d9..78c105e38 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java
@@ -70,4 +70,36 @@ public class BackportCaCerts {
+ "0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB\n"
+ "NVOFBkpdn627G190\n"
+ "-----END CERTIFICATE-----";
+
+ public static final String LETSENCRYPT_ISRG = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
+ + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n"
+ + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n"
+ + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n"
+ + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n"
+ + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n"
+ + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n"
+ + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n"
+ + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n"
+ + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n"
+ + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n"
+ + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n"
+ + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n"
+ + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n"
+ + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n"
+ + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n"
+ + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n"
+ + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n"
+ + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n"
+ + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n"
+ + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n"
+ + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n"
+ + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n"
+ + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n"
+ + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n"
+ + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n"
+ + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n"
+ + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n"
+ + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
+ + "-----END CERTIFICATE-----";
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java b/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java
index b8fe950b2..81d2a0709 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java
@@ -45,6 +45,8 @@ public class BackportTrustManager {
new ByteArrayInputStream(BackportCaCerts.COMODO.getBytes(Charset.forName("UTF-8")))));
keystore.setCertificateEntry("SECTIGO_USER_TRUST_CA", cf.generateCertificate(
new ByteArrayInputStream(BackportCaCerts.SECTIGO_USER_TRUST.getBytes(Charset.forName("UTF-8")))));
+ keystore.setCertificateEntry("LETSENCRYPT_ISRG_CA", cf.generateCertificate(
+ new ByteArrayInputStream(BackportCaCerts.LETSENCRYPT_ISRG.getBytes(Charset.forName("UTF-8")))));
List<X509TrustManager> managers = new ArrayList<>();
managers.add(getSystemTrustManager(keystore));
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java
index 7ec4db5dd..061d6cf3f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java
@@ -65,7 +65,7 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
Iterator<FeedItem> it = candidates.iterator();
while (it.hasNext()) {
FeedItem item = it.next();
- if (!item.isAutoDownloadable()) {
+ if (!item.isAutoDownloadable() || item.getFeed().isLocalFeed()) {
it.remove();
}
}
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 baeca9bb9..8721dcd08 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
@@ -7,6 +7,7 @@ import androidx.collection.ArrayMap;
import android.text.TextUtils;
import android.util.Log;
+import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -773,7 +774,7 @@ public final class DBReader {
feedTotalTime += media.getDuration() / 1000;
if (media.isDownloaded()) {
- totalDownloadSize = totalDownloadSize + media.getSize();
+ totalDownloadSize += new File(media.getFile_url()).length();
episodesDownloadCount++;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
index c059e696a..ec39e7144 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
@@ -6,7 +6,6 @@ import android.database.Cursor;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
-import androidx.annotation.VisibleForTesting;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.FeedItemEvent;
@@ -290,7 +289,7 @@ public final class DBTasks {
*/
public static Future<?> autodownloadUndownloadedItems(final Context context) {
Log.d(TAG, "autodownloadUndownloadedItems");
- return autodownloadExec.submit(ClientConfig.dbTasksCallbacks.getAutomaticDownloadAlgorithm()
+ return autodownloadExec.submit(ClientConfig.automaticDownloadAlgorithm
.autoDownloadUndownloadedItems(context));
}
@@ -304,7 +303,7 @@ public final class DBTasks {
* @param context Used for accessing the DB.
*/
public static void performAutoCleanup(final Context context) {
- ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().performCleanup(context);
+ UserPreferences.getEpisodeCleanupAlgorithm().performCleanup(context);
}
/**
@@ -445,7 +444,8 @@ public final class DBTasks {
// as the most recent item
// (if the most recent date is null then we can assume there are no items
// and this is the first, hence 'new')
- if (priorMostRecentDate == null
+ // New items that do not have a pubDate set are always marked as new
+ if (item.getPubDate() == null || priorMostRecentDate == null
|| priorMostRecentDate.before(item.getPubDate())
|| priorMostRecentDate.equals(item.getPubDate())) {
Log.d(TAG, "Marking item published on " + item.getPubDate()
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index 9e6041df3..84cc4b6a8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -21,8 +21,8 @@ import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
-import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.core.event.FavoritesEvent;
@@ -74,6 +74,18 @@ public class DBWriter {
}
/**
+ * Wait until all threads are finished to avoid the "Illegal connection pointer" error of
+ * Robolectric. Call this method only for unit tests.
+ */
+ public static void tearDownTests() {
+ try {
+ dbExec.awaitTermination(1, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ // ignore error
+ }
+ }
+
+ /**
* Deletes a downloaded FeedMedia file from the storage device.
*
* @param context A context that is used for opening a database connection.
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
index 2f48cfc07..ea62065fc 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
@@ -3,10 +3,8 @@ package de.danoeh.antennapod.core.storage;
import android.content.Context;
import androidx.annotation.NonNull;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedComponent;
import de.danoeh.antennapod.core.feed.FeedItem;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
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 935b06cd6..4a4f94053 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
@@ -1,6 +1,5 @@
package de.danoeh.antennapod.core.storage;
-import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -195,11 +194,11 @@ public class PodDBAdapter {
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_FEED + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_FEED + ")";
- static final String CREATE_INDEX_FEEDITEMS_PUBDATE = "CREATE INDEX IF NOT EXISTS "
+ static final String CREATE_INDEX_FEEDITEMS_PUBDATE = "CREATE INDEX "
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_PUBDATE + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_PUBDATE + ")";
- static final String CREATE_INDEX_FEEDITEMS_READ = "CREATE INDEX IF NOT EXISTS "
+ static final String CREATE_INDEX_FEEDITEMS_READ = "CREATE INDEX "
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_READ + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_READ + ")";
@@ -316,46 +315,44 @@ public class PodDBAdapter {
+ JOIN_FEED_ITEM_AND_MEDIA;
private static Context context;
+ private static PodDBAdapter instance;
- private static volatile SQLiteDatabase db;
+ private final SQLiteDatabase db;
+ private final PodDBHelper dbHelper;
public static void init(Context context) {
PodDBAdapter.context = context.getApplicationContext();
}
- // Bill Pugh Singleton Implementation
- private static class SingletonHolder {
- private static final PodDBHelper dbHelper = new PodDBHelper(PodDBAdapter.context, DATABASE_NAME, null);
- private static final PodDBAdapter dbAdapter = new PodDBAdapter();
- }
-
public static PodDBAdapter getInstance() {
- return SingletonHolder.dbAdapter;
+ if (instance == null) {
+ instance = new PodDBAdapter();
+ }
+ return instance;
}
private PodDBAdapter() {
+ dbHelper = new PodDBHelper(PodDBAdapter.context, DATABASE_NAME, null);
+ db = openDb();
}
- public synchronized PodDBAdapter open() {
- if (db == null || !db.isOpen() || db.isReadOnly()) {
- db = openDb();
- }
- return this;
- }
-
- @SuppressLint("NewApi")
private SQLiteDatabase openDb() {
SQLiteDatabase newDb;
try {
- newDb = SingletonHolder.dbHelper.getWritableDatabase();
+ newDb = dbHelper.getWritableDatabase();
newDb.disableWriteAheadLogging();
} catch (SQLException ex) {
Log.e(TAG, Log.getStackTraceString(ex));
- newDb = SingletonHolder.dbHelper.getReadableDatabase();
+ newDb = dbHelper.getReadableDatabase();
}
return newDb;
}
+ public synchronized PodDBAdapter open() {
+ // do nothing
+ return this;
+ }
+
public synchronized void close() {
// do nothing
}
@@ -371,8 +368,8 @@ public class PodDBAdapter {
* <a href="https://github.com/robolectric/robolectric/issues/1890">robolectric/robolectric#1890</a>.</p>
*/
public static void tearDownTests() {
- db = null;
- SingletonHolder.dbHelper.close();
+ getInstance().dbHelper.close();
+ instance = null;
}
public static boolean deleteDatabase() {
@@ -380,7 +377,7 @@ public class PodDBAdapter {
adapter.open();
try {
for (String tableName : ALL_TABLES) {
- db.delete(tableName, "1", null);
+ adapter.db.delete(tableName, "1", null);
}
return true;
} finally {
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 1f5d9b75f..7563ab715 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
@@ -80,7 +80,7 @@ public class SyncService extends Worker {
if (!GpodnetPreferences.loggedIn()) {
return Result.success();
}
- syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetService.DEFAULT_BASE_HOST);
+ syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHostname());
SharedPreferences.Editor prefs = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit();
prefs.putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, System.currentTimeMillis()).apply();
@@ -485,7 +485,11 @@ public class SyncService extends Worker {
}
private void updateErrorNotification(SyncServiceException exception) {
- Log.d(TAG, "Posting error notification");
+ if (!UserPreferences.gpodnetNotificationsEnabled()) {
+ Log.d(TAG, "Skipping sync error notification because of user setting");
+ return;
+ }
+ Log.d(TAG, "Posting sync error notification");
final String description = getApplicationContext().getString(R.string.gpodnetsync_error_descr)
+ exception.getMessage();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
index e15ab2fdc..833ff33f1 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
@@ -22,14 +22,7 @@ public class DateUtils {
private DateUtils(){}
private static final String TAG = "DateUtils";
-
private static final TimeZone defaultTimezone = TimeZone.getTimeZone("GMT");
- private static final SimpleDateFormat dateFormatParser = new SimpleDateFormat("", Locale.US);
-
- static {
- dateFormatParser.setLenient(false);
- dateFormatParser.setTimeZone(defaultTimezone);
- }
public static Date parse(final String input) {
if (input == null) {
@@ -99,12 +92,16 @@ public class DateUtils {
"EEE d MMM yyyy HH:mm:ss 'GMT'Z (z)"
};
+ SimpleDateFormat parser = new SimpleDateFormat("", Locale.US);
+ parser.setLenient(false);
+ parser.setTimeZone(defaultTimezone);
+
ParsePosition pos = new ParsePosition(0);
for (String pattern : patterns) {
- dateFormatParser.applyPattern(pattern);
+ parser.applyPattern(pattern);
pos.setIndex(0);
try {
- Date result = dateFormatParser.parse(date, pos);
+ Date result = parser.parse(date, pos);
if (result != null && pos.getIndex() == date.length()) {
return result;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/LangUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/LangUtils.java
deleted file mode 100644
index 20af6415e..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/util/LangUtils.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package de.danoeh.antennapod.core.util;
-
-import androidx.collection.ArrayMap;
-
-import java.nio.charset.Charset;
-
-public class LangUtils {
-
- private LangUtils(){}
-
- public static final Charset UTF_8 = Charset.forName("UTF-8");
-
- private static final ArrayMap<String, String> languages;
- static {
- languages = new ArrayMap<>();
- languages.put("af", "Afrikaans");
- languages.put("sq", "Albanian");
- languages.put("sq", "Albanian");
- languages.put("eu", "Basque");
- languages.put("be", "Belarusian");
- languages.put("bg", "Bulgarian");
- languages.put("ca", "Catalan");
- languages.put("Chinese (Simplified)", "zh-cn");
- languages.put("Chinese (Traditional)", "zh-tw");
- languages.put("hr", "Croatian");
- languages.put("cs", "Czech");
- languages.put("da", "Danish");
- languages.put("nl", "Dutch");
- languages.put("nl-be", "Dutch (Belgium)");
- languages.put("nl-nl", "Dutch (Netherlands)");
- languages.put("en", "English");
- languages.put("en-au", "English (Australia)");
- languages.put("en-bz", "English (Belize)");
- languages.put("en-ca", "English (Canada)");
- languages.put("en-ie", "English (Ireland)");
- languages.put("en-jm", "English (Jamaica)");
- languages.put("en-nz", "English (New Zealand)");
- languages.put("en-ph", "English (Phillipines)");
- languages.put("en-za", "English (South Africa)");
- languages.put("en-tt", "English (Trinidad)");
- languages.put("en-gb", "English (United Kingdom)");
- languages.put("en-us", "English (United States)");
- languages.put("en-zw", "English (Zimbabwe)");
- languages.put("et", "Estonian");
- languages.put("fo", "Faeroese");
- languages.put("fi", "Finnish");
- languages.put("fr", "French");
- languages.put("fr-be", "French (Belgium)");
- languages.put("fr-ca", "French (Canada)");
- languages.put("fr-fr", "French (France)");
- languages.put("fr-lu", "French (Luxembourg)");
- languages.put("fr-mc", "French (Monaco)");
- languages.put("fr-ch", "French (Switzerland)");
- languages.put("gl", "Galician");
- languages.put("gd", "Gaelic");
- languages.put("de", "German");
- languages.put("de-at", "German (Austria)");
- languages.put("de-de", "German (Germany)");
- languages.put("de-li", "German (Liechtenstein)");
- languages.put("de-lu", "German (Luxembourg)");
- languages.put("de-ch", "German (Switzerland)");
- languages.put("el", "Greek");
- languages.put("haw", "Hawaiian");
- languages.put("hu", "Hungarian");
- languages.put("is", "Icelandic");
- languages.put("in", "Indonesian");
- languages.put("ga", "Irish");
- languages.put("it", "Italian");
- languages.put("it-it", "Italian (Italy)");
- languages.put("it-ch", "Italian (Switzerland)");
- languages.put("ja", "Japanese");
- languages.put("ko", "Korean");
- languages.put("mk", "Macedonian");
- languages.put("no", "Norwegian");
- languages.put("pl", "Polish");
- languages.put("pt", "Portugese");
- languages.put("pt-br", "Portugese (Brazil)");
- languages.put("pt-pt", "Portugese (Portugal");
- languages.put("ro", "Romanian");
- languages.put("ro-mo", "Romanian (Moldova)");
- languages.put("ro-ro", "Romanian (Romania");
- languages.put("ru", "Russian");
- languages.put("ru-mo", "Russian (Moldova)");
- languages.put("ru-ru", "Russian (Russia)");
- languages.put("sr", "Serbian");
- languages.put("sk", "Slovak");
- languages.put("sl", "Slovenian");
- languages.put("es", "Spanish");
- languages.put("es-ar", "Spanish (Argentinia)");
- languages.put("es=bo", "Spanish (Bolivia)");
- languages.put("es-cl", "Spanish (Chile)");
- languages.put("es-co", "Spanish (Colombia)");
- languages.put("es-cr", "Spanish (Costa Rica)");
- languages.put("es-do", "Spanish (Dominican Republic)");
- languages.put("es-ec", "Spanish (Ecuador)");
- languages.put("es-sv", "Spanish (El Salvador)");
- languages.put("es-gt", "Spanish (Guatemala)");
- languages.put("es-hn", "Spanish (Honduras)");
- languages.put("es-mx", "Spanish (Mexico)");
- languages.put("es-ni", "Spanish (Nicaragua)");
- languages.put("es-pa", "Spanish (Panama)");
- languages.put("es-py", "Spanish (Paraguay)");
- languages.put("es-pe", "Spanish (Peru)");
- languages.put("es-pr", "Spanish (Puerto Rico)");
- languages.put("es-es", "Spanish (Spain)");
- languages.put("es-uy", "Spanish (Uruguay)");
- languages.put("es-ve", "Spanish (Venezuela)");
- languages.put("sv", "Swedish");
- languages.put("sv-fi", "Swedish (Finland)");
- languages.put("sv-se", "Swedish (Sweden)");
- languages.put("tr", "Turkish");
- languages.put("uk", "Ukranian");
- }
-
- /** Finds language string for key or returns the language key if it can't be found. */
- public static String getLanguageString(String key) {
- String language = languages.get(key);
- if (language != null) {
- return language;
- } else {
- return key;
- }
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java
index 3e9e8327e..2622d81aa 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java
@@ -19,74 +19,77 @@ import de.danoeh.antennapod.core.feed.FeedMedia;
/** Utility methods for sharing data */
public class ShareUtils {
- private static final String TAG = "ShareUtils";
-
- private ShareUtils() {}
-
- public static void shareLink(Context context, String text) {
- Intent i = new Intent(Intent.ACTION_SEND);
- i.setType("text/plain");
- i.putExtra(Intent.EXTRA_TEXT, text);
- context.startActivity(Intent.createChooser(i, context.getString(R.string.share_url_label)));
- }
+ private static final String TAG = "ShareUtils";
- public static void shareFeedlink(Context context, Feed feed) {
- shareLink(context, feed.getTitle() + ": " + feed.getLink());
- }
-
- public static void shareFeedDownloadLink(Context context, Feed feed) {
- shareLink(context, feed.getTitle() + ": " + feed.getDownload_url());
- }
+ private ShareUtils() {
+ }
- public static void shareFeedItemLink(Context context, FeedItem item) {
- shareFeedItemLink(context, item, false);
- }
+ public static void shareLink(Context context, String text) {
+ Intent i = new Intent(Intent.ACTION_SEND);
+ i.setType("text/plain");
+ i.putExtra(Intent.EXTRA_TEXT, text);
+ context.startActivity(Intent.createChooser(i, context.getString(R.string.share_url_label)));
+ }
- public static void shareFeedItemDownloadLink(Context context, FeedItem item) {
- shareFeedItemDownloadLink(context, item, false);
- }
+ public static void shareFeedlink(Context context, Feed feed) {
+ shareLink(context, feed.getTitle() + ": " + feed.getLink());
+ }
- private static String getItemShareText(FeedItem item) {
- return item.getFeed().getTitle() + ": " + item.getTitle();
- }
+ public static void shareFeedDownloadLink(Context context, Feed feed) {
+ shareLink(context, feed.getTitle() + ": " + feed.getDownload_url());
+ }
+
+ public static void shareFeedItemLink(Context context, FeedItem item) {
+ shareFeedItemLink(context, item, false);
+ }
+
+ public static void shareFeedItemDownloadLink(Context context, FeedItem item) {
+ shareFeedItemDownloadLink(context, item, false);
+ }
+
+ private static String getItemShareText(FeedItem item) {
+ return item.getFeed().getTitle() + ": " + item.getTitle();
+ }
public static boolean hasLinkToShare(FeedItem item) {
- return FeedItemUtil.getLinkWithFallback(item) != null;
+ return FeedItemUtil.getLinkWithFallback(item) != null;
}
- public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) {
- String text = getItemShareText(item) + " " + FeedItemUtil.getLinkWithFallback(item);
- if(withPosition) {
- int pos = item.getMedia().getPosition();
- text += " [" + Converter.getDurationStringLong(pos) + "]";
- }
- shareLink(context, text);
- }
+ public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) {
+ String text = getItemShareText(item) + " " + FeedItemUtil.getLinkWithFallback(item);
+ if (withPosition) {
+ int pos = item.getMedia().getPosition();
+ text += " [" + Converter.getDurationStringLong(pos) + "]";
+ }
+ shareLink(context, text);
+ }
- public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) {
- String text = getItemShareText(item) + " " + item.getMedia().getDownload_url();
- if(withPosition) {
- int pos = item.getMedia().getPosition();
- text += " [" + Converter.getDurationStringLong(pos) + "]";
- }
- shareLink(context, text);
- }
+ public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) {
+ String text = getItemShareText(item) + " " + item.getMedia().getDownload_url();
+ if (withPosition) {
+ int pos = item.getMedia().getPosition();
+ text += "#t=" + pos / 1000;
+ text += " [" + Converter.getDurationStringLong(pos) + "]";
+ }
+ shareLink(context, text);
+ }
- public static void shareFeedItemFile(Context context, FeedMedia media) {
- Intent i = new Intent(Intent.ACTION_SEND);
- i.setType(media.getMime_type());
- Uri fileUri = FileProvider.getUriForFile(context, context.getString(R.string.provider_authority),
- new File(media.getLocalMediaUrl()));
- i.putExtra(Intent.EXTRA_STREAM, fileUri);
- i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
- List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);
- for (ResolveInfo resolveInfo : resInfoList) {
- String packageName = resolveInfo.activityInfo.packageName;
- context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- }
- context.startActivity(Intent.createChooser(i, context.getString(R.string.share_file_label)));
- Log.e(TAG, "shareFeedItemFile called");
- }
+ public static void shareFeedItemFile(Context context, FeedMedia media) {
+ Intent i = new Intent(Intent.ACTION_SEND);
+ i.setType(media.getMime_type());
+ Uri fileUri = FileProvider.getUriForFile(context, context.getString(R.string.provider_authority),
+ new File(media.getLocalMediaUrl()));
+ i.putExtra(Intent.EXTRA_STREAM, fileUri);
+ i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
+ List<ResolveInfo> resInfoList = context.getPackageManager()
+ .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);
+ for (ResolveInfo resolveInfo : resInfoList) {
+ String packageName = resolveInfo.activityInfo.packageName;
+ context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
+ }
+ context.startActivity(Intent.createChooser(i, context.getString(R.string.share_file_label)));
+ Log.e(TAG, "shareFeedItemFile called");
+ }
}
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 ac7f4848c..cb7db1709 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
@@ -9,7 +9,6 @@ import de.danoeh.antennapod.core.BuildConfig;
import okhttp3.HttpUrl;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java
index ad81a1d17..766986bed 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java
@@ -14,8 +14,12 @@ public class FeedItemPubdateComparator implements Comparator<FeedItem> {
*/
@Override
public int compare(FeedItem lhs, FeedItem rhs) {
- if (rhs.getPubDate() == null || lhs.getPubDate() == null) {
+ if (rhs.getPubDate() == null && lhs.getPubDate() == null) {
return 0;
+ } else if (rhs.getPubDate() == null) {
+ return 1;
+ } else if (lhs.getPubDate() == null) {
+ return -1;
}
return rhs.getPubDate().compareTo(lhs.getPubDate());
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java
index ddbe68938..3101eac34 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java
@@ -2,28 +2,36 @@ package de.danoeh.antennapod.core.util.gui;
import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import androidx.annotation.RequiresApi;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
public class NotificationUtils {
public static final String CHANNEL_ID_USER_ACTION = "user_action";
public static final String CHANNEL_ID_DOWNLOADING = "downloading";
public static final String CHANNEL_ID_PLAYING = "playing";
- public static final String CHANNEL_ID_ERROR = "error";
+ public static final String CHANNEL_ID_DOWNLOAD_ERROR = "error";
public static final String CHANNEL_ID_SYNC_ERROR = "sync_error";
public static final String CHANNEL_ID_AUTO_DOWNLOAD = "auto_download";
+ public static final String GROUP_ID_ERRORS = "group_errors";
+ public static final String GROUP_ID_NEWS = "group_news";
+
public static void createChannels(Context context) {
- if (android.os.Build.VERSION.SDK_INT < 26) {
+ if (Build.VERSION.SDK_INT < 26) {
return;
}
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (mNotificationManager != null) {
+ mNotificationManager.createNotificationChannelGroup(createGroupErrors(context));
+ mNotificationManager.createNotificationChannelGroup(createGroupNews(context));
+
mNotificationManager.createNotificationChannel(createChannelUserAction(context));
mNotificationManager.createNotificationChannel(createChannelDownloading(context));
mNotificationManager.createNotificationChannel(createChannelPlaying(context));
@@ -35,36 +43,43 @@ public class NotificationUtils {
@RequiresApi(api = Build.VERSION_CODES.O)
private static NotificationChannel createChannelUserAction(Context c) {
- NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID_USER_ACTION,
+ NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID_USER_ACTION,
c.getString(R.string.notification_channel_user_action), NotificationManager.IMPORTANCE_HIGH);
- mChannel.setDescription(c.getString(R.string.notification_channel_user_action_description));
- return mChannel;
+ notificationChannel.setDescription(c.getString(R.string.notification_channel_user_action_description));
+ notificationChannel.setGroup(GROUP_ID_ERRORS);
+ return notificationChannel;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private static NotificationChannel createChannelDownloading(Context c) {
- NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID_DOWNLOADING,
+ NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID_DOWNLOADING,
c.getString(R.string.notification_channel_downloading), NotificationManager.IMPORTANCE_LOW);
- mChannel.setDescription(c.getString(R.string.notification_channel_downloading_description));
- mChannel.setShowBadge(false);
- return mChannel;
+ notificationChannel.setDescription(c.getString(R.string.notification_channel_downloading_description));
+ notificationChannel.setShowBadge(false);
+ return notificationChannel;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private static NotificationChannel createChannelPlaying(Context c) {
- NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID_PLAYING,
+ NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID_PLAYING,
c.getString(R.string.notification_channel_playing), NotificationManager.IMPORTANCE_LOW);
- mChannel.setDescription(c.getString(R.string.notification_channel_playing_description));
- mChannel.setShowBadge(false);
- return mChannel;
+ notificationChannel.setDescription(c.getString(R.string.notification_channel_playing_description));
+ notificationChannel.setShowBadge(false);
+ return notificationChannel;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private static NotificationChannel createChannelError(Context c) {
- NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID_ERROR,
- c.getString(R.string.notification_channel_error), NotificationManager.IMPORTANCE_HIGH);
- mChannel.setDescription(c.getString(R.string.notification_channel_error_description));
- return mChannel;
+ NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID_DOWNLOAD_ERROR,
+ c.getString(R.string.notification_channel_download_error), NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.setDescription(c.getString(R.string.notification_channel_download_error_description));
+ notificationChannel.setGroup(GROUP_ID_ERRORS);
+
+ if (!UserPreferences.getShowDownloadReportRaw()) {
+ // Migration from app managed setting: disable notification
+ notificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
+ }
+ return notificationChannel;
}
@RequiresApi(api = Build.VERSION_CODES.O)
@@ -72,14 +87,38 @@ public class NotificationUtils {
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID_SYNC_ERROR,
c.getString(R.string.notification_channel_sync_error), NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription(c.getString(R.string.notification_channel_sync_error_description));
+ notificationChannel.setGroup(GROUP_ID_ERRORS);
+
+ if (!UserPreferences.getGpodnetNotificationsEnabledRaw()) {
+ // Migration from app managed setting: disable notification
+ notificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
+ }
return notificationChannel;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private static NotificationChannel createChannelAutoDownload(Context c) {
- NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID_AUTO_DOWNLOAD,
- c.getString(R.string.notification_channel_auto_download), NotificationManager.IMPORTANCE_DEFAULT);
- mChannel.setDescription(c.getString(R.string.notification_channel_episode_auto_download));
- return mChannel;
+ NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID_AUTO_DOWNLOAD,
+ c.getString(R.string.notification_channel_auto_download), NotificationManager.IMPORTANCE_NONE);
+ notificationChannel.setDescription(c.getString(R.string.notification_channel_episode_auto_download));
+ notificationChannel.setGroup(GROUP_ID_NEWS);
+
+ if (UserPreferences.getShowAutoDownloadReportRaw()) {
+ // Migration from app managed setting: enable notification
+ notificationChannel.setImportance(NotificationManager.IMPORTANCE_DEFAULT);
+ }
+ return notificationChannel;
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ private static NotificationChannelGroup createGroupErrors(Context c) {
+ return new NotificationChannelGroup(GROUP_ID_ERRORS,
+ c.getString(R.string.notification_group_errors));
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ private static NotificationChannelGroup createGroupNews(Context c) {
+ return new NotificationChannelGroup(GROUP_ID_NEWS,
+ c.getString(R.string.notification_group_news));
}
}
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 fecb14d25..0467c0a78 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
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.core.util.playback;
import android.content.Context;
-import android.content.SharedPreferences;
import androidx.preference.PreferenceManager;
import android.util.Log;
import android.view.SurfaceHolder;
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 425a07f4a..e1b4c967c 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
@@ -564,6 +564,13 @@ public class PlaybackController {
}
}
+ public void extendSleepTimer(long extendTime) {
+ long timeLeft = getSleepTimerTimeLeft();
+ if (playbackService != null && timeLeft != INVALID_TIME) {
+ setSleepTimer(timeLeft + extendTime);
+ }
+ }
+
public void setSleepTimer(long time) {
if (playbackService != null) {
playbackService.setSleepTimer(time);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java
index b12967264..107399e60 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java
@@ -2,7 +2,6 @@ package de.danoeh.antennapod.core.util.playback;
import android.content.Context;
import android.content.Intent;
-import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;