summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java59
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java11
-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/NewEpisodesNotification.java131
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java35
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java11
-rw-r--r--core/src/main/res/drawable-hdpi/ic_notification_new.pngbin0 -> 1054 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_notification_new.pngbin0 -> 688 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_notification_new.pngbin0 -> 1402 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_notification_new.pngbin0 -> 2207 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_notification_new.pngbin0 -> 3012 bytes
-rw-r--r--core/src/main/res/drawable/ic_notification_auto_download_complete.xml9
-rw-r--r--core/src/main/res/values/strings.xml13
16 files changed, 241 insertions, 54 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
index 5ffee0d62..21474db89 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
@@ -16,37 +16,40 @@ public class FeedPreferences {
public static final float SPEED_USE_GLOBAL = -1;
- @NonNull
- private FeedFilter filter;
- private long feedID;
- private boolean autoDownload;
- private boolean keepUpdated;
-
public enum AutoDeleteAction {
GLOBAL,
YES,
NO
}
- private AutoDeleteAction auto_delete_action;
+ @NonNull
+ private FeedFilter filter;
+ private long feedID;
+ private boolean autoDownload;
+ private boolean keepUpdated;
+ private AutoDeleteAction autoDeleteAction;
private VolumeAdaptionSetting volumeAdaptionSetting;
-
private String username;
private String password;
private float feedPlaybackSpeed;
private int feedSkipIntro;
private int feedSkipEnding;
+ private boolean showEpisodeNotification;
- public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password) {
- this(feedID, autoDownload, true, auto_delete_action, volumeAdaptionSetting,
- username, password, new FeedFilter(), SPEED_USE_GLOBAL, 0, 0);
+ public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction autoDeleteAction,
+ VolumeAdaptionSetting volumeAdaptionSetting, String username, String password) {
+ this(feedID, autoDownload, true, autoDeleteAction, volumeAdaptionSetting,
+ username, password, new FeedFilter(), SPEED_USE_GLOBAL, 0, 0, false);
}
- private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed, int feedSkipIntro, int feedSkipEnding) {
+ private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated,
+ AutoDeleteAction autoDeleteAction, VolumeAdaptionSetting volumeAdaptionSetting,
+ String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed,
+ int feedSkipIntro, int feedSkipEnding, boolean showEpisodeNotification) {
this.feedID = feedID;
this.autoDownload = autoDownload;
this.keepUpdated = keepUpdated;
- this.auto_delete_action = auto_delete_action;
+ this.autoDeleteAction = autoDeleteAction;
this.volumeAdaptionSetting = volumeAdaptionSetting;
this.username = username;
this.password = password;
@@ -54,6 +57,7 @@ public class FeedPreferences {
this.feedPlaybackSpeed = feedPlaybackSpeed;
this.feedSkipIntro = feedSkipIntro;
this.feedSkipEnding = feedSkipEnding;
+ this.showEpisodeNotification = showEpisodeNotification;
}
public static FeedPreferences fromCursor(Cursor cursor) {
@@ -69,6 +73,7 @@ public class FeedPreferences {
int indexFeedPlaybackSpeed = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_PLAYBACK_SPEED);
int indexAutoSkipIntro = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_INTRO);
int indexAutoSkipEnding = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_ENDING);
+ int indexEpisodeNotification = cursor.getColumnIndex(PodDBAdapter.KEY_EPISODE_NOTIFICATION);
long feedId = cursor.getLong(indexId);
boolean autoDownload = cursor.getInt(indexAutoDownload) > 0;
@@ -84,6 +89,7 @@ public class FeedPreferences {
float feedPlaybackSpeed = cursor.getFloat(indexFeedPlaybackSpeed);
int feedAutoSkipIntro = cursor.getInt(indexAutoSkipIntro);
int feedAutoSkipEnding = cursor.getInt(indexAutoSkipEnding);
+ boolean showNotification = cursor.getInt(indexEpisodeNotification) > 0;
return new FeedPreferences(feedId,
autoDownload,
autoRefresh,
@@ -94,7 +100,8 @@ public class FeedPreferences {
new FeedFilter(includeFilter, excludeFilter),
feedPlaybackSpeed,
feedAutoSkipIntro,
- feedAutoSkipEnding
+ feedAutoSkipEnding,
+ showNotification
);
}
@@ -168,15 +175,15 @@ public class FeedPreferences {
}
public AutoDeleteAction getAutoDeleteAction() {
- return auto_delete_action;
+ return autoDeleteAction;
}
public VolumeAdaptionSetting getVolumeAdaptionSetting() {
return volumeAdaptionSetting;
}
- public void setAutoDeleteAction(AutoDeleteAction auto_delete_action) {
- this.auto_delete_action = auto_delete_action;
+ public void setAutoDeleteAction(AutoDeleteAction autoDeleteAction) {
+ this.autoDeleteAction = autoDeleteAction;
}
public void setVolumeAdaptionSetting(VolumeAdaptionSetting volumeAdaptionSetting) {
@@ -184,17 +191,15 @@ public class FeedPreferences {
}
public boolean getCurrentAutoDelete() {
- switch (auto_delete_action) {
+ switch (autoDeleteAction) {
case GLOBAL:
return UserPreferences.isAutoDelete();
-
case YES:
return true;
-
case NO:
+ default: // fall-through
return false;
}
- return false; // TODO - add exceptions here
}
public void save(Context context) {
@@ -240,4 +245,16 @@ public class FeedPreferences {
public int getFeedSkipEnding() {
return feedSkipEnding;
}
+
+ /**
+ * getter for preference if notifications should be display for new episodes.
+ * @return true for displaying notifications
+ */
+ public boolean getShowEpisodeNotification() {
+ return showEpisodeNotification;
+ }
+
+ public void setShowEpisodeNotification(boolean showEpisodeNotification) {
+ this.showEpisodeNotification = showEpisodeNotification;
+ }
}
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 6dbc4a82f..025088273 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
@@ -95,6 +95,7 @@ public class DownloadService extends Service {
private final CompletionService<Downloader> downloadExecutor;
private final DownloadRequester requester;
private DownloadServiceNotification notificationManager;
+ private final NewEpisodesNotification newEpisodesNotification;
/**
* Currently running downloads.
@@ -117,7 +118,7 @@ public class DownloadService extends Service {
private ScheduledFuture<?> notificationUpdaterFuture;
private ScheduledFuture<?> downloadPostFuture;
private static final int SCHED_EX_POOL_SIZE = 1;
- private ScheduledThreadPoolExecutor schedExecutor;
+ private final ScheduledThreadPoolExecutor schedExecutor;
private static DownloaderFactory downloaderFactory = new DefaultDownloaderFactory();
private final IBinder mBinder = new LocalBinder();
@@ -133,12 +134,16 @@ public class DownloadService extends Service {
downloads = Collections.synchronizedList(new ArrayList<>());
numberOfDownloads = new AtomicInteger(0);
requester = DownloadRequester.getInstance();
+ newEpisodesNotification = new NewEpisodesNotification();
syncExecutor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "SyncThread");
t.setPriority(Thread.MIN_PRIORITY);
return t;
});
+ // Must be the first runnable in syncExecutor
+ syncExecutor.execute(newEpisodesNotification::loadCountersBeforeRefresh);
+
Log.d(TAG, "parallel downloads: " + UserPreferences.getParallelDownloads());
downloadExecutor = new ExecutorCompletionService<>(
Executors.newFixedThreadPool(UserPreferences.getParallelDownloads(),
@@ -289,6 +294,10 @@ public class DownloadService extends Service {
if (log.size() > 0 && !log.get(0).isSuccessful()) {
saveDownloadStatus(task.getDownloadStatus());
}
+ if (request.getFeedfileId() != 0 && !request.isInitiatedByUser()) {
+ // Was stored in the database before and not initiated manually
+ newEpisodesNotification.showIfNeeded(DownloadService.this, task.getSavedFeed());
+ }
} else {
DBWriter.setFeedLastUpdateFailed(request.getFeedfileId(), true);
saveDownloadStatus(task.getDownloadStatus());
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 fb6009c02..4fae9f34a 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
@@ -143,7 +143,7 @@ public class DownloadServiceNotification {
// We are generating an auto-download report
channelId = NotificationUtils.CHANNEL_ID_AUTO_DOWNLOAD;
titleId = R.string.auto_download_report_title;
- iconId = R.drawable.ic_notification_auto_download_complete;
+ iconId = R.drawable.ic_notification_new;
intent = ClientConfig.downloadServiceCallbacks.getAutoDownloadReportNotificationContentIntent(context);
id = R.id.notification_auto_download_report;
content = createAutoDownloadNotificationContent(reportQueue);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java
new file mode 100644
index 000000000..749f7b136
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java
@@ -0,0 +1,131 @@
+package de.danoeh.antennapod.core.service.download;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedPreferences;
+import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.storage.PodDBAdapter;
+import de.danoeh.antennapod.core.util.LongIntMap;
+import de.danoeh.antennapod.core.util.gui.NotificationUtils;
+
+public class NewEpisodesNotification {
+ private static final String TAG = "NewEpisodesNotification";
+ private static final String GROUP_KEY = "de.danoeh.antennapod.EPISODES";
+
+ private LongIntMap countersBefore;
+
+ public NewEpisodesNotification() {
+ }
+
+ public void loadCountersBeforeRefresh() {
+ PodDBAdapter adapter = PodDBAdapter.getInstance();
+ adapter.open();
+ countersBefore = adapter.getFeedCounters(UserPreferences.FEED_COUNTER_SHOW_NEW);
+ adapter.close();
+ }
+
+ public void showIfNeeded(Context context, Feed feed) {
+ FeedPreferences prefs = feed.getPreferences();
+ if (!prefs.getKeepUpdated() || !prefs.getShowEpisodeNotification()) {
+ return;
+ }
+
+ int newEpisodesBefore = countersBefore.get(feed.getId());
+ int newEpisodesAfter = getNewEpisodeCount(feed.getId());
+
+ Log.d(TAG, "New episodes before: " + newEpisodesBefore + ", after: " + newEpisodesAfter);
+ if (newEpisodesAfter > newEpisodesBefore) {
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
+ showNotification(newEpisodesAfter, feed, context, notificationManager);
+ }
+ }
+
+ private static void showNotification(int newEpisodes, Feed feed, Context context,
+ NotificationManagerCompat notificationManager) {
+ Resources res = context.getResources();
+ String text = res.getQuantityString(
+ R.plurals.new_episode_notification_message, newEpisodes, newEpisodes, feed.getTitle()
+ );
+ String title = res.getQuantityString(R.plurals.new_episode_notification_title, newEpisodes);
+
+ Intent intent = new Intent();
+ intent.setAction("NewEpisodes" + feed.getId());
+ intent.setComponent(new ComponentName(context, "de.danoeh.antennapod.activity.MainActivity"));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ intent.putExtra("fragment_feed_id", feed.getId());
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
+
+ Notification notification = new NotificationCompat.Builder(
+ context, NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS)
+ .setSmallIcon(R.drawable.ic_notification_new)
+ .setContentTitle(title)
+ .setLargeIcon(loadIcon(context, feed))
+ .setContentText(text)
+ .setContentIntent(pendingIntent)
+ .setGroup(GROUP_KEY)
+ .setAutoCancel(true)
+ .build();
+
+ notificationManager.notify(NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS, feed.hashCode(), notification);
+ showGroupSummaryNotification(context, notificationManager);
+ }
+
+ private static void showGroupSummaryNotification(Context context, NotificationManagerCompat notificationManager) {
+ Intent intent = new Intent();
+ intent.setAction("NewEpisodes");
+ intent.setComponent(new ComponentName(context, "de.danoeh.antennapod.activity.MainActivity"));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ intent.putExtra("fragment_tag", "EpisodesFragment");
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
+
+ Notification notificationGroupSummary = new NotificationCompat.Builder(
+ context, NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS)
+ .setSmallIcon(R.drawable.ic_notification_new)
+ .setContentTitle(context.getString(R.string.new_episode_notification_group_text))
+ .setContentIntent(pendingIntent)
+ .setGroup(GROUP_KEY)
+ .setGroupSummary(true)
+ .setAutoCancel(true)
+ .build();
+ notificationManager.notify(NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS, 0, notificationGroupSummary);
+ }
+
+ private static Bitmap loadIcon(Context context, Feed feed) {
+ int iconSize = (int) (128 * context.getResources().getDisplayMetrics().density);
+ try {
+ return Glide.with(context)
+ .asBitmap()
+ .load(ImageResourceUtils.getImageLocation(feed))
+ .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY))
+ .apply(new RequestOptions().centerCrop())
+ .submit(iconSize, iconSize)
+ .get();
+ } catch (Throwable tr) {
+ return null;
+ }
+ }
+
+ private static int getNewEpisodeCount(long feedId) {
+ PodDBAdapter adapter = PodDBAdapter.getInstance();
+ adapter.open();
+ int episodeCount = adapter.getFeedCounters(UserPreferences.FEED_COUNTER_SHOW_NEW, feedId).get(feedId);
+ adapter.close();
+ return episodeCount;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java
index 483a2aa56..e2d9ee614 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.service.download.handler;
import android.content.Context;
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;
@@ -15,6 +16,7 @@ public class FeedSyncTask {
private final DownloadRequest request;
private final Context context;
private DownloadStatus downloadStatus;
+ private Feed savedFeed;
public FeedSyncTask(Context context, DownloadRequest request) {
this.request = request;
@@ -30,7 +32,7 @@ public class FeedSyncTask {
return false;
}
- Feed savedFeed = DBTasks.updateFeed(context, result.feed, false);
+ savedFeed = DBTasks.updateFeed(context, result.feed, false);
// If loadAllPages=true, check if another page is available and queue it for download
final boolean loadAllPages = request.getArguments().getBoolean(DownloadRequester.REQUEST_ARG_LOAD_ALL_PAGES);
final Feed feed = result.feed;
@@ -48,4 +50,8 @@ public class FeedSyncTask {
public DownloadStatus getDownloadStatus() {
return downloadStatus;
}
+
+ public Feed getSavedFeed() {
+ return savedFeed;
+ }
}
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 ee46f4e62..27f08243f 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
@@ -802,15 +802,9 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- List<Feed> feeds = getFeedList(adapter);
- long[] feedIds = new long[feeds.size()];
- for (int i = 0; i < feeds.size(); i++) {
- feedIds[i] = feeds.get(i).getId();
- }
- final LongIntMap feedCounters = adapter.getFeedCounters(feedIds);
-
+ final LongIntMap feedCounters = adapter.getFeedCounters();
SubscriptionsFilter subscriptionsFilter = UserPreferences.getSubscriptionsFilter();
- feeds = subscriptionsFilter.filter(getFeedList(adapter), feedCounters);
+ List<Feed> feeds = subscriptionsFilter.filter(getFeedList(adapter), feedCounters);
Comparator<Feed> comparator;
int feedOrder = UserPreferences.getFeedOrder();
@@ -840,7 +834,7 @@ public final class DBReader {
}
};
} else if (feedOrder == UserPreferences.FEED_ORDER_MOST_PLAYED) {
- final LongIntMap playedCounters = adapter.getPlayedEpisodesCounters(feedIds);
+ final LongIntMap playedCounters = adapter.getPlayedEpisodesCounters();
comparator = (lhs, rhs) -> {
long counterLhs = playedCounters.get(lhs.getId());
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
index 8574ff33b..93bc74ea8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
@@ -310,6 +310,10 @@ class DBUpgrader {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS +
" ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0;");
}
+ if (oldVersion < 2020000) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + PodDBAdapter.KEY_EPISODE_NOTIFICATION + " INTEGER DEFAULT 0;");
+ }
}
}
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 4a06829ce..8d1352a10 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
@@ -51,7 +51,7 @@ public class PodDBAdapter {
private static final String TAG = "PodDBAdapter";
public static final String DATABASE_NAME = "Antennapod.db";
- public static final int VERSION = 1090001;
+ public static final int VERSION = 2020000;
/**
* Maximum number of arguments for IN-operator.
@@ -115,6 +115,7 @@ public class PodDBAdapter {
public static final String KEY_FEED_PLAYBACK_SPEED = "feed_playback_speed";
public static final String KEY_FEED_SKIP_INTRO = "feed_skip_intro";
public static final String KEY_FEED_SKIP_ENDING = "feed_skip_ending";
+ public static final String KEY_EPISODE_NOTIFICATION = "episode_notification";
// Table names
public static final String TABLE_NAME_FEEDS = "Feeds";
@@ -152,7 +153,8 @@ public class PodDBAdapter {
+ KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL + ","
+ KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0,"
+ KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0,"
- + KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0)";
+ + KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0,"
+ + KEY_EPISODE_NOTIFICATION + " INTEGER DEFAULT 0)";
private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
+ TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
@@ -254,7 +256,8 @@ public class PodDBAdapter {
TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER,
TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED,
TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_INTRO,
- TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_ENDING
+ TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_ENDING,
+ TABLE_NAME_FEEDS + "." + KEY_EPISODE_NOTIFICATION
};
/**
@@ -446,6 +449,7 @@ public class PodDBAdapter {
values.put(KEY_FEED_PLAYBACK_SPEED, prefs.getFeedPlaybackSpeed());
values.put(KEY_FEED_SKIP_INTRO, prefs.getFeedSkipIntro());
values.put(KEY_FEED_SKIP_ENDING, prefs.getFeedSkipEnding());
+ values.put(KEY_EPISODE_NOTIFICATION, prefs.getShowEpisodeNotification());
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
}
@@ -1164,6 +1168,11 @@ public class PodDBAdapter {
public final LongIntMap getFeedCounters(long... feedIds) {
int setting = UserPreferences.getFeedCounterSetting();
+
+ return getFeedCounters(setting, feedIds);
+ }
+
+ public final LongIntMap getFeedCounters(int setting, long... feedIds) {
String whereRead;
switch (setting) {
case UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM:
@@ -1188,24 +1197,26 @@ public class PodDBAdapter {
}
private LongIntMap conditionalFeedCounterRead(String whereRead, long... feedIds) {
- // work around TextUtils.join wanting only boxed items
- // and StringUtils.join() causing NoSuchMethodErrors on MIUI
- StringBuilder builder = new StringBuilder();
- for (long id : feedIds) {
- builder.append(id);
- builder.append(',');
- }
+ String limitFeeds = "";
if (feedIds.length > 0) {
+ // work around TextUtils.join wanting only boxed items
+ // and StringUtils.join() causing NoSuchMethodErrors on MIUI
+ StringBuilder builder = new StringBuilder();
+ for (long id : feedIds) {
+ builder.append(id);
+ builder.append(',');
+ }
// there's an extra ',', get rid of it
builder.deleteCharAt(builder.length() - 1);
+ limitFeeds = KEY_FEED + " IN (" + builder.toString() + ") AND ";
}
final String query = "SELECT " + KEY_FEED + ", COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ") AS count "
+ " FROM " + TABLE_NAME_FEED_ITEMS
+ " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
+ TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") "
- + " AND " + whereRead + " GROUP BY " + KEY_FEED;
+ + " WHERE " + limitFeeds + " "
+ + whereRead + " GROUP BY " + KEY_FEED;
Cursor c = db.rawQuery(query, null);
LongIntMap result = new LongIntMap(c.getCount());
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 3101eac34..5895c5933 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
@@ -18,6 +18,7 @@ public class NotificationUtils {
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 CHANNEL_ID_EPISODE_NOTIFICATIONS = "episode_notifications";
public static final String GROUP_ID_ERRORS = "group_errors";
public static final String GROUP_ID_NEWS = "group_news";
@@ -38,6 +39,7 @@ public class NotificationUtils {
mNotificationManager.createNotificationChannel(createChannelError(context));
mNotificationManager.createNotificationChannel(createChannelSyncError(context));
mNotificationManager.createNotificationChannel(createChannelAutoDownload(context));
+ mNotificationManager.createNotificationChannel(createChannelEpisodeNotification(context));
}
}
@@ -111,6 +113,15 @@ public class NotificationUtils {
}
@RequiresApi(api = Build.VERSION_CODES.O)
+ private static NotificationChannel createChannelEpisodeNotification(Context c) {
+ NotificationChannel channel = new NotificationChannel(CHANNEL_ID_EPISODE_NOTIFICATIONS,
+ c.getString(R.string.notification_channel_new_episode), NotificationManager.IMPORTANCE_DEFAULT);
+ channel.setDescription(c.getString(R.string.notification_channel_new_episode_description));
+ channel.setGroup(GROUP_ID_NEWS);
+ return channel;
+ }
+
+ @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));
diff --git a/core/src/main/res/drawable-hdpi/ic_notification_new.png b/core/src/main/res/drawable-hdpi/ic_notification_new.png
new file mode 100644
index 000000000..28a8446e4
--- /dev/null
+++ b/core/src/main/res/drawable-hdpi/ic_notification_new.png
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_notification_new.png b/core/src/main/res/drawable-mdpi/ic_notification_new.png
new file mode 100644
index 000000000..02530f5e4
--- /dev/null
+++ b/core/src/main/res/drawable-mdpi/ic_notification_new.png
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_notification_new.png b/core/src/main/res/drawable-xhdpi/ic_notification_new.png
new file mode 100644
index 000000000..49c696798
--- /dev/null
+++ b/core/src/main/res/drawable-xhdpi/ic_notification_new.png
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_notification_new.png b/core/src/main/res/drawable-xxhdpi/ic_notification_new.png
new file mode 100644
index 000000000..ec6ef4f1e
--- /dev/null
+++ b/core/src/main/res/drawable-xxhdpi/ic_notification_new.png
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_notification_new.png b/core/src/main/res/drawable-xxxhdpi/ic_notification_new.png
new file mode 100644
index 000000000..66f968872
--- /dev/null
+++ b/core/src/main/res/drawable-xxxhdpi/ic_notification_new.png
Binary files differ
diff --git a/core/src/main/res/drawable/ic_notification_auto_download_complete.xml b/core/src/main/res/drawable/ic_notification_auto_download_complete.xml
deleted file mode 100644
index 0caf27836..000000000
--- a/core/src/main/res/drawable/ic_notification_auto_download_complete.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM16.59,7.58L10,14.17l-2.59,-2.58L6,13l4,4 8,-8z"
- android:fillColor="#ffffff"/>
-</vector>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index a52b30512..64554bc38 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -132,6 +132,17 @@
<item quantity="other">%d episodes</item>
</plurals>
<string name="loading_more">Loading moreā€¦</string>
+ <string name="episode_notification">Episode Notifications</string>
+ <string name="episode_notification_summary">Show a notification when a new episode is released.</string>
+ <plurals name="new_episode_notification_message">
+ <item quantity="one">%2$s has a new episode</item>
+ <item quantity="other">%2$s has %1$d new episodes</item>
+ </plurals>
+ <plurals name="new_episode_notification_title">
+ <item quantity="one">New Episode</item>
+ <item quantity="other">New Episodes</item>
+ </plurals>
+ <string name="new_episode_notification_group_text">Your subscriptions have new epsiodes.</string>
<!-- Actions on feeds -->
<string name="mark_all_read_label">Mark all as played</string>
@@ -870,6 +881,8 @@
<string name="notification_channel_sync_error_description">Shown when gpodder synchronization fails.</string>
<string name="notification_channel_auto_download">Automatic download completed</string>
<string name="notification_channel_episode_auto_download">Shown when episodes have been automatically downloaded.</string>
+ <string name="notification_channel_new_episode">New Episode</string>
+ <string name="notification_channel_new_episode_description">Shown when a new episode of a podcast was found, where notifications are enabled</string>
<!-- Widget settings -->
<string name="widget_settings">Widget settings</string>