From d53bb4c337da6df807b43295d2991e8af9015098 Mon Sep 17 00:00:00 2001
From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
Date: Fri, 4 Mar 2022 10:15:49 +0700
Subject: [PATCH] Use existing worker for manual backup creation (#6718)
* Use existing worker for manual backup creation
This will show the "creating backup" notification when auto backup is
running. Complete or error notification will continue to be shown only on
manual job.
* Make sure disabling auto backup don't cancel running manual backup job
---
app/src/main/AndroidManifest.xml | 4 -
.../data/backup/AbstractBackupManager.kt | 2 +-
.../tachiyomi/data/backup/BackupConst.kt | 11 ++
.../data/backup/BackupCreateService.kt | 114 ------------------
.../tachiyomi/data/backup/BackupCreatorJob.kt | 51 +++++++-
.../data/backup/full/FullBackupManager.kt | 22 ++--
.../data/backup/legacy/LegacyBackupManager.kt | 4 +-
.../ui/setting/SettingsBackupController.kt | 17 +--
8 files changed, 77 insertions(+), 148 deletions(-)
delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index edc1336552..f656c6fe05 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -181,10 +181,6 @@
android:name=".data.updater.AppUpdateService"
android:exported="false" />
-
-
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt
index de637c6e52..d23ce07309 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt
@@ -21,7 +21,7 @@ abstract class AbstractBackupManager(protected val context: Context) {
internal val trackManager: TrackManager by injectLazy()
protected val preferences: PreferencesHelper by injectLazy()
- abstract fun createBackup(uri: Uri, flags: Int, isJob: Boolean): String
+ abstract fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String
/**
* Returns manga
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt
index d168e2c3d9..e185508d1d 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt
@@ -11,4 +11,15 @@ object BackupConst {
const val BACKUP_TYPE_LEGACY = 0
const val BACKUP_TYPE_FULL = 1
+
+ // Filter options
+ internal const val BACKUP_CATEGORY = 0x1
+ internal const val BACKUP_CATEGORY_MASK = 0x1
+ internal const val BACKUP_CHAPTER = 0x2
+ internal const val BACKUP_CHAPTER_MASK = 0x2
+ internal const val BACKUP_HISTORY = 0x4
+ internal const val BACKUP_HISTORY_MASK = 0x4
+ internal const val BACKUP_TRACK = 0x8
+ internal const val BACKUP_TRACK_MASK = 0x8
+ internal const val BACKUP_ALL = 0xF
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt
deleted file mode 100644
index 9a7dffcae1..0000000000
--- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-package eu.kanade.tachiyomi.data.backup
-
-import android.app.Service
-import android.content.Context
-import android.content.Intent
-import android.net.Uri
-import android.os.IBinder
-import android.os.PowerManager
-import androidx.core.content.ContextCompat
-import androidx.core.net.toUri
-import com.hippo.unifile.UniFile
-import eu.kanade.tachiyomi.data.backup.full.FullBackupManager
-import eu.kanade.tachiyomi.data.notification.Notifications
-import eu.kanade.tachiyomi.util.system.acquireWakeLock
-import eu.kanade.tachiyomi.util.system.isServiceRunning
-
-/**
- * Service for backing up library information to a JSON file.
- */
-class BackupCreateService : Service() {
-
- companion object {
- // Filter options
- internal const val BACKUP_CATEGORY = 0x1
- internal const val BACKUP_CATEGORY_MASK = 0x1
- internal const val BACKUP_CHAPTER = 0x2
- internal const val BACKUP_CHAPTER_MASK = 0x2
- internal const val BACKUP_HISTORY = 0x4
- internal const val BACKUP_HISTORY_MASK = 0x4
- internal const val BACKUP_TRACK = 0x8
- internal const val BACKUP_TRACK_MASK = 0x8
- internal const val BACKUP_ALL = 0xF
-
- /**
- * Returns the status of the service.
- *
- * @param context the application context.
- * @return true if the service is running, false otherwise.
- */
- fun isRunning(context: Context): Boolean =
- context.isServiceRunning(BackupCreateService::class.java)
-
- /**
- * Make a backup from library
- *
- * @param context context of application
- * @param uri path of Uri
- * @param flags determines what to backup
- */
- fun start(context: Context, uri: Uri, flags: Int) {
- if (!isRunning(context)) {
- val intent = Intent(context, BackupCreateService::class.java).apply {
- putExtra(BackupConst.EXTRA_URI, uri)
- putExtra(BackupConst.EXTRA_FLAGS, flags)
- }
- ContextCompat.startForegroundService(context, intent)
- }
- }
- }
-
- /**
- * Wake lock that will be held until the service is destroyed.
- */
- private lateinit var wakeLock: PowerManager.WakeLock
-
- private lateinit var notifier: BackupNotifier
-
- override fun onCreate() {
- super.onCreate()
-
- notifier = BackupNotifier(this)
- wakeLock = acquireWakeLock(javaClass.name)
-
- startForeground(Notifications.ID_BACKUP_PROGRESS, notifier.showBackupProgress().build())
- }
-
- override fun stopService(name: Intent?): Boolean {
- destroyJob()
- return super.stopService(name)
- }
-
- override fun onDestroy() {
- destroyJob()
- super.onDestroy()
- }
-
- private fun destroyJob() {
- if (wakeLock.isHeld) {
- wakeLock.release()
- }
- }
-
- /**
- * This method needs to be implemented, but it's not used/needed.
- */
- override fun onBind(intent: Intent): IBinder? = null
-
- override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
- if (intent == null) return START_NOT_STICKY
-
- try {
- val uri = intent.getParcelableExtra(BackupConst.EXTRA_URI)!!
- val backupFlags = intent.getIntExtra(BackupConst.EXTRA_FLAGS, 0)
- val backupFileUri = FullBackupManager(this).createBackup(uri, backupFlags, false)?.toUri()
- val unifile = UniFile.fromUri(this, backupFileUri)
- notifier.showBackupComplete(unifile)
- } catch (e: Exception) {
- notifier.showBackupError(e.message)
- }
-
- stopSelf(startId)
- return START_NOT_STICKY
- }
-}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt
index bfaa407aad..6d6300df1a 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt
@@ -1,15 +1,23 @@
package eu.kanade.tachiyomi.data.backup
import android.content.Context
+import android.net.Uri
import androidx.core.net.toUri
import androidx.work.ExistingPeriodicWorkPolicy
+import androidx.work.ExistingWorkPolicy
+import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
+import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
+import androidx.work.workDataOf
+import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.backup.full.FullBackupManager
+import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.util.system.logcat
+import eu.kanade.tachiyomi.util.system.notificationManager
import logcat.LogPriority
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -20,23 +28,42 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
override fun doWork(): Result {
val preferences = Injekt.get()
- val uri = preferences.backupsDirectory().get().toUri()
- val flags = BackupCreateService.BACKUP_ALL
+ val notifier = BackupNotifier(context)
+ val uri = inputData.getString(LOCATION_URI_KEY)?.let { Uri.parse(it) }
+ ?: preferences.backupsDirectory().get().toUri()
+ val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupConst.BACKUP_ALL)
+ val isAutoBackup = inputData.getBoolean(IS_AUTO_BACKUP_KEY, false)
+
+ context.notificationManager.notify(Notifications.ID_BACKUP_PROGRESS, notifier.showBackupProgress().build())
return try {
- FullBackupManager(context).createBackup(uri, flags, true)
+ val location = FullBackupManager(context).createBackup(uri, flags, isAutoBackup)
+ if (!isAutoBackup) notifier.showBackupComplete(UniFile.fromUri(context, location.toUri()))
Result.success()
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
+ if (!isAutoBackup) notifier.showBackupError(e.message)
Result.failure()
+ } finally {
+ context.notificationManager.cancel(Notifications.ID_BACKUP_PROGRESS)
}
}
companion object {
private const val TAG = "BackupCreator"
+ private const val IS_AUTO_BACKUP_KEY = "is_auto_backup" // Boolean
+ private const val LOCATION_URI_KEY = "location_uri" // String
+ private const val BACKUP_FLAGS_KEY = "backup_flags" // Int
+
+ fun isManualJobRunning(context: Context): Boolean {
+ val list = WorkManager.getInstance(context).getWorkInfosByTag(TAG).get()
+ return list.find { it.state == WorkInfo.State.RUNNING } != null
+ }
+
fun setupTask(context: Context, prefInterval: Int? = null) {
val preferences = Injekt.get()
val interval = prefInterval ?: preferences.backupInterval().get()
+ val workManager = WorkManager.getInstance(context)
if (interval > 0) {
val request = PeriodicWorkRequestBuilder(
interval.toLong(),
@@ -45,12 +72,26 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
TimeUnit.MINUTES
)
.addTag(TAG)
+ .setInputData(workDataOf(IS_AUTO_BACKUP_KEY to true))
.build()
- WorkManager.getInstance(context).enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.REPLACE, request)
+ workManager.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.REPLACE, request)
} else {
- WorkManager.getInstance(context).cancelAllWorkByTag(TAG)
+ workManager.cancelUniqueWork(TAG)
}
}
+
+ fun startNow(context: Context, uri: Uri, flags: Int) {
+ val inputData = workDataOf(
+ IS_AUTO_BACKUP_KEY to false,
+ LOCATION_URI_KEY to uri.toString(),
+ BACKUP_FLAGS_KEY to flags
+ )
+ val request = OneTimeWorkRequestBuilder()
+ .addTag(TAG)
+ .setInputData(inputData)
+ .build()
+ WorkManager.getInstance(context).enqueueUniqueWork("$TAG:manual", ExistingWorkPolicy.KEEP, request)
+ }
}
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt
index 652471c331..134c034ff0 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt
@@ -4,14 +4,14 @@ import android.content.Context
import android.net.Uri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.backup.AbstractBackupManager
-import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY
-import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY_MASK
-import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CHAPTER
-import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CHAPTER_MASK
-import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_HISTORY
-import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_HISTORY_MASK
-import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_TRACK
-import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_TRACK_MASK
+import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY
+import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY_MASK
+import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CHAPTER
+import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CHAPTER_MASK
+import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_HISTORY
+import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_HISTORY_MASK
+import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK
+import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK_MASK
import eu.kanade.tachiyomi.data.backup.full.models.Backup
import eu.kanade.tachiyomi.data.backup.full.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.full.models.BackupChapter
@@ -43,9 +43,9 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
* Create backup Json file from database
*
* @param uri path of Uri
- * @param isJob backup called from job
+ * @param isAutoBackup backup called from scheduled backup job
*/
- override fun createBackup(uri: Uri, flags: Int, isJob: Boolean): String {
+ override fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String {
// Create root object
var backup: Backup? = null
@@ -63,7 +63,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
var file: UniFile? = null
try {
file = (
- if (isJob) {
+ if (isAutoBackup) {
// Get dir of file and create
var dir = UniFile.fromUri(context, uri)
dir = dir.createDirectory("automatic")
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupManager.kt
index d03e91a7af..4984b242ce 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupManager.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupManager.kt
@@ -55,9 +55,9 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab
* Create backup Json file from database
*
* @param uri path of Uri
- * @param isJob backup called from job
+ * @param isAutoBackup backup called from scheduled backup job
*/
- override fun createBackup(uri: Uri, flags: Int, isJob: Boolean) =
+ override fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean) =
throw IllegalStateException("Legacy backup creation is not supported")
fun restoreMangaNoFetch(manga: Manga, dbManga: Manga) {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt
index a6d1353605..e1fde8e417 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt
@@ -20,7 +20,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupConst
-import eu.kanade.tachiyomi.data.backup.BackupCreateService
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
import eu.kanade.tachiyomi.data.backup.ValidatorParseException
@@ -70,7 +69,7 @@ class SettingsBackupController : SettingsController() {
context.toast(R.string.restore_miui_warning, Toast.LENGTH_LONG)
}
- if (!BackupCreateService.isRunning(context)) {
+ if (!BackupCreatorJob.isManualJobRunning(context)) {
val ctrl = CreateBackupDialog()
ctrl.targetController = this@SettingsBackupController
ctrl.showDialog(router)
@@ -197,11 +196,7 @@ class SettingsBackupController : SettingsController() {
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
activity.contentResolver.takePersistableUriPermission(uri, flags)
- BackupCreateService.start(
- activity,
- uri,
- backupFlags,
- )
+ BackupCreatorJob.startNow(activity, uri, backupFlags)
}
CODE_BACKUP_RESTORE -> {
RestoreBackupDialog(uri).showDialog(router)
@@ -252,10 +247,10 @@ class SettingsBackupController : SettingsController() {
selected.forEachIndexed { i, checked ->
if (checked) {
when (i) {
- 1 -> flags = flags or BackupCreateService.BACKUP_CATEGORY
- 2 -> flags = flags or BackupCreateService.BACKUP_CHAPTER
- 3 -> flags = flags or BackupCreateService.BACKUP_TRACK
- 4 -> flags = flags or BackupCreateService.BACKUP_HISTORY
+ 1 -> flags = flags or BackupConst.BACKUP_CATEGORY
+ 2 -> flags = flags or BackupConst.BACKUP_CHAPTER
+ 3 -> flags = flags or BackupConst.BACKUP_TRACK
+ 4 -> flags = flags or BackupConst.BACKUP_HISTORY
}
}
}