From 84dc13d267f2a60ec2bc4abd11f62b1406de68c7 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 27 Sep 2024 17:36:05 -0300 Subject: [PATCH] Split up success and error notification Now, we don't do partial backups anymore. A snapshot is only done at the end and no information can make it to the backup before. Hence the old error notification with number of apps backed up didn't make sense anymore. --- .../seedvault/e2e/LargeBackupTestBase.kt | 10 ++++- app/src/main/AndroidManifest.xml | 1 + .../notification/BackupNotificationManager.kt | 37 +++++++++++++------ .../NotificationBackupObserver.kt | 4 +- .../seedvault/worker/BackupRequester.kt | 2 +- app/src/main/res/values/strings.xml | 1 + 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/LargeBackupTestBase.kt b/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/LargeBackupTestBase.kt index 738e19e6..ab4e1fdf 100644 --- a/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/LargeBackupTestBase.kt +++ b/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/LargeBackupTestBase.kt @@ -24,6 +24,7 @@ import kotlinx.coroutines.withTimeout import org.koin.core.component.get import java.io.ByteArrayOutputStream import java.util.concurrent.atomic.AtomicBoolean +import kotlin.test.fail internal interface LargeBackupTestBase : LargeTestBase { @@ -189,7 +190,7 @@ internal interface LargeBackupTestBase : LargeTestBase { clearMocks(spyBackupNotificationManager) every { - spyBackupNotificationManager.onBackupFinished(any(), any(), any(), any()) + spyBackupNotificationManager.onBackupSuccess(any(), any(), any()) } answers { val success = firstArg() assert(success) { "Backup failed." } @@ -197,6 +198,13 @@ internal interface LargeBackupTestBase : LargeTestBase { callOriginal() completed.set(true) } + every { + spyBackupNotificationManager.onBackupError() + } answers { + callOriginal() + completed.set(true) + fail("Backup failed.") + } return completed } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 80180014..0a79268a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -101,6 +101,7 @@ diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/notification/BackupNotificationManager.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/notification/BackupNotificationManager.kt index 251bf9b7..1bd8a9b8 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/notification/BackupNotificationManager.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/notification/BackupNotificationManager.kt @@ -185,21 +185,17 @@ internal class BackupNotificationManager(private val context: Context) { // } } - fun onBackupFinished(success: Boolean, numBackedUp: Int?, total: Int, size: Long) { - val titleRes = - if (success) R.string.notification_success_title else R.string.notification_failed_title - val contentText = if (numBackedUp == null) null else { - val sizeStr = Formatter.formatShortFileSize(context, size) + fun onBackupSuccess(numBackedUp: Int, total: Int, size: Long) { + val sizeStr = Formatter.formatShortFileSize(context, size) + val contentText = context.getString(R.string.notification_success_text, numBackedUp, total, sizeStr) - } - val iconRes = if (success) R.drawable.ic_cloud_done else R.drawable.ic_cloud_error val intent = Intent(context, SettingsActivity::class.java).apply { - if (success) action = ACTION_APP_STATUS_LIST + action = ACTION_APP_STATUS_LIST } val pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE) val notification = Builder(context, CHANNEL_ID_SUCCESS).apply { - setSmallIcon(iconRes) - setContentTitle(context.getString(titleRes)) + setSmallIcon(R.drawable.ic_cloud_done) + setContentTitle(context.getString(R.string.notification_success_title)) setContentText(contentText) setOngoing(false) setShowWhen(true) @@ -213,8 +209,27 @@ internal class BackupNotificationManager(private val context: Context) { nm.notify(NOTIFICATION_ID_SUCCESS, notification) } - @SuppressLint("RestrictedApi") fun onBackupError() { + val intent = Intent(context, SettingsActivity::class.java) + val pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE) + val notification = Builder(context, CHANNEL_ID_ERROR).apply { + setSmallIcon(R.drawable.ic_cloud_error) + setContentTitle(context.getString(R.string.notification_failed_title)) + setContentText(context.getString(R.string.notification_failed_text)) + setOngoing(false) + setShowWhen(true) + setAutoCancel(true) + setContentIntent(pendingIntent) + setWhen(System.currentTimeMillis()) + setProgress(0, 0, false) + priority = PRIORITY_LOW + }.build() + nm.cancel(NOTIFICATION_ID_OBSERVER) + nm.notify(NOTIFICATION_ID_ERROR, notification) + } + + @SuppressLint("RestrictedApi") + fun onFixableBackupError() { val intent = Intent(context, SettingsActivity::class.java) val pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE) val actionText = context.getString(R.string.notification_error_action) diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/notification/NotificationBackupObserver.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/notification/NotificationBackupObserver.kt index 49fad317..ac0fa195 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/notification/NotificationBackupObserver.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/notification/NotificationBackupObserver.kt @@ -172,10 +172,12 @@ internal class NotificationBackupObserver( snapshot.blobsMap[it.hexFromProto()]?.uncompressedLength?.toLong() ?: 0L } } else 0L - nm.onBackupFinished(success, numPackagesToReport, total, size) if (success) { + nm.onBackupSuccess(numPackagesToReport, total, size) // prune old backups AppBackupPruneWorker.scheduleNow(context) + } else { + nm.onBackupError() } } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/worker/BackupRequester.kt b/app/src/main/java/com/stevesoltys/seedvault/worker/BackupRequester.kt index f7a7ce95..c4dfb61a 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/worker/BackupRequester.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/worker/BackupRequester.kt @@ -115,7 +115,7 @@ internal class BackupRequester( } catch (e: RemoteException) { Log.e(TAG, "Error during backup: ", e) val nm: BackupNotificationManager = GlobalContext.get().get() - nm.onBackupError() + nm.onFixableBackupError() } return if (result == BackupManager.SUCCESS) { Log.i(TAG, "Backup request succeeded") diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f3c32247..5bf7309e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -155,6 +155,7 @@ Backup finished %1$d of %2$d apps backed up (%3$s). Tap to learn more. Backup failed + An error occurred while running the backup. Error notification Backup error