diff --git a/app/src/main/java/com/stevesoltys/seedvault/App.kt b/app/src/main/java/com/stevesoltys/seedvault/App.kt index afff3eed..d5dde682 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/App.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/App.kt @@ -39,7 +39,7 @@ class App : Application() { single { Clock() } factory { IBackupManager.Stub.asInterface(getService(BACKUP_SERVICE)) } - viewModel { SettingsViewModel(this@App, get(), get(), get(), get()) } + viewModel { SettingsViewModel(this@App, get(), get(), get(), get(), get()) } viewModel { RecoveryCodeViewModel(this@App, get()) } viewModel { BackupStorageViewModel(this@App, get(), get(), get()) } viewModel { RestoreStorageViewModel(this@App, get(), get()) } diff --git a/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt b/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt index bc3d37c5..a398b56d 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt @@ -199,6 +199,8 @@ class MetadataManager( @Synchronized fun getPackagesNumBackedUp(): Int { + // FIXME we are under-reporting packages here, + // because we have no way to also include upgraded system apps return metadata.packageMetadataMap.filter { (_, packageMetadata) -> !packageMetadata.system && ( // ignore system apps packageMetadata.state == APK_AND_DATA || // either full success diff --git a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsViewModel.kt b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsViewModel.kt index 3b11506f..859b016d 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsViewModel.kt @@ -4,6 +4,8 @@ import android.app.Application import android.content.pm.PackageManager.NameNotFoundException import android.provider.Settings import android.util.Log +import android.widget.Toast +import android.widget.Toast.LENGTH_LONG import androidx.annotation.UiThread import androidx.core.content.ContextCompat.getDrawable import androidx.lifecycle.LiveData @@ -30,6 +32,7 @@ import com.stevesoltys.seedvault.restore.AppRestoreStatus.SUCCEEDED import com.stevesoltys.seedvault.transport.backup.PackageService import com.stevesoltys.seedvault.transport.requestBackup import com.stevesoltys.seedvault.ui.RequireProvisioningViewModel +import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.ui.notification.getAppName import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -43,6 +46,7 @@ internal class SettingsViewModel( app: Application, settingsManager: SettingsManager, keyManager: KeyManager, + private val notificationManager: BackupNotificationManager, private val metadataManager: MetadataManager, private val packageService: PackageService ) : RequireProvisioningViewModel(app, settingsManager, keyManager) { @@ -68,7 +72,11 @@ internal class SettingsViewModel( } internal fun backupNow() { - Thread { requestBackup(app) }.start() + if (notificationManager.hasActiveBackupNotifications()) { + Toast.makeText(app, R.string.notification_backup_already_running, LENGTH_LONG).show() + } else { + Thread { requestBackup(app) }.start() + } } private fun getAppStatusResult(): LiveData = liveData { 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 7225c5db..98e70619 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 @@ -16,6 +16,7 @@ import androidx.core.app.NotificationCompat.Builder import androidx.core.app.NotificationCompat.PRIORITY_DEFAULT import androidx.core.app.NotificationCompat.PRIORITY_HIGH import androidx.core.app.NotificationCompat.PRIORITY_LOW +import com.stevesoltys.seedvault.BuildConfig.APPLICATION_ID import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.restore.ACTION_RESTORE_ERROR_UNINSTALL @@ -204,6 +205,15 @@ internal class BackupNotificationManager(private val context: Context) { expectedAppTotals = null } + fun hasActiveBackupNotifications(): Boolean { + nm.activeNotifications.forEach { + if (it.packageName == APPLICATION_ID && + (it.id == NOTIFICATION_ID_OBSERVER || it.id == NOTIFICATION_ID_BACKGROUND) + ) return true + } + return false + } + fun onBackupError() { val intent = Intent(context, SettingsActivity::class.java) val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 338053ec..d8fb40bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -76,6 +76,7 @@ Backup complete Not backed up Backup failed + Backup already in progress Backup finished %1$d of %2$d apps backed up. Tap to learn more.