Browse Source

Run periodic backups without launching services

inorichi 7 years ago
parent
commit
fa4d61eaf0

+ 3 - 102
app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt

@@ -4,17 +4,8 @@ import android.app.IntentService
 import android.content.Context
 import android.content.Intent
 import android.net.Uri
-import com.github.salomonbrys.kotson.set
 import com.google.gson.JsonArray
-import com.google.gson.JsonObject
-import com.hippo.unifile.UniFile
-import eu.kanade.tachiyomi.data.backup.models.Backup
-import eu.kanade.tachiyomi.data.backup.models.Backup.CATEGORIES
-import eu.kanade.tachiyomi.data.backup.models.Backup.MANGAS
-import eu.kanade.tachiyomi.data.backup.models.Backup.VERSION
 import eu.kanade.tachiyomi.data.database.models.Manga
-import eu.kanade.tachiyomi.util.sendLocalBroadcast
-import timber.log.Timber
 import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
 
 /**
@@ -26,8 +17,6 @@ class BackupCreateService : IntentService(NAME) {
         // Name of class
         private const val NAME = "BackupCreateService"
 
-        // Backup called from job
-        private const val EXTRA_IS_JOB = "$ID.$NAME.EXTRA_IS_JOB"
         // Options for backup
         private const val EXTRA_FLAGS = "$ID.$NAME.EXTRA_FLAGS"
 
@@ -48,12 +37,10 @@ class BackupCreateService : IntentService(NAME) {
          * @param context context of application
          * @param uri path of Uri
          * @param flags determines what to backup
-         * @param isJob backup called from job
          */
-        fun makeBackup(context: Context, uri: Uri, flags: Int, isJob: Boolean = false) {
+        fun makeBackup(context: Context, uri: Uri, flags: Int) {
             val intent = Intent(context, BackupCreateService::class.java).apply {
                 putExtra(BackupConst.EXTRA_URI, uri)
-                putExtra(EXTRA_IS_JOB, isJob)
                 putExtra(EXTRA_FLAGS, flags)
             }
             context.startService(intent)
@@ -68,95 +55,9 @@ class BackupCreateService : IntentService(NAME) {
 
         // Get values
         val uri = intent.getParcelableExtra<Uri>(BackupConst.EXTRA_URI)
-        val isJob = intent.getBooleanExtra(EXTRA_IS_JOB, false)
         val flags = intent.getIntExtra(EXTRA_FLAGS, 0)
         // Create backup
-        createBackupFromApp(uri, flags, isJob)
+        backupManager.createBackup(uri, flags, false)
     }
 
-    /**
-     * Create backup Json file from database
-     *
-     * @param uri path of Uri
-     * @param isJob backup called from job
-     */
-    private fun createBackupFromApp(uri: Uri, flags: Int, isJob: Boolean) {
-        // Create root object
-        val root = JsonObject()
-
-        // Create manga array
-        val mangaEntries = JsonArray()
-
-        // Create category array
-        val categoryEntries = JsonArray()
-
-        // Add value's to root
-        root[VERSION] = Backup.CURRENT_VERSION
-        root[MANGAS] = mangaEntries
-        root[CATEGORIES] = categoryEntries
-
-        backupManager.databaseHelper.inTransaction {
-            // Get manga from database
-            val mangas = backupManager.getFavoriteManga()
-
-            // Backup library manga and its dependencies
-            mangas.forEach { manga ->
-                mangaEntries.add(backupManager.backupMangaObject(manga, flags))
-            }
-
-            // Backup categories
-            if ((flags and BACKUP_CATEGORY_MASK) == BACKUP_CATEGORY) {
-                backupManager.backupCategories(categoryEntries)
-            }
-        }
-
-        try {
-            // When BackupCreatorJob
-            if (isJob) {
-                // Get dir of file and create
-                var dir = UniFile.fromUri(this, uri)
-                dir = dir.createDirectory("automatic")
-
-                // Delete older backups
-                val numberOfBackups = backupManager.numberOfBackups()
-                val backupRegex = Regex("""tachiyomi_\d+-\d+-\d+_\d+-\d+.json""")
-                dir.listFiles { _, filename -> backupRegex.matches(filename) }
-                        .orEmpty()
-                        .sortedByDescending { it.name }
-                        .drop(numberOfBackups - 1)
-                        .forEach { it.delete() }
-
-                // Create new file to place backup
-                val newFile = dir.createFile(Backup.getDefaultFilename())
-                        ?: throw Exception("Couldn't create backup file")
-
-                newFile.openOutputStream().bufferedWriter().use {
-                    backupManager.parser.toJson(root, it)
-                }
-            } else {
-                val file = UniFile.fromUri(this, uri)
-                        ?: throw Exception("Couldn't create backup file")
-                file.openOutputStream().bufferedWriter().use {
-                    backupManager.parser.toJson(root, it)
-                }
-
-                // Show completed dialog
-                val intent = Intent(BackupConst.INTENT_FILTER).apply {
-                    putExtra(BackupConst.ACTION, BackupConst.ACTION_BACKUP_COMPLETED_DIALOG)
-                    putExtra(BackupConst.EXTRA_URI, file.uri.toString())
-                }
-                sendLocalBroadcast(intent)
-            }
-        } catch (e: Exception) {
-            Timber.e(e)
-            if (!isJob) {
-                // Show error dialog
-                val intent = Intent(BackupConst.INTENT_FILTER).apply {
-                    putExtra(BackupConst.ACTION, BackupConst.ACTION_ERROR_BACKUP_DIALOG)
-                    putExtra(BackupConst.EXTRA_ERROR_MESSAGE, e.message)
-                }
-                sendLocalBroadcast(intent)
-            }
-        }
-    }
-}
+}

+ 3 - 2
app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt

@@ -13,9 +13,10 @@ class BackupCreatorJob : Job() {
 
     override fun onRunJob(params: Params): Result {
         val preferences = Injekt.get<PreferencesHelper>()
+        val backupManager = Injekt.get<BackupManager>()
         val uri = Uri.parse(preferences.backupsDirectory().getOrDefault())
         val flags = BackupCreateService.BACKUP_ALL
-        BackupCreateService.makeBackup(context, uri, flags, true)
+        backupManager.createBackup(uri, flags, true)
         return Result.SUCCESS
     }
 
@@ -38,4 +39,4 @@ class BackupCreatorJob : Job() {
             JobManager.instance().cancelAllForTag(TAG)
         }
     }
-}
+}

+ 92 - 0
app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt

@@ -1,8 +1,11 @@
 package eu.kanade.tachiyomi.data.backup
 
 import android.content.Context
+import android.content.Intent
+import android.net.Uri
 import com.github.salomonbrys.kotson.*
 import com.google.gson.*
+import com.hippo.unifile.UniFile
 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
@@ -11,6 +14,7 @@ import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_HIST
 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.models.Backup
 import eu.kanade.tachiyomi.data.backup.models.Backup.CATEGORIES
 import eu.kanade.tachiyomi.data.backup.models.Backup.CHAPTERS
 import eu.kanade.tachiyomi.data.backup.models.Backup.CURRENT_VERSION
@@ -26,8 +30,10 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.source.Source
 import eu.kanade.tachiyomi.source.SourceManager
+import eu.kanade.tachiyomi.util.sendLocalBroadcast
 import eu.kanade.tachiyomi.util.syncChaptersWithSource
 import rx.Observable
+import timber.log.Timber
 import uy.kohesive.injekt.injectLazy
 
 class BackupManager(val context: Context, version: Int = CURRENT_VERSION) {
@@ -85,6 +91,92 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) {
         else -> throw Exception("Json version unknown")
     }
 
+    /**
+     * Create backup Json file from database
+     *
+     * @param uri path of Uri
+     * @param isJob backup called from job
+     */
+    fun createBackup(uri: Uri, flags: Int, isJob: Boolean) {
+        // Create root object
+        val root = JsonObject()
+
+        // Create manga array
+        val mangaEntries = JsonArray()
+
+        // Create category array
+        val categoryEntries = JsonArray()
+
+        // Add value's to root
+        root[Backup.VERSION] = Backup.CURRENT_VERSION
+        root[Backup.MANGAS] = mangaEntries
+        root[CATEGORIES] = categoryEntries
+
+        databaseHelper.inTransaction {
+            // Get manga from database
+            val mangas = getFavoriteManga()
+
+            // Backup library manga and its dependencies
+            mangas.forEach { manga ->
+                mangaEntries.add(backupMangaObject(manga, flags))
+            }
+
+            // Backup categories
+            if ((flags and BACKUP_CATEGORY_MASK) == BACKUP_CATEGORY) {
+                backupCategories(categoryEntries)
+            }
+        }
+
+        try {
+            // When BackupCreatorJob
+            if (isJob) {
+                // Get dir of file and create
+                var dir = UniFile.fromUri(context, uri)
+                dir = dir.createDirectory("automatic")
+
+                // Delete older backups
+                val numberOfBackups = numberOfBackups()
+                val backupRegex = Regex("""tachiyomi_\d+-\d+-\d+_\d+-\d+.json""")
+                dir.listFiles { _, filename -> backupRegex.matches(filename) }
+                        .orEmpty()
+                        .sortedByDescending { it.name }
+                        .drop(numberOfBackups - 1)
+                        .forEach { it.delete() }
+
+                // Create new file to place backup
+                val newFile = dir.createFile(Backup.getDefaultFilename())
+                        ?: throw Exception("Couldn't create backup file")
+
+                newFile.openOutputStream().bufferedWriter().use {
+                    parser.toJson(root, it)
+                }
+            } else {
+                val file = UniFile.fromUri(context, uri)
+                        ?: throw Exception("Couldn't create backup file")
+                file.openOutputStream().bufferedWriter().use {
+                    parser.toJson(root, it)
+                }
+
+                // Show completed dialog
+                val intent = Intent(BackupConst.INTENT_FILTER).apply {
+                    putExtra(BackupConst.ACTION, BackupConst.ACTION_BACKUP_COMPLETED_DIALOG)
+                    putExtra(BackupConst.EXTRA_URI, file.uri.toString())
+                }
+                context.sendLocalBroadcast(intent)
+            }
+        } catch (e: Exception) {
+            Timber.e(e)
+            if (!isJob) {
+                // Show error dialog
+                val intent = Intent(BackupConst.INTENT_FILTER).apply {
+                    putExtra(BackupConst.ACTION, BackupConst.ACTION_ERROR_BACKUP_DIALOG)
+                    putExtra(BackupConst.EXTRA_ERROR_MESSAGE, e.message)
+                }
+                context.sendLocalBroadcast(intent)
+            }
+        }
+    }
+
     /**
      * Backup the categories of library
      *

+ 2 - 11
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt

@@ -3,11 +3,7 @@ package eu.kanade.tachiyomi.ui.setting
 import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
 import android.app.Activity
 import android.app.Dialog
-import android.content.ActivityNotFoundException
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
+import android.content.*
 import android.net.Uri
 import android.os.Build
 import android.os.Bundle
@@ -15,22 +11,17 @@ import android.support.v7.preference.PreferenceScreen
 import android.view.View
 import com.afollestad.materialdialogs.MaterialDialog
 import com.hippo.unifile.UniFile
-import com.nononsenseapps.filepicker.FilePickerActivity
 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.models.Backup
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.preference.getOrDefault
 import eu.kanade.tachiyomi.ui.base.controller.DialogController
 import eu.kanade.tachiyomi.ui.base.controller.popControllerWithTag
 import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
 import eu.kanade.tachiyomi.util.*
-import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
-import uy.kohesive.injekt.Injekt
-import uy.kohesive.injekt.api.get
 import java.io.File
 import java.util.concurrent.TimeUnit
 import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
@@ -464,4 +455,4 @@ class SettingsBackupController : SettingsController() {
         const val TAG_RESTORING_BACKUP_DIALOG = "RestoringBackupDialog"
     }
 
-}
+}