Add retry button to download failed notifications (#6333)
This commit is contained in:
parent
c98194f519
commit
a5d4864776
|
@ -14,6 +14,7 @@ import android.util.Log;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.app.ServiceCompat;
|
||||
|
||||
import de.danoeh.antennapod.core.R;
|
||||
|
@ -82,6 +83,7 @@ public class DownloadService extends Service {
|
|||
private final ExecutorService downloadEnqueueExecutor;
|
||||
|
||||
private final List<DownloadStatus> reportQueue = new ArrayList<>();
|
||||
private final List<DownloadRequest> failedRequestsForReport = new ArrayList<>();
|
||||
private DownloadServiceNotification notificationManager;
|
||||
private final NewEpisodesNotification newEpisodesNotification;
|
||||
private NotificationUpdater notificationUpdater;
|
||||
|
@ -176,11 +178,15 @@ public class DownloadService extends Service {
|
|||
if (intent != null && intent.hasExtra(EXTRA_REQUESTS)) {
|
||||
Notification notification = notificationManager.updateNotifications(downloads);
|
||||
startForeground(R.id.notification_downloading, notification);
|
||||
NotificationManagerCompat.from(this).cancel(R.id.notification_download_report);
|
||||
NotificationManagerCompat.from(this).cancel(R.id.notification_auto_download_report);
|
||||
setupNotificationUpdaterIfNecessary();
|
||||
downloadEnqueueExecutor.execute(() -> onDownloadQueued(intent));
|
||||
} else if (intent != null && intent.getBooleanExtra(EXTRA_REFRESH_ALL, false)) {
|
||||
Notification notification = notificationManager.updateNotifications(downloads);
|
||||
startForeground(R.id.notification_downloading, notification);
|
||||
NotificationManagerCompat.from(this).cancel(R.id.notification_download_report);
|
||||
NotificationManagerCompat.from(this).cancel(R.id.notification_auto_download_report);
|
||||
setupNotificationUpdaterIfNecessary();
|
||||
downloadEnqueueExecutor.execute(() -> enqueueAll(intent));
|
||||
} else if (downloads.size() == 0) {
|
||||
|
@ -198,8 +204,9 @@ public class DownloadService extends Service {
|
|||
|
||||
boolean showAutoDownloadReport = UserPreferences.showAutoDownloadReport();
|
||||
if (UserPreferences.showDownloadReport() || showAutoDownloadReport) {
|
||||
notificationManager.updateReport(reportQueue, showAutoDownloadReport);
|
||||
notificationManager.updateReport(reportQueue, showAutoDownloadReport, failedRequestsForReport);
|
||||
reportQueue.clear();
|
||||
failedRequestsForReport.clear();
|
||||
}
|
||||
|
||||
unregisterReceiver(cancelDownloadReceiver);
|
||||
|
@ -283,7 +290,7 @@ public class DownloadService extends Service {
|
|||
// we create a 'successful' download log if the feed's last refresh failed
|
||||
List<DownloadStatus> log = DBReader.getFeedDownloadLog(request.getFeedfileId());
|
||||
if (log.size() > 0 && !log.get(0).isSuccessful()) {
|
||||
saveDownloadStatus(feedSyncTask.getDownloadStatus());
|
||||
saveDownloadStatus(feedSyncTask.getDownloadStatus(), downloader.getDownloadRequest());
|
||||
}
|
||||
if (!request.isInitiatedByUser()) {
|
||||
// Was stored in the database before and not initiated manually
|
||||
|
@ -296,13 +303,13 @@ public class DownloadService extends Service {
|
|||
}
|
||||
} else {
|
||||
DBWriter.setFeedLastUpdateFailed(request.getFeedfileId(), true);
|
||||
saveDownloadStatus(feedSyncTask.getDownloadStatus());
|
||||
saveDownloadStatus(feedSyncTask.getDownloadStatus(), downloader.getDownloadRequest());
|
||||
}
|
||||
} else if (type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
|
||||
Log.d(TAG, "Handling completed FeedMedia Download");
|
||||
MediaDownloadedHandler handler = new MediaDownloadedHandler(DownloadService.this, status, request);
|
||||
handler.run();
|
||||
saveDownloadStatus(handler.getUpdatedStatus());
|
||||
saveDownloadStatus(handler.getUpdatedStatus(), downloader.getDownloadRequest());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,7 +328,7 @@ public class DownloadService extends Service {
|
|||
DownloadServiceInterface.get().download(this, false, downloader.getDownloadRequest());
|
||||
} else {
|
||||
Log.e(TAG, "Download failed");
|
||||
saveDownloadStatus(status);
|
||||
saveDownloadStatus(status, downloader.getDownloadRequest());
|
||||
new FailedDownloadHandler(downloader.getDownloadRequest()).run();
|
||||
|
||||
if (type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
|
||||
|
@ -509,8 +516,11 @@ public class DownloadService extends Service {
|
|||
*
|
||||
* @param status the download that is going to be saved
|
||||
*/
|
||||
private void saveDownloadStatus(@NonNull DownloadStatus status) {
|
||||
private void saveDownloadStatus(@NonNull DownloadStatus status, @NonNull DownloadRequest request) {
|
||||
reportQueue.add(status);
|
||||
if (!status.isSuccessful() && !status.isCancelled()) {
|
||||
failedRequestsForReport.add(request);
|
||||
}
|
||||
DBWriter.addDownloadStatus(status);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,13 @@ public class DownloadServiceInterfaceImpl extends DownloadServiceInterface {
|
|||
private static final String TAG = "DownloadServiceInterface";
|
||||
|
||||
public void download(Context context, boolean cleanupMedia, DownloadRequest... requests) {
|
||||
Intent intent = makeDownloadIntent(context, cleanupMedia, requests);
|
||||
if (intent != null) {
|
||||
ContextCompat.startForegroundService(context, intent);
|
||||
}
|
||||
}
|
||||
|
||||
public Intent makeDownloadIntent(Context context, boolean cleanupMedia, DownloadRequest... requests) {
|
||||
ArrayList<DownloadRequest> requestsToSend = new ArrayList<>();
|
||||
for (DownloadRequest request : requests) {
|
||||
if (!isDownloadingFile(request.getSource())) {
|
||||
|
@ -23,7 +30,7 @@ public class DownloadServiceInterfaceImpl extends DownloadServiceInterface {
|
|||
}
|
||||
}
|
||||
if (requestsToSend.isEmpty()) {
|
||||
return;
|
||||
return null;
|
||||
} else if (requestsToSend.size() > 100) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
throw new IllegalArgumentException("Android silently drops intent payloads that are too large");
|
||||
|
@ -38,7 +45,7 @@ public class DownloadServiceInterfaceImpl extends DownloadServiceInterface {
|
|||
if (cleanupMedia) {
|
||||
launchIntent.putExtra(DownloadService.EXTRA_CLEANUP_MEDIA, true);
|
||||
}
|
||||
ContextCompat.startForegroundService(context, launchIntent);
|
||||
return launchIntent;
|
||||
}
|
||||
|
||||
public void refreshAllFeeds(Context context, boolean initiatedByUser) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import de.danoeh.antennapod.model.feed.Feed;
|
|||
import de.danoeh.antennapod.model.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
|
||||
import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest;
|
||||
import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
|
||||
import de.danoeh.antennapod.ui.appstartintent.DownloadAuthenticationActivityStarter;
|
||||
import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
|
||||
|
||||
|
@ -153,7 +154,8 @@ public class DownloadServiceNotification {
|
|||
* 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, boolean showAutoDownloadReport) {
|
||||
public void updateReport(List<DownloadStatus> reportQueue, boolean showAutoDownloadReport,
|
||||
List<DownloadRequest> failedRequests) {
|
||||
// check if report should be created
|
||||
boolean createReport = false;
|
||||
int failedDownloads = 0;
|
||||
|
@ -173,48 +175,68 @@ public class DownloadServiceNotification {
|
|||
}
|
||||
}
|
||||
|
||||
if (createReport) {
|
||||
if (!createReport) {
|
||||
Log.d(TAG, "No report is created");
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "Creating report");
|
||||
|
||||
// create notification object
|
||||
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.ic_notification_new;
|
||||
intent = getAutoDownloadReportNotificationContentIntent(context);
|
||||
id = R.id.notification_auto_download_report;
|
||||
content = createAutoDownloadNotificationContent(reportQueue);
|
||||
createAutoDownloadReportNotification(reportQueue);
|
||||
} else {
|
||||
channelId = NotificationUtils.CHANNEL_ID_DOWNLOAD_ERROR;
|
||||
titleId = R.string.download_report_title;
|
||||
iconId = R.drawable.ic_notification_sync_error;
|
||||
intent = getReportNotificationContentIntent(context);
|
||||
id = R.id.notification_download_report;
|
||||
content = createFailedDownloadNotificationContent(reportQueue);
|
||||
createDownloadFailedNotification(reportQueue, failedRequests);
|
||||
}
|
||||
Log.d(TAG, "Download report notification was posted");
|
||||
}
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId);
|
||||
builder.setTicker(context.getString(titleId))
|
||||
.setContentTitle(context.getString(titleId))
|
||||
private void createAutoDownloadReportNotification(List<DownloadStatus> reportQueue) {
|
||||
PendingIntent intent = getAutoDownloadReportNotificationContentIntent(context);
|
||||
String content = createAutoDownloadNotificationContent(reportQueue);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,
|
||||
NotificationUtils.CHANNEL_ID_AUTO_DOWNLOAD);
|
||||
builder.setTicker(context.getString(R.string.auto_download_report_title))
|
||||
.setContentTitle(context.getString(R.string.auto_download_report_title))
|
||||
.setContentText(content)
|
||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(content))
|
||||
.setSmallIcon(iconId)
|
||||
.setSmallIcon(R.drawable.ic_notification_new)
|
||||
.setContentIntent(intent)
|
||||
.setAutoCancel(true)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify(R.id.notification_auto_download_report, builder.build());
|
||||
}
|
||||
|
||||
private void createDownloadFailedNotification(List<DownloadStatus> reportQueue,
|
||||
List<DownloadRequest> failedRequests) {
|
||||
Intent retryIntent = DownloadServiceInterface.get().makeDownloadIntent(context,
|
||||
false, failedRequests.toArray(new DownloadRequest[0]));
|
||||
PendingIntent retryPendingIntent = null;
|
||||
if (retryIntent != null && Build.VERSION.SDK_INT >= 26) {
|
||||
retryPendingIntent = PendingIntent.getForegroundService(context, R.id.pending_intent_download_service_retry,
|
||||
retryIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
} else if (retryIntent != null) {
|
||||
retryPendingIntent = PendingIntent.getService(context,
|
||||
R.id.pending_intent_download_service_retry, retryIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
| (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
PendingIntent intent = getReportNotificationContentIntent(context);
|
||||
String content = createFailedDownloadNotificationContent(reportQueue);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,
|
||||
NotificationUtils.CHANNEL_ID_DOWNLOAD_ERROR);
|
||||
builder.setTicker(context.getString(R.string.download_report_title))
|
||||
.setContentTitle(context.getString(R.string.download_report_title))
|
||||
.setContentText(content)
|
||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(content))
|
||||
.setSmallIcon(R.drawable.ic_notification_sync_error)
|
||||
.setContentIntent(intent)
|
||||
.setAutoCancel(true);
|
||||
if (retryPendingIntent != null) {
|
||||
builder.addAction(new NotificationCompat.Action(
|
||||
R.drawable.ic_notification_sync, context.getString(R.string.retry_label), retryPendingIntent));
|
||||
}
|
||||
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify(id, builder.build());
|
||||
Log.d(TAG, "Download report notification was posted");
|
||||
} else {
|
||||
Log.d(TAG, "No report is created");
|
||||
}
|
||||
nm.notify(R.id.notification_download_report, builder.build());
|
||||
}
|
||||
|
||||
public void postAuthenticationNotification(final DownloadRequest downloadRequest) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package de.danoeh.antennapod.net.download.serviceinterface;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public abstract class DownloadServiceInterface {
|
||||
private static DownloadServiceInterface impl;
|
||||
|
@ -15,6 +16,8 @@ public abstract class DownloadServiceInterface {
|
|||
|
||||
public abstract void download(Context context, boolean cleanupMedia, DownloadRequest... requests);
|
||||
|
||||
public abstract Intent makeDownloadIntent(Context context, boolean cleanupMedia, DownloadRequest... requests);
|
||||
|
||||
public abstract void refreshAllFeeds(Context context, boolean initiatedByUser);
|
||||
|
||||
public abstract void cancel(Context context, String url);
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package de.danoeh.antennapod.net.download.serviceinterface;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class DownloadServiceInterfaceStub extends DownloadServiceInterface {
|
||||
|
||||
public void download(Context context, boolean cleanupMedia, DownloadRequest... requests) {
|
||||
}
|
||||
|
||||
public Intent makeDownloadIntent(Context context, boolean cleanupMedia, DownloadRequest... requests) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void refreshAllFeeds(Context context, boolean initiatedByUser) {
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item name="pending_intent_download_service_notification" type="id"/>
|
||||
<item name="pending_intent_download_service_retry" type="id"/>
|
||||
<item name="pending_intent_download_service_auth" type="id"/>
|
||||
<item name="pending_intent_download_service_report" type="id"/>
|
||||
<item name="pending_intent_download_service_autodownload_report" type="id"/>
|
||||
|
|
Loading…
Reference in New Issue