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.
This commit is contained in:
Torsten Grote 2024-09-27 17:36:05 -03:00
parent b7b07d0ba1
commit 84dc13d267
No known key found for this signature in database
GPG key ID: 3E5F77D92CF891FF
6 changed files with 41 additions and 14 deletions

View file

@ -24,6 +24,7 @@ import kotlinx.coroutines.withTimeout
import org.koin.core.component.get import org.koin.core.component.get
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import kotlin.test.fail
internal interface LargeBackupTestBase : LargeTestBase { internal interface LargeBackupTestBase : LargeTestBase {
@ -189,7 +190,7 @@ internal interface LargeBackupTestBase : LargeTestBase {
clearMocks(spyBackupNotificationManager) clearMocks(spyBackupNotificationManager)
every { every {
spyBackupNotificationManager.onBackupFinished(any(), any(), any(), any()) spyBackupNotificationManager.onBackupSuccess(any(), any(), any())
} answers { } answers {
val success = firstArg<Boolean>() val success = firstArg<Boolean>()
assert(success) { "Backup failed." } assert(success) { "Backup failed." }
@ -197,6 +198,13 @@ internal interface LargeBackupTestBase : LargeTestBase {
callOriginal() callOriginal()
completed.set(true) completed.set(true)
} }
every {
spyBackupNotificationManager.onBackupError()
} answers {
callOriginal()
completed.set(true)
fail("Backup failed.")
}
return completed return completed
} }

View file

@ -101,6 +101,7 @@
<activity <activity
android:name=".settings.SettingsActivity" android:name=".settings.SettingsActivity"
android:exported="true" android:exported="true"
android:launchMode="singleTask"
android:permission="com.stevesoltys.seedvault.OPEN_SETTINGS" android:permission="com.stevesoltys.seedvault.OPEN_SETTINGS"
android:windowSoftInputMode="adjustResize" /> android:windowSoftInputMode="adjustResize" />

View file

@ -185,21 +185,17 @@ internal class BackupNotificationManager(private val context: Context) {
// } // }
} }
fun onBackupFinished(success: Boolean, numBackedUp: Int?, total: Int, size: Long) { fun onBackupSuccess(numBackedUp: Int, total: Int, size: Long) {
val titleRes = val sizeStr = Formatter.formatShortFileSize(context, size)
if (success) R.string.notification_success_title else R.string.notification_failed_title val contentText =
val contentText = if (numBackedUp == null) null else {
val sizeStr = Formatter.formatShortFileSize(context, size)
context.getString(R.string.notification_success_text, numBackedUp, total, sizeStr) 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 { 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 pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE)
val notification = Builder(context, CHANNEL_ID_SUCCESS).apply { val notification = Builder(context, CHANNEL_ID_SUCCESS).apply {
setSmallIcon(iconRes) setSmallIcon(R.drawable.ic_cloud_done)
setContentTitle(context.getString(titleRes)) setContentTitle(context.getString(R.string.notification_success_title))
setContentText(contentText) setContentText(contentText)
setOngoing(false) setOngoing(false)
setShowWhen(true) setShowWhen(true)
@ -213,8 +209,27 @@ internal class BackupNotificationManager(private val context: Context) {
nm.notify(NOTIFICATION_ID_SUCCESS, notification) nm.notify(NOTIFICATION_ID_SUCCESS, notification)
} }
@SuppressLint("RestrictedApi")
fun onBackupError() { 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 intent = Intent(context, SettingsActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE) val pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE)
val actionText = context.getString(R.string.notification_error_action) val actionText = context.getString(R.string.notification_error_action)

View file

@ -172,10 +172,12 @@ internal class NotificationBackupObserver(
snapshot.blobsMap[it.hexFromProto()]?.uncompressedLength?.toLong() ?: 0L snapshot.blobsMap[it.hexFromProto()]?.uncompressedLength?.toLong() ?: 0L
} }
} else 0L } else 0L
nm.onBackupFinished(success, numPackagesToReport, total, size)
if (success) { if (success) {
nm.onBackupSuccess(numPackagesToReport, total, size)
// prune old backups // prune old backups
AppBackupPruneWorker.scheduleNow(context) AppBackupPruneWorker.scheduleNow(context)
} else {
nm.onBackupError()
} }
} }
} }

View file

@ -115,7 +115,7 @@ internal class BackupRequester(
} catch (e: RemoteException) { } catch (e: RemoteException) {
Log.e(TAG, "Error during backup: ", e) Log.e(TAG, "Error during backup: ", e)
val nm: BackupNotificationManager = GlobalContext.get().get() val nm: BackupNotificationManager = GlobalContext.get().get()
nm.onBackupError() nm.onFixableBackupError()
} }
return if (result == BackupManager.SUCCESS) { return if (result == BackupManager.SUCCESS) {
Log.i(TAG, "Backup request succeeded") Log.i(TAG, "Backup request succeeded")

View file

@ -155,6 +155,7 @@
<string name="notification_success_title">Backup finished</string> <string name="notification_success_title">Backup finished</string>
<string name="notification_success_text">%1$d of %2$d apps backed up (%3$s). Tap to learn more.</string> <string name="notification_success_text">%1$d of %2$d apps backed up (%3$s). Tap to learn more.</string>
<string name="notification_failed_title">Backup failed</string> <string name="notification_failed_title">Backup failed</string>
<string name="notification_failed_text">An error occurred while running the backup.</string>
<string name="notification_error_channel_title">Error notification</string> <string name="notification_error_channel_title">Error notification</string>
<string name="notification_error_title">Backup error</string> <string name="notification_error_title">Backup error</string>