Use WorkInfo for determining if a backup is already running

Backup and restore is not possible when a backup is running. We used to check notifications for this, but now can use WorkManager's WorkInfo which should be more reliable.

Also, we used to prevent the "Backup now" action when app backup was disabled. But the user may want to do a storage backup. This is now possible.
This commit is contained in:
Torsten Grote 2024-02-22 13:09:48 -03:00
parent 0c1898c198
commit 8a870d8942
No known key found for this signature in database
GPG key ID: 3E5F77D92CF891FF
4 changed files with 26 additions and 33 deletions

View file

@ -141,10 +141,17 @@ class SettingsFragment : PreferenceFragmentCompat() {
super.onViewCreated(view, savedInstanceState)
viewModel.lastBackupTime.observe(viewLifecycleOwner) { time ->
setAppBackupStatusSummary(time, viewModel.nextScheduleTimeMillis.value)
setAppBackupStatusSummary(
lastBackupInMillis = time,
nextScheduleTimeMillis = viewModel.appBackupWorkInfo.value?.nextScheduleTimeMillis,
)
}
viewModel.nextScheduleTimeMillis.observe(viewLifecycleOwner) { time ->
setAppBackupStatusSummary(viewModel.lastBackupTime.value, time)
viewModel.appBackupWorkInfo.observe(viewLifecycleOwner) { workInfo ->
viewModel.onWorkerStateChanged()
setAppBackupStatusSummary(
lastBackupInMillis = viewModel.lastBackupTime.value,
nextScheduleTimeMillis = workInfo?.nextScheduleTimeMillis,
)
}
val backupFiles: Preference = findPreference("backup_files")!!
@ -165,7 +172,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
setAutoRestoreState()
setAppBackupStatusSummary(
lastBackupInMillis = viewModel.lastBackupTime.value,
nextScheduleTimeMillis = viewModel.nextScheduleTimeMillis.value,
nextScheduleTimeMillis = viewModel.appBackupWorkInfo.value?.nextScheduleTimeMillis,
)
}
@ -273,11 +280,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
if (sb.isNotEmpty()) sb.append("\n")
// set time of next backup
when (nextScheduleTimeMillis) {
-1L -> {
val text = getString(R.string.settings_backup_last_backup_never)
sb.append(getString(R.string.settings_backup_status_next_backup, text))
}
Long.MAX_VALUE -> {
val text = if (backupManager.isBackupEnabled && storage?.isUsb != true) {
getString(R.string.notification_title)

View file

@ -26,6 +26,7 @@ import androidx.lifecycle.map
import androidx.lifecycle.switchMap
import androidx.lifecycle.viewModelScope
import androidx.recyclerview.widget.DiffUtil.calculateDiff
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.crypto.KeyManager
@ -72,10 +73,9 @@ internal class SettingsViewModel(
val backupPossible: LiveData<Boolean> = mBackupPossible
internal val lastBackupTime = metadataManager.lastBackupTime
val nextScheduleTimeMillis =
internal val appBackupWorkInfo =
workManager.getWorkInfosForUniqueWorkLiveData(UNIQUE_WORK_NAME).map {
if (it.size > 0) it[0].nextScheduleTimeMillis
else -1L
it.getOrNull(0)
}
private val mAppStatusList = lastBackupTime.switchMap {
@ -140,6 +140,14 @@ internal class SettingsViewModel(
onStoragePropertiesChanged()
}
fun onWorkerStateChanged() {
viewModelScope.launch(Dispatchers.IO) {
val canDo = settingsManager.canDoBackupNow() &&
appBackupWorkInfo.value?.state != WorkInfo.State.RUNNING
mBackupPossible.postValue(canDo)
}
}
private fun onStoragePropertiesChanged() {
val storage = settingsManager.getStorage() ?: return
@ -165,11 +173,8 @@ internal class SettingsViewModel(
connectivityManager?.registerNetworkCallback(request, networkCallback)
networkCallback.registered = true
}
viewModelScope.launch(Dispatchers.IO) {
val canDo = settingsManager.canDoBackupNow()
mBackupPossible.postValue(canDo)
}
// update whether we can do backups right now or not
onWorkerStateChanged()
}
override fun onCleared() {
@ -181,12 +186,7 @@ internal class SettingsViewModel(
}
internal fun backupNow() {
// maybe replace the check below with one that checks if our transport service is running
if (notificationManager.hasActiveBackupNotifications()) {
Toast.makeText(app, R.string.notification_backup_already_running, LENGTH_LONG).show()
} else if (!backupManager.isBackupEnabled) {
Toast.makeText(app, R.string.notification_backup_disabled, LENGTH_LONG).show()
} else viewModelScope.launch(Dispatchers.IO) {
viewModelScope.launch(Dispatchers.IO) {
if (settingsManager.isStorageBackupEnabled()) {
val i = Intent(app, StorageBackupService::class.java)
// this starts an app backup afterwards

View file

@ -23,6 +23,7 @@ force running with:
adb shell cmd jobscheduler run -f com.stevesoltys.seedvault 0
*/
internal class StorageBackupJobService : BackupJobService(StorageBackupService::class.java)
internal class StorageBackupService : BackupService() {

View file

@ -192,16 +192,6 @@ internal class BackupNotificationManager(private val context: Context) {
nm.notify(NOTIFICATION_ID_SUCCESS, notification)
}
fun hasActiveBackupNotifications(): Boolean {
nm.activeNotifications.forEach {
if (it.packageName == context.packageName) {
if (it.id == NOTIFICATION_ID_BACKGROUND) return true
if (it.id == NOTIFICATION_ID_OBSERVER) return it.isOngoing
}
}
return false
}
@SuppressLint("RestrictedApi")
fun onBackupError() {
val intent = Intent(context, SettingsActivity::class.java)