summaryrefslogtreecommitdiff
path: root/core/src/main
diff options
context:
space:
mode:
authorH. Lehmann <ByteHamster@users.noreply.github.com>2020-03-26 19:22:04 +0100
committerGitHub <noreply@github.com>2020-03-26 19:22:04 +0100
commit38c1b559e3d3a7714a4fd0b1fe41ed94a1bcd526 (patch)
treee3cd6f1eb757e742195c4d7f077787800c66072e /core/src/main
parenta6accec122297c414b7f00b3e5444bd39f94b390 (diff)
parent13ca1a8dbc04958eda4a488642139972637f6d2f (diff)
downloadAntennaPod-38c1b559e3d3a7714a4fd0b1fe41ed94a1bcd526.zip
Merge pull request #3839 from shortspider/NotificationForAutoDownloads
Notification for Auto Downloads
Diffstat (limited to 'core/src/main')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/DownloadServiceCallbacks.java12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java81
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java69
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java92
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.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/DBTasks.java45
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java30
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java10
-rw-r--r--core/src/main/res/drawable/auto_download_complete.xml9
-rw-r--r--core/src/main/res/values/strings.xml5
16 files changed, 211 insertions, 168 deletions
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 dbaece14a..ad3fb8d42 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/DownloadServiceCallbacks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/DownloadServiceCallbacks.java
@@ -42,9 +42,19 @@ public interface DownloadServiceCallbacks {
PendingIntent getReportNotificationContentIntent(Context context);
/**
+ * Returns a PendingIntent for notification that notifies the user about the episodes that have been automatically
+ * downloaded.
+ * <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
+ */
+ 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/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
index b2ea1fa62..f7b6ccb2a 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
@@ -60,6 +60,7 @@ public class UserPreferences {
public static final String PREF_COMPACT_NOTIFICATION_BUTTONS = "prefCompactNotificationButtons";
public static final String PREF_LOCKSCREEN_BACKGROUND = "prefLockscreenBackground";
private static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport";
+ private static final String PREF_SHOW_AUTO_DOWNLOAD_REPORT = "prefShowAutoDownloadReport";
public static final String PREF_BACK_BUTTON_BEHAVIOR = "prefBackButtonBehavior";
private static final String PREF_BACK_BUTTON_GO_TO_PAGE = "prefBackButtonGoToPage";
@@ -292,6 +293,10 @@ public class UserPreferences {
return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true);
}
+ public static boolean showAutoDownloadReport() {
+ return prefs.getBoolean(PREF_SHOW_AUTO_DOWNLOAD_REPORT, false);
+ }
+
public static boolean enqueueDownloadedEpisodes() {
return prefs.getBoolean(PREF_ENQUEUE_DOWNLOADED, true);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
index 4443319e9..8811faf8a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
@@ -31,7 +31,7 @@ public class FeedUpdateWorker extends Worker {
ClientConfig.initialize(getApplicationContext());
if (NetworkUtils.networkAvailable() && NetworkUtils.isFeedRefreshAllowed()) {
- DBTasks.refreshAllFeeds(getApplicationContext());
+ DBTasks.refreshAllFeeds(getApplicationContext(), false);
} else {
Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed");
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
index 2dd46cf96..78c4d3f48 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
@@ -29,59 +29,42 @@ public class DownloadRequest implements Parcelable {
private long size;
private int statusMsg;
private boolean mediaEnqueued;
+ private boolean initiatedByUser;
- public DownloadRequest(@NonNull String destination,
- @NonNull String source,
- @NonNull String title,
- long feedfileId,
- int feedfileType,
- String username,
- String password,
- boolean deleteOnFailure,
- Bundle arguments) {
+ public DownloadRequest(@NonNull String destination, @NonNull String source, @NonNull String title, long feedfileId,
+ int feedfileType, String username, String password, boolean deleteOnFailure,
+ Bundle arguments, boolean initiatedByUser) {
+ this(destination, source, title, feedfileId, feedfileType, null, deleteOnFailure, username, password, false,
+ arguments, initiatedByUser);
+ }
+
+ private DownloadRequest(Builder builder) {
+ this(builder.destination, builder.source, builder.title, builder.feedfileId, builder.feedfileType,
+ builder.lastModified, builder.deleteOnFailure, builder.username, builder.password, false,
+ builder.arguments != null ? builder.arguments : new Bundle(), builder.initiatedByUser);
+ }
+ private DownloadRequest(Parcel in) {
+ this(in.readString(), in.readString(), in.readString(), in.readLong(), in.readInt(), in.readString(),
+ in.readByte() > 0, nullIfEmpty(in.readString()), nullIfEmpty(in.readString()), in.readByte() > 0,
+ in.readBundle(), in.readByte() > 0);
+ }
+
+ private DownloadRequest(String destination, String source, String title, long feedfileId, int feedfileType,
+ String lastModified, boolean deleteOnFailure, String username, String password,
+ boolean mediaEnqueued, Bundle arguments, boolean initiatedByUser) {
this.destination = destination;
this.source = source;
this.title = title;
this.feedfileId = feedfileId;
this.feedfileType = feedfileType;
+ this.lastModified = lastModified;
+ this.deleteOnFailure = deleteOnFailure;
this.username = username;
this.password = password;
- this.deleteOnFailure = deleteOnFailure;
- this.mediaEnqueued = false;
- this.arguments = (arguments != null) ? arguments : new Bundle();
- }
-
- public DownloadRequest(String destination, String source, String title,
- long feedfileId, int feedfileType) {
- this(destination, source, title, feedfileId, feedfileType, null, null, true, null);
- }
-
- private DownloadRequest(Builder builder) {
- this.destination = builder.destination;
- this.source = builder.source;
- this.title = builder.title;
- this.feedfileId = builder.feedfileId;
- this.feedfileType = builder.feedfileType;
- this.username = builder.username;
- this.password = builder.password;
- this.lastModified = builder.lastModified;
- this.deleteOnFailure = builder.deleteOnFailure;
- this.arguments = (builder.arguments != null) ? builder.arguments : new Bundle();
- }
-
- private DownloadRequest(Parcel in) {
- destination = in.readString();
- source = in.readString();
- title = in.readString();
- feedfileId = in.readLong();
- feedfileType = in.readInt();
- lastModified = in.readString();
- deleteOnFailure = (in.readByte() > 0);
- username = nullIfEmpty(in.readString());
- password = nullIfEmpty(in.readString());
- mediaEnqueued = (in.readByte() > 0);
- arguments = in.readBundle();
+ this.mediaEnqueued = mediaEnqueued;
+ this.arguments = arguments;
+ this.initiatedByUser = initiatedByUser;
}
@Override
@@ -107,6 +90,7 @@ public class DownloadRequest implements Parcelable {
dest.writeString(nonNullString(password));
dest.writeByte((mediaEnqueued) ? (byte) 1 : 0);
dest.writeBundle(arguments);
+ dest.writeByte(initiatedByUser ? (byte) 1 : 0);
}
private static String nonNullString(String str) {
@@ -153,6 +137,7 @@ public class DownloadRequest implements Parcelable {
if (username != null ? !username.equals(that.username) : that.username != null)
return false;
if (mediaEnqueued != that.mediaEnqueued) return false;
+ if (initiatedByUser != that.initiatedByUser) return false;
return true;
}
@@ -258,6 +243,10 @@ public class DownloadRequest implements Parcelable {
return mediaEnqueued;
}
+ public boolean isInitiatedByUser() {
+ return initiatedByUser;
+ }
+
/**
* Set to true if the media is enqueued because of this download.
* The state is helpful if the download is cancelled, and undoing the enqueue is needed.
@@ -281,13 +270,15 @@ public class DownloadRequest implements Parcelable {
private final long feedfileId;
private final int feedfileType;
private Bundle arguments;
+ private boolean initiatedByUser;
- public Builder(@NonNull String destination, @NonNull FeedFile item) {
+ public Builder(@NonNull String destination, @NonNull FeedFile item, boolean initiatedByUser) {
this.destination = destination;
this.source = URLChecker.prepareURL(item.getDownload_url());
this.title = item.getHumanReadableIdentifier();
this.feedfileId = item.getId();
this.feedfileType = item.getTypeAsInt();
+ this.initiatedByUser = initiatedByUser;
}
public Builder deleteOnFailure(boolean deleteOnFailure) {
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 d4177df46..ee34746fc 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
@@ -205,9 +205,10 @@ public class DownloadService extends Service {
Log.d(TAG, "Service shutting down");
isRunning = false;
+ boolean showAutoDownloadReport = UserPreferences.showAutoDownloadReport();
if (ClientConfig.downloadServiceCallbacks.shouldCreateReport()
- && UserPreferences.showDownloadReport()) {
- notificationManager.updateReport(reportQueue);
+ && (UserPreferences.showDownloadReport() || showAutoDownloadReport)) {
+ notificationManager.updateReport(reportQueue, showAutoDownloadReport);
reportQueue.clear();
}
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 f49257174..b6f7e0b8f 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
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.service.download;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
@@ -19,6 +20,7 @@ import java.util.List;
public class DownloadServiceNotification {
private static final String TAG = "DownloadSvcNotification";
private static final int REPORT_ID = 3;
+ private static final int AUTO_REPORT_ID = 4;
private final Context context;
private NotificationCompat.Builder notificationCompatBuilder;
@@ -91,12 +93,26 @@ public class DownloadServiceNotification {
return TextUtils.join("\n", lines);
}
+ private static String createAutoDownloadNotificationContent(List<DownloadStatus> statuses) {
+ int length = statuses.size();
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < length; i++) {
+ sb.append("• ").append(statuses.get(i).getTitle());
+ if (i != length - 1) {
+ sb.append("\n");
+ }
+ }
+
+ return sb.toString();
+ }
+
/**
* Creates a notification at the end of the service lifecycle to notify the
* user about the number of completed downloads. A report will only be
* created if there is at least one failed download excluding images
*/
- public void updateReport(List<DownloadStatus> reportQueue) {
+ public void updateReport(List<DownloadStatus> reportQueue, boolean showAutoDownloadReport) {
// check if report should be created
boolean createReport = false;
int successfulDownloads = 0;
@@ -107,34 +123,53 @@ public class DownloadServiceNotification {
for (DownloadStatus status : reportQueue) {
if (status.isSuccessful()) {
successfulDownloads++;
+ createReport |= showAutoDownloadReport && !status.isInitiatedByUser() && status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA;
} else if (!status.isCancelled()) {
- createReport = true;
failedDownloads++;
+ createReport = true;
}
}
if (createReport) {
Log.d(TAG, "Creating report");
+
// create notification object
- NotificationCompat.Builder builder = new NotificationCompat.Builder(context,
- NotificationUtils.CHANNEL_ID_ERROR)
- .setTicker(context.getString(R.string.download_report_title))
- .setContentTitle(context.getString(R.string.download_report_content_title))
- .setContentText(
- String.format(
- context.getString(R.string.download_report_content),
- successfulDownloads, failedDownloads)
- )
- .setSmallIcon(R.drawable.stat_notify_sync_error)
- .setContentIntent(
- ClientConfig.downloadServiceCallbacks.getReportNotificationContentIntent(context)
- )
- .setAutoCancel(true);
+ String channelId;
+ int titleId;
+ int iconId;
+ int id;
+ String content;
+ PendingIntent intent;
+ if (failedDownloads == 0) {
+ // We are generating an auto-download report
+ channelId = NotificationUtils.CHANNEL_ID_AUTO_DOWNLOAD;
+ titleId = R.string.auto_download_report_title;
+ iconId = R.drawable.auto_download_complete;
+ intent = ClientConfig.downloadServiceCallbacks.getAutoDownloadReportNotificationContentIntent(context);
+ id = AUTO_REPORT_ID;
+ content = createAutoDownloadNotificationContent(reportQueue);
+ } else {
+ channelId = NotificationUtils.CHANNEL_ID_ERROR;
+ titleId = R.string.download_report_title;
+ iconId = R.drawable.stat_notify_sync_error;
+ intent = ClientConfig.downloadServiceCallbacks.getReportNotificationContentIntent(context);
+ id = REPORT_ID;
+ content = String.format(context.getString(R.string.download_report_content), successfulDownloads, failedDownloads);
+ }
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId);
+ builder.setTicker(context.getString(titleId))
+ .setContentTitle(context.getString(titleId))
+ .setContentText(content)
+ .setStyle(new NotificationCompat.BigTextStyle().bigText(content))
+ .setSmallIcon(iconId)
+ .setContentIntent(intent)
+ .setAutoCancel(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
}
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- nm.notify(REPORT_ID, builder.build());
+ nm.notify(id, builder.build());
} else {
Log.d(TAG, "No report is created");
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java
index 675115bc7..bad2ba1ef 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java
@@ -41,62 +41,23 @@ public class DownloadStatus {
* FEEDFILETYPE_FEEDIMAGE or FEEDFILETYPE_FEEDMEDIA
*/
private final int feedfileType;
+ private final boolean initiatedByUser;
// ------------------------------------ NOT STORED IN DB
private boolean done;
private boolean cancelled;
- /** Constructor for restoring Download status entries from DB. */
- private DownloadStatus(long id, String title, long feedfileId,
- int feedfileType, boolean successful, DownloadError reason,
- Date completionDate, String reasonDetailed) {
- this.id = id;
- this.title = title;
- this.done = true;
- this.feedfileId = feedfileId;
- this.reason = reason;
- this.successful = successful;
- this.completionDate = (Date) completionDate.clone();
- this.reasonDetailed = reasonDetailed;
- this.feedfileType = feedfileType;
- }
-
- public DownloadStatus(@NonNull DownloadRequest request, DownloadError reason,
- boolean successful, boolean cancelled, String reasonDetailed) {
- this.title = request.getTitle();
- this.feedfileId = request.getFeedfileId();
- this.feedfileType = request.getFeedfileType();
- this.reason = reason;
- this.successful = successful;
- this.cancelled = cancelled;
- this.reasonDetailed = reasonDetailed;
- this.completionDate = new Date();
+ public DownloadStatus(@NonNull DownloadRequest request, DownloadError reason, boolean successful, boolean cancelled,
+ String reasonDetailed) {
+ this(0, request.getTitle(), request.getFeedfileId(), request.getFeedfileType(), successful, cancelled, false,
+ reason, new Date(), reasonDetailed, request.isInitiatedByUser());
}
/** Constructor for creating new completed downloads. */
- public DownloadStatus(@NonNull FeedFile feedfile, String title, DownloadError reason,
- boolean successful, String reasonDetailed) {
- this.title = title;
- this.done = true;
- this.feedfileId = feedfile.getId();
- this.feedfileType = feedfile.getTypeAsInt();
- this.reason = reason;
- this.successful = successful;
- this.completionDate = new Date();
- this.reasonDetailed = reasonDetailed;
- }
-
- /** Constructor for creating new completed downloads. */
- public DownloadStatus(long feedfileId, int feedfileType, String title,
- DownloadError reason, boolean successful, String reasonDetailed) {
- this.title = title;
- this.done = true;
- this.feedfileId = feedfileId;
- this.feedfileType = feedfileType;
- this.reason = reason;
- this.successful = successful;
- this.completionDate = new Date();
- this.reasonDetailed = reasonDetailed;
+ public DownloadStatus(@NonNull FeedFile feedfile, String title, DownloadError reason, boolean successful,
+ String reasonDetailed, boolean initiatedByUser) {
+ this(0, title, feedfile.getId(), feedfile.getTypeAsInt(), successful, false, true, reason, new Date(),
+ reasonDetailed, initiatedByUser);
}
public static DownloadStatus fromCursor(Cursor cursor) {
@@ -109,18 +70,27 @@ public class DownloadStatus {
int indexCompletionDate = cursor.getColumnIndex(PodDBAdapter.KEY_COMPLETION_DATE);
int indexReasonDetailed = cursor.getColumnIndex(PodDBAdapter.KEY_REASON_DETAILED);
- long id = cursor.getLong(indexId);
- String title = cursor.getString(indexTitle);
- long feedfileId = cursor.getLong(indexFeedFile);
- int feedfileType = cursor.getInt(indexFileFileType);
- boolean successful = cursor.getInt(indexSuccessful) > 0;
- int reason = cursor.getInt(indexReason);
- Date completionDate = new Date(cursor.getLong(indexCompletionDate));
- String reasonDetailed = cursor.getString(indexReasonDetailed);
-
- return new DownloadStatus(id, title, feedfileId,
- feedfileType, successful, DownloadError.fromCode(reason), completionDate,
- reasonDetailed);
+ return new DownloadStatus(cursor.getLong(indexId), cursor.getString(indexTitle), cursor.getLong(indexFeedFile),
+ cursor.getInt(indexFileFileType), cursor.getInt(indexSuccessful) > 0, false, true,
+ DownloadError.fromCode(cursor.getInt(indexReason)),
+ new Date(cursor.getLong(indexCompletionDate)),
+ cursor.getString(indexReasonDetailed), false);
+ }
+
+ private DownloadStatus(long id, String title, long feedfileId, int feedfileType, boolean successful,
+ boolean cancelled, boolean done, DownloadError reason, Date completionDate,
+ String reasonDetailed, boolean initiatedByUser) {
+ this.id = id;
+ this.title = title;
+ this.feedfileId = feedfileId;
+ this.reason = reason;
+ this.successful = successful;
+ this.cancelled = cancelled;
+ this.done = done;
+ this.completionDate = (Date) completionDate.clone();
+ this.reasonDetailed = reasonDetailed;
+ this.feedfileType = feedfileType;
+ this.initiatedByUser = initiatedByUser;
}
@Override
@@ -165,6 +135,8 @@ public class DownloadStatus {
return feedfileType;
}
+ public boolean isInitiatedByUser() { return initiatedByUser; }
+
public boolean isDone() {
return done;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
index c418db214..05e602db8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
@@ -78,12 +78,12 @@ public class FeedParserTask implements Callable<FeedHandlerResult> {
}
if (successful) {
- downloadStatus = new DownloadStatus(feed, feed.getHumanReadableIdentifier(),
- DownloadError.SUCCESS, successful, reasonDetailed);
+ downloadStatus = new DownloadStatus(feed, feed.getHumanReadableIdentifier(), DownloadError.SUCCESS,
+ successful, reasonDetailed, request.isInitiatedByUser());
return result;
} else {
- downloadStatus = new DownloadStatus(feed, request.getTitle(),
- reason, successful, reasonDetailed);
+ downloadStatus = new DownloadStatus(feed, feed.getTitle(), reason, successful,
+ reasonDetailed, request.isInitiatedByUser());
return null;
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
index 9ecabd14b..26a0e416e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
@@ -96,7 +96,7 @@ public class MediaDownloadedHandler implements Runnable {
} catch (ExecutionException e) {
Log.e(TAG, "ExecutionException in MediaHandlerThread: " + e.getMessage());
updatedStatus = new DownloadStatus(media, media.getEpisodeTitle(),
- DownloadError.ERROR_DB_ACCESS_ERROR, false, e.getMessage());
+ DownloadError.ERROR_DB_ACCESS_ERROR, false, e.getMessage(), request.isInitiatedByUser());
}
if (GpodnetPreferences.loggedIn() && item != null) {
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 6e4054009..7ec4db5dd 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
@@ -92,7 +92,7 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
Log.d(TAG, "Enqueueing " + itemsToDownload.length + " items for download");
try {
- DownloadRequester.getInstance().downloadMedia(false, context, itemsToDownload);
+ DownloadRequester.getInstance().downloadMedia(false, context, false, itemsToDownload);
} catch (DownloadRequestException e) {
e.printStackTrace();
}
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 5b7e62964..0695b1d04 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
@@ -105,8 +105,9 @@ public final class DBTasks {
* enqueuing Feeds for download from a previous call
*
* @param context Might be used for accessing the database
+ * @param initiatedByUser a boolean indicating if the refresh was triggered by user action.
*/
- public static void refreshAllFeeds(final Context context) {
+ public static void refreshAllFeeds(final Context context, boolean initiatedByUser) {
if (!isRefreshing.compareAndSet(false, true)) {
Log.d(TAG, "Ignoring request to refresh all feeds: Refresh lock is locked");
return;
@@ -116,7 +117,7 @@ public final class DBTasks {
throw new IllegalStateException("DBTasks.refreshAllFeeds() must not be called from the main thread.");
}
- refreshFeeds(context, DBReader.getFeedList());
+ refreshFeeds(context, DBReader.getFeedList(), initiatedByUser);
isRefreshing.set(false);
SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE);
@@ -134,9 +135,11 @@ public final class DBTasks {
/**
* @param context
* @param feedList the list of feeds to refresh
+ * @param initiatedByUser a boolean indicating if the refresh was triggered by user action.
*/
private static void refreshFeeds(final Context context,
- final List<Feed> feedList) {
+ final List<Feed> feedList,
+ boolean initiatedByUser) {
for (Feed feed : feedList) {
FeedPreferences prefs = feed.getPreferences();
@@ -148,11 +151,12 @@ public final class DBTasks {
} catch (DownloadRequestException e) {
e.printStackTrace();
DBWriter.addDownloadStatus(
- new DownloadStatus(feed, feed
- .getHumanReadableIdentifier(),
- DownloadError.ERROR_REQUEST_ERROR, false, e
- .getMessage()
- )
+ new DownloadStatus(feed,
+ feed.getHumanReadableIdentifier(),
+ DownloadError.ERROR_REQUEST_ERROR,
+ false,
+ e.getMessage(),
+ initiatedByUser)
);
}
}
@@ -168,15 +172,16 @@ public final class DBTasks {
*/
public static void forceRefreshCompleteFeed(final Context context, final Feed feed) {
try {
- refreshFeed(context, feed, true, true);
+ refreshFeed(context, feed, true, true, false);
} catch (DownloadRequestException e) {
e.printStackTrace();
DBWriter.addDownloadStatus(
- new DownloadStatus(feed, feed
- .getHumanReadableIdentifier(),
- DownloadError.ERROR_REQUEST_ERROR, false, e
- .getMessage()
- )
+ new DownloadStatus(feed,
+ feed.getHumanReadableIdentifier(),
+ DownloadError.ERROR_REQUEST_ERROR,
+ false,
+ e.getMessage(),
+ false)
);
}
}
@@ -196,7 +201,7 @@ public final class DBTasks {
nextFeed.setPageNr(pageNr);
nextFeed.setPaged(true);
nextFeed.setId(feed.getId());
- DownloadRequester.getInstance().downloadFeed(context, nextFeed, loadAllPages, false);
+ DownloadRequester.getInstance().downloadFeed(context, nextFeed, loadAllPages, false, true);
} else {
Log.e(TAG, "loadNextPageOfFeed: Feed was either not paged or contained no nextPageLink");
}
@@ -212,7 +217,7 @@ public final class DBTasks {
private static void refreshFeed(Context context, Feed feed)
throws DownloadRequestException {
Log.d(TAG, "refreshFeed(feed.id: " + feed.getId() +")");
- refreshFeed(context, feed, false, false);
+ refreshFeed(context, feed, false, false, false);
}
/**
@@ -221,13 +226,13 @@ public final class DBTasks {
* @param context Used for requesting the download.
* @param feed The Feed object.
*/
- public static void forceRefreshFeed(Context context, Feed feed)
+ public static void forceRefreshFeed(Context context, Feed feed, boolean initiatedByUser)
throws DownloadRequestException {
Log.d(TAG, "refreshFeed(feed.id: " + feed.getId() +")");
- refreshFeed(context, feed, false, true);
+ refreshFeed(context, feed, false, true, initiatedByUser);
}
- private static void refreshFeed(Context context, Feed feed, boolean loadAllPages, boolean force)
+ private static void refreshFeed(Context context, Feed feed, boolean loadAllPages, boolean force, boolean initiatedByUser)
throws DownloadRequestException {
Feed f;
String lastUpdate = feed.hasLastUpdateFailed() ? null : feed.getLastUpdate();
@@ -238,7 +243,7 @@ public final class DBTasks {
feed.getPreferences().getUsername(), feed.getPreferences().getPassword());
}
f.setId(feed.getId());
- DownloadRequester.getInstance().downloadFeed(context, f, loadAllPages, force);
+ DownloadRequester.getInstance().downloadFeed(context, f, loadAllPages, force, initiatedByUser);
}
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
index 8bd9afe38..6f9e6b056 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
@@ -113,9 +113,9 @@ public class DownloadRequester implements DownloadStateProvider {
}
@Nullable
- private DownloadRequest createRequest(FeedFile item, FeedFile container, File dest,
- boolean overwriteIfExists, String username, String password,
- String lastModified, boolean deleteOnFailure, Bundle arguments) {
+ private DownloadRequest createRequest(FeedFile item, FeedFile container, File dest, boolean overwriteIfExists,
+ String username, String password, String lastModified,
+ boolean deleteOnFailure, Bundle arguments, boolean initiatedByUser) {
final boolean partiallyDownloadedFileExists = item.getFile_url() != null && new File(item.getFile_url()).exists();
Log.d(TAG, "partiallyDownloadedFileExists: " + partiallyDownloadedFileExists);
@@ -156,7 +156,7 @@ public class DownloadRequester implements DownloadStateProvider {
String baseUrl = (container != null) ? container.getDownload_url() : null;
item.setDownload_url(URLChecker.prepareURL(item.getDownload_url(), baseUrl));
- DownloadRequest.Builder builder = new DownloadRequest.Builder(dest.toString(), item)
+ DownloadRequest.Builder builder = new DownloadRequest.Builder(dest.toString(), item, initiatedByUser)
.withAuthentication(username, password)
.lastModified(lastModified)
.deleteOnFailure(deleteOnFailure)
@@ -191,7 +191,7 @@ public class DownloadRequester implements DownloadStateProvider {
* @param loadAllPages Set to true to download all pages
*/
public synchronized void downloadFeed(Context context, Feed feed, boolean loadAllPages,
- boolean force)
+ boolean force, boolean initiatedByUser)
throws DownloadRequestException {
if (feedFileValid(feed)) {
String username = (feed.getPreferences() != null) ? feed.getPreferences().getUsername() : null;
@@ -203,7 +203,8 @@ public class DownloadRequester implements DownloadStateProvider {
args.putBoolean(REQUEST_ARG_LOAD_ALL_PAGES, loadAllPages);
DownloadRequest request = createRequest(feed, null, new File(getFeedfilePath(), getFeedfileName(feed)),
- true, username, password, lastModified, true, args);
+ true, username, password, lastModified, true, args, initiatedByUser
+ );
if (request != null) {
download(context, request);
}
@@ -211,18 +212,18 @@ public class DownloadRequester implements DownloadStateProvider {
}
public synchronized void downloadFeed(Context context, Feed feed) throws DownloadRequestException {
- downloadFeed(context, feed, false, false);
+ downloadFeed(context, feed, false, false, true);
}
- public synchronized void downloadMedia(@NonNull Context context, FeedItem... feedItems)
+ public synchronized void downloadMedia(@NonNull Context context, boolean initiatedByUser, FeedItem... feedItems)
throws DownloadRequestException {
- downloadMedia(true, context, feedItems);
+ downloadMedia(true, context, initiatedByUser, feedItems);
}
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public synchronized void downloadMedia(boolean performAutoCleanup, @NonNull Context context,
- FeedItem... items)
+ boolean initiatedByUser, FeedItem... items)
throws DownloadRequestException {
Log.d(TAG, "downloadMedia() called with: performAutoCleanup = [" + performAutoCleanup
+ "], #items = [" + items.length + "]");
@@ -230,7 +231,7 @@ public class DownloadRequester implements DownloadStateProvider {
List<DownloadRequest> requests = new ArrayList<>(items.length);
for (FeedItem item : items) {
try {
- DownloadRequest request = createRequest(item.getMedia());
+ DownloadRequest request = createRequest(item.getMedia(), initiatedByUser);
if (request != null) {
requests.add(request);
}
@@ -246,7 +247,7 @@ public class DownloadRequester implements DownloadStateProvider {
.getMedia()
.getHumanReadableIdentifier(),
DownloadError.ERROR_REQUEST_ERROR,
- false, e.getMessage()
+ false, e.getMessage(), initiatedByUser
)
);
}
@@ -256,7 +257,7 @@ public class DownloadRequester implements DownloadStateProvider {
}
@Nullable
- private DownloadRequest createRequest(@Nullable FeedMedia feedmedia)
+ private DownloadRequest createRequest(@Nullable FeedMedia feedmedia, boolean initiatedByUser)
throws DownloadRequestException {
if (!feedFileValid(feedmedia)) {
return null;
@@ -278,8 +279,7 @@ public class DownloadRequester implements DownloadStateProvider {
} else {
dest = new File(getMediafilePath(feedmedia), getMediafilename(feedmedia));
}
- return createRequest(feedmedia, feed,
- dest, false, username, password, null, false, null);
+ return createRequest(feedmedia, feed, dest, false, username, password, null, false, null, initiatedByUser);
}
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java b/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
index e093a7e00..fc04d82cc 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java
@@ -115,7 +115,7 @@ public class AutoUpdateManager {
public static void runImmediate(@NonNull Context context) {
Log.d(TAG, "Run auto update immediately in background.");
new Thread(() -> {
- DBTasks.refreshAllFeeds(context.getApplicationContext());
+ DBTasks.refreshAllFeeds(context.getApplicationContext(), true);
}, "ManualRefreshAllFeeds").start();
}
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 02e98ba84..f546ca019 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
@@ -14,6 +14,7 @@ public class NotificationUtils {
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_AUTO_DOWNLOAD = "auto_download";
public static void createChannels(Context context) {
if (android.os.Build.VERSION.SDK_INT < 26) {
@@ -26,6 +27,7 @@ public class NotificationUtils {
mNotificationManager.createNotificationChannel(createChannelDownloading(context));
mNotificationManager.createNotificationChannel(createChannelPlaying(context));
mNotificationManager.createNotificationChannel(createChannelError(context));
+ mNotificationManager.createNotificationChannel(createChannelAutoDownload(context));
}
}
@@ -62,4 +64,12 @@ public class NotificationUtils {
mChannel.setDescription(c.getString(R.string.notification_channel_error_description));
return mChannel;
}
+
+ @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;
+ }
}
diff --git a/core/src/main/res/drawable/auto_download_complete.xml b/core/src/main/res/drawable/auto_download_complete.xml
new file mode 100644
index 000000000..500d1e156
--- /dev/null
+++ b/core/src/main/res/drawable/auto_download_complete.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ 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 c65aed322..2f80ac416 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -237,6 +237,7 @@
<string name="download_canceled_msg">Download canceled</string>
<string name="download_canceled_autodownload_enabled_msg">Download canceled\nDisabled <i>Auto Download</i> for this item</string>
<string name="download_report_title">Downloads completed with error(s)</string>
+ <string name="auto_download_report_title">Auto-downloads completed</string>
<string name="download_report_content_title">Download Report</string>
<string name="download_error_malformed_url">Malformed URL</string>
<string name="download_error_io_error">IO Error</string>
@@ -470,6 +471,8 @@
<string name="pref_lockscreen_background_sum">Set the lockscreen background to the current episode\'s image. As a side effect, this will also show the image in third party apps.</string>
<string name="pref_showDownloadReport_title">Show Download Report</string>
<string name="pref_showDownloadReport_sum">If downloads fail, generate a report that shows the details of the failure.</string>
+ <string name="pref_showAutoDownloadReport_title">Show Auto Download Report</string>
+ <string name="pref_showAutoDownloadReport_sum">Show a notification for automatically downloaded episodes.</string>
<string name="pref_expand_notify_unsupport_toast">Android versions before 4.1 do not support expanded notifications.</string>
<string name="pref_enqueue_location_title">Enqueue Location</string>
<string name="pref_enqueue_location_sum">Add episodes to: %1$s</string>
@@ -781,6 +784,8 @@
<string name="notification_channel_playing_description">Allows to control playback. This is the main notification you see while playing a podcast.</string>
<string name="notification_channel_error">Errors</string>
<string name="notification_channel_error_description">Shown if something went wrong, for example if download or gpodder sync fails.</string>
+ <string name="notification_channel_auto_download">Auto Downloads</string>
+ <string name="notification_channel_episode_auto_download">Shown when episodes have been automatically downloaded.</string>
<!-- Widget settings -->
<string name="widget_settings">Widget settings</string>