Convert BackupRestoreService to a WorkManager job
Co-authored-by: Jays2Kings <Jays2Kings@users.noreply.github.com>
This commit is contained in:
parent
14d1bcacc9
commit
cdc160afc2
@ -209,10 +209,6 @@
|
||||
android:name=".data.updater.AppUpdateService"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".data.backup.BackupRestoreService"
|
||||
android:exported="false" />
|
||||
|
||||
<service android:name=".extension.util.ExtensionInstallService"
|
||||
android:exported="false" />
|
||||
|
||||
|
@ -41,9 +41,9 @@ import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.util.collectAsState
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.BackupConst
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
||||
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
@ -93,7 +93,7 @@ object SettingsBackupScreen : SearchableSettings {
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
|
||||
)
|
||||
BackupCreatorJob.startNow(context, it, flag)
|
||||
BackupCreateJob.startNow(context, it, flag)
|
||||
}
|
||||
flag = 0
|
||||
}
|
||||
@ -119,7 +119,7 @@ object SettingsBackupScreen : SearchableSettings {
|
||||
subtitle = stringResource(R.string.pref_create_backup_summ),
|
||||
onClick = {
|
||||
scope.launch {
|
||||
if (!BackupCreatorJob.isManualJobRunning(context)) {
|
||||
if (!BackupCreateJob.isManualJobRunning(context)) {
|
||||
if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) {
|
||||
context.toast(R.string.restore_miui_warning, Toast.LENGTH_LONG)
|
||||
}
|
||||
@ -271,7 +271,7 @@ object SettingsBackupScreen : SearchableSettings {
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
BackupRestoreService.start(context, err.uri)
|
||||
BackupRestoreJob.start(context, err.uri)
|
||||
onDismissRequest()
|
||||
},
|
||||
) {
|
||||
@ -301,7 +301,7 @@ object SettingsBackupScreen : SearchableSettings {
|
||||
}
|
||||
|
||||
if (results.missingSources.isEmpty() && results.missingTrackers.isEmpty()) {
|
||||
BackupRestoreService.start(context, it)
|
||||
BackupRestoreJob.start(context, it)
|
||||
return@rememberLauncherForActivityResult
|
||||
}
|
||||
|
||||
@ -313,7 +313,7 @@ object SettingsBackupScreen : SearchableSettings {
|
||||
title = stringResource(R.string.pref_restore_backup),
|
||||
subtitle = stringResource(R.string.pref_restore_backup_summ),
|
||||
onClick = {
|
||||
if (!BackupRestoreService.isRunning(context)) {
|
||||
if (!BackupRestoreJob.isRunning(context)) {
|
||||
if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) {
|
||||
context.toast(R.string.restore_miui_warning, Toast.LENGTH_LONG)
|
||||
}
|
||||
@ -364,7 +364,7 @@ object SettingsBackupScreen : SearchableSettings {
|
||||
168 to stringResource(R.string.update_weekly),
|
||||
),
|
||||
onValueChanged = {
|
||||
BackupCreatorJob.setupTask(context, it)
|
||||
BackupCreateJob.setupTask(context, it)
|
||||
true
|
||||
},
|
||||
),
|
||||
|
@ -11,11 +11,11 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
|
||||
/**
|
||||
* Create a BitmapPainter from an drawable resource.
|
||||
*
|
||||
* > Only use this if [androidx.compose.ui.res.painterResource] doesn't work.
|
||||
* Create a BitmapPainter from a drawable resource.
|
||||
* Use this only if [androidx.compose.ui.res.painterResource] doesn't work.
|
||||
*
|
||||
* @param id the resource identifier
|
||||
*
|
||||
* @return the bitmap associated with the resource
|
||||
*/
|
||||
@Composable
|
||||
|
@ -8,7 +8,7 @@ import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
@ -57,7 +57,7 @@ object Migrations {
|
||||
|
||||
// Always set up background tasks to ensure they're running
|
||||
LibraryUpdateJob.setupTask(context)
|
||||
BackupCreatorJob.setupTask(context)
|
||||
BackupCreateJob.setupTask(context)
|
||||
|
||||
// Fresh install
|
||||
if (oldVersion == 0) {
|
||||
@ -99,7 +99,7 @@ object Migrations {
|
||||
if (oldVersion < 43) {
|
||||
// Restore jobs after migrating from Evernote's job scheduler to WorkManager.
|
||||
LibraryUpdateJob.setupTask(context)
|
||||
BackupCreatorJob.setupTask(context)
|
||||
BackupCreateJob.setupTask(context)
|
||||
}
|
||||
if (oldVersion < 44) {
|
||||
// Reset sorting preference if using removed sort by source
|
||||
@ -249,7 +249,7 @@ object Migrations {
|
||||
}
|
||||
}
|
||||
if (oldVersion < 76) {
|
||||
BackupCreatorJob.setupTask(context)
|
||||
BackupCreateJob.setupTask(context)
|
||||
}
|
||||
if (oldVersion < 77) {
|
||||
val oldReaderTap = prefs.getBoolean("reader_tap", false)
|
||||
@ -284,7 +284,7 @@ object Migrations {
|
||||
}
|
||||
if (backupPreferences.backupInterval().get() == 0) {
|
||||
backupPreferences.backupInterval().set(12)
|
||||
BackupCreatorJob.setupTask(context)
|
||||
BackupCreateJob.setupTask(context)
|
||||
}
|
||||
}
|
||||
if (oldVersion < 85) {
|
||||
|
@ -23,7 +23,7 @@ import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class BackupCreatorJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
class BackupCreateJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val notifier = BackupNotifier(context)
|
||||
@ -41,7 +41,6 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to run on foreground service" }
|
||||
}
|
||||
|
||||
context.notificationManager.notify(Notifications.ID_BACKUP_PROGRESS, notifier.showBackupProgress().build())
|
||||
return try {
|
||||
val location = BackupManager(context).createBackup(uri, flags, isAutoBackup)
|
||||
if (!isAutoBackup) notifier.showBackupComplete(UniFile.fromUri(context, location.toUri()))
|
||||
@ -70,7 +69,7 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
|
||||
val interval = prefInterval ?: backupPreferences.backupInterval().get()
|
||||
val workManager = WorkManager.getInstance(context)
|
||||
if (interval > 0) {
|
||||
val request = PeriodicWorkRequestBuilder<BackupCreatorJob>(
|
||||
val request = PeriodicWorkRequestBuilder<BackupCreateJob>(
|
||||
interval.toLong(),
|
||||
TimeUnit.HOURS,
|
||||
10,
|
||||
@ -92,7 +91,7 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
|
||||
LOCATION_URI_KEY to uri.toString(),
|
||||
BACKUP_FLAGS_KEY to flags,
|
||||
)
|
||||
val request = OneTimeWorkRequestBuilder<BackupCreatorJob>()
|
||||
val request = OneTimeWorkRequestBuilder<BackupCreateJob>()
|
||||
.addTag(TAG_MANUAL)
|
||||
.setInputData(inputData)
|
||||
.build()
|
@ -67,9 +67,7 @@ class BackupNotifier(private val context: Context) {
|
||||
setContentTitle(context.getString(R.string.backup_created))
|
||||
setContentText(unifile.filePath ?: unifile.name)
|
||||
|
||||
// Clear old actions if they exist
|
||||
clearActions()
|
||||
|
||||
addAction(
|
||||
R.drawable.ic_share_24dp,
|
||||
context.getString(R.string.action_share),
|
||||
@ -91,12 +89,10 @@ class BackupNotifier(private val context: Context) {
|
||||
setProgress(maxAmount, progress, false)
|
||||
setOnlyAlertOnce(true)
|
||||
|
||||
// Clear old actions if they exist
|
||||
clearActions()
|
||||
|
||||
addAction(
|
||||
R.drawable.ic_close_24dp,
|
||||
context.getString(R.string.action_stop),
|
||||
context.getString(R.string.action_cancel),
|
||||
NotificationReceiver.cancelRestorePendingBroadcast(context, Notifications.ID_RESTORE_PROGRESS),
|
||||
)
|
||||
}
|
||||
@ -132,9 +128,7 @@ class BackupNotifier(private val context: Context) {
|
||||
setContentTitle(context.getString(R.string.restore_completed))
|
||||
setContentText(context.resources.getQuantityString(R.plurals.restore_completed_message, errorCount, timeString, errorCount))
|
||||
|
||||
// Clear old actions if they exist
|
||||
clearActions()
|
||||
|
||||
if (errorCount > 0 && !path.isNullOrEmpty() && !file.isNullOrEmpty()) {
|
||||
val destFile = File(path, file)
|
||||
val uri = destFile.getUriCompat(context)
|
||||
|
@ -0,0 +1,87 @@
|
||||
package eu.kanade.tachiyomi.data.backup
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.system.logcat
|
||||
|
||||
class BackupRestoreJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val notifier = BackupNotifier(context)
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val uri = inputData.getString(LOCATION_URI_KEY)?.toUri()
|
||||
?: return Result.failure()
|
||||
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
} catch (e: IllegalStateException) {
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to run on foreground service" }
|
||||
}
|
||||
|
||||
return try {
|
||||
val restorer = BackupRestorer(context, notifier)
|
||||
restorer.restoreBackup(uri)
|
||||
Result.success()
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) {
|
||||
notifier.showRestoreError(context.getString(R.string.restoring_backup_canceled))
|
||||
Result.success()
|
||||
} else {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
notifier.showRestoreError(e.message)
|
||||
Result.failure()
|
||||
}
|
||||
} finally {
|
||||
context.notificationManager.cancel(Notifications.ID_RESTORE_PROGRESS)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
return ForegroundInfo(
|
||||
Notifications.ID_RESTORE_PROGRESS,
|
||||
notifier.showRestoreProgress().build(),
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun isRunning(context: Context): Boolean {
|
||||
val list = WorkManager.getInstance(context).getWorkInfosByTag(TAG).get()
|
||||
return list.find { it.state == WorkInfo.State.RUNNING } != null
|
||||
}
|
||||
|
||||
fun start(context: Context, uri: Uri) {
|
||||
val inputData = workDataOf(
|
||||
LOCATION_URI_KEY to uri.toString(),
|
||||
)
|
||||
val request = OneTimeWorkRequestBuilder<BackupRestoreJob>()
|
||||
.addTag(TAG)
|
||||
.setInputData(inputData)
|
||||
.build()
|
||||
WorkManager.getInstance(context)
|
||||
.enqueueUniqueWork(TAG, ExistingWorkPolicy.KEEP, request)
|
||||
}
|
||||
|
||||
fun stop(context: Context) {
|
||||
WorkManager.getInstance(context).cancelUniqueWork(TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val TAG = "BackupRestore"
|
||||
|
||||
private const val LOCATION_URI_KEY = "location_uri" // String
|
@ -1,141 +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 eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.acquireWakeLock
|
||||
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
|
||||
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.system.logcat
|
||||
|
||||
/**
|
||||
* Restores backup.
|
||||
*/
|
||||
class BackupRestoreService : Service() {
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* 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(BackupRestoreService::class.java)
|
||||
|
||||
/**
|
||||
* Starts a service to restore a backup from Json
|
||||
*
|
||||
* @param context context of application
|
||||
* @param uri path of Uri
|
||||
*/
|
||||
fun start(context: Context, uri: Uri) {
|
||||
if (isRunning(context)) return
|
||||
|
||||
val intent = Intent(context, BackupRestoreService::class.java).apply {
|
||||
putExtra(BackupConst.EXTRA_URI, uri)
|
||||
}
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the service.
|
||||
*
|
||||
* @param context the application context.
|
||||
*/
|
||||
fun stop(context: Context) {
|
||||
context.stopService(Intent(context, BackupRestoreService::class.java))
|
||||
|
||||
BackupNotifier(context).showRestoreError(context.getString(R.string.restoring_backup_canceled))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wake lock that will be held until the service is destroyed.
|
||||
*/
|
||||
private lateinit var wakeLock: PowerManager.WakeLock
|
||||
|
||||
private lateinit var scope: CoroutineScope
|
||||
private var restorer: BackupRestorer? = null
|
||||
private lateinit var notifier: BackupNotifier
|
||||
|
||||
override fun onCreate() {
|
||||
scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
notifier = BackupNotifier(this)
|
||||
wakeLock = acquireWakeLock(javaClass.name)
|
||||
|
||||
startForeground(Notifications.ID_RESTORE_PROGRESS, notifier.showRestoreProgress().build())
|
||||
}
|
||||
|
||||
override fun stopService(name: Intent?): Boolean {
|
||||
destroyJob()
|
||||
return super.stopService(name)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
destroyJob()
|
||||
}
|
||||
|
||||
private fun destroyJob() {
|
||||
restorer?.job?.cancel()
|
||||
scope.cancel()
|
||||
if (wakeLock.isHeld) {
|
||||
wakeLock.release()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method needs to be implemented, but it's not used/needed.
|
||||
*/
|
||||
override fun onBind(intent: Intent): IBinder? = null
|
||||
|
||||
/**
|
||||
* Method called when the service receives an intent.
|
||||
*
|
||||
* @param intent the start intent from.
|
||||
* @param flags the flags of the command.
|
||||
* @param startId the start id of this command.
|
||||
* @return the start value of the command.
|
||||
*/
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
val uri = intent?.getParcelableExtraCompat<Uri>(BackupConst.EXTRA_URI) ?: return START_NOT_STICKY
|
||||
|
||||
// Cancel any previous job if needed.
|
||||
restorer?.job?.cancel()
|
||||
|
||||
restorer = BackupRestorer(this, notifier)
|
||||
|
||||
val handler = CoroutineExceptionHandler { _, exception ->
|
||||
logcat(LogPriority.ERROR, exception)
|
||||
restorer?.writeErrorLog()
|
||||
|
||||
notifier.showRestoreError(exception.message)
|
||||
stopSelf(startId)
|
||||
}
|
||||
val job = scope.launch(handler) {
|
||||
if (restorer?.restoreBackup(uri) == false) {
|
||||
notifier.showRestoreError(getString(R.string.restoring_backup_canceled))
|
||||
}
|
||||
}
|
||||
job.invokeOnCompletion {
|
||||
stopSelf(startId)
|
||||
}
|
||||
restorer?.job = job
|
||||
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
}
|
@ -9,8 +9,8 @@ import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
||||
import eu.kanade.tachiyomi.util.BackupUtil
|
||||
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
||||
import kotlinx.coroutines.Job
|
||||
import okio.source
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.isActive
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.track.model.Track
|
||||
@ -24,8 +24,6 @@ class BackupRestorer(
|
||||
private val notifier: BackupNotifier,
|
||||
) {
|
||||
|
||||
var job: Job? = null
|
||||
|
||||
private var backupManager = BackupManager(context)
|
||||
|
||||
private var restoreAmount = 0
|
||||
@ -56,7 +54,7 @@ class BackupRestorer(
|
||||
return true
|
||||
}
|
||||
|
||||
fun writeErrorLog(): File {
|
||||
private fun writeErrorLog(): File {
|
||||
try {
|
||||
if (errors.isNotEmpty()) {
|
||||
val file = context.createFileInCacheDir("tachiyomi_restore.txt")
|
||||
@ -90,18 +88,18 @@ class BackupRestorer(
|
||||
val backupMaps = backup.backupBrokenSources.map { BackupSource(it.name, it.sourceId) } + backup.backupSources
|
||||
sourceMapping = backupMaps.associate { it.sourceId to it.name }
|
||||
|
||||
// Restore individual manga
|
||||
backup.backupManga.forEach {
|
||||
if (job?.isActive != true) {
|
||||
return false
|
||||
return coroutineScope {
|
||||
// Restore individual manga
|
||||
backup.backupManga.forEach {
|
||||
if (!isActive) {
|
||||
return@coroutineScope false
|
||||
}
|
||||
|
||||
restoreManga(it, backup.backupCategories)
|
||||
}
|
||||
|
||||
restoreManga(it, backup.backupCategories)
|
||||
// TODO: optionally trigger online library + tracker update
|
||||
true
|
||||
}
|
||||
|
||||
// TODO: optionally trigger online library + tracker update
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private suspend fun restoreCategories(backupCategories: List<BackupCategory>) {
|
||||
|
@ -6,10 +6,9 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.data.updater.AppUpdateService
|
||||
@ -82,10 +81,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
"application/x-protobuf+gzip",
|
||||
intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1),
|
||||
)
|
||||
ACTION_CANCEL_RESTORE -> cancelRestore(
|
||||
context,
|
||||
intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1),
|
||||
)
|
||||
ACTION_CANCEL_RESTORE -> cancelRestore(context)
|
||||
// Cancel library update and dismiss notification
|
||||
ACTION_CANCEL_LIBRARY_UPDATE -> cancelLibraryUpdate(context)
|
||||
// Cancel downloading app update
|
||||
@ -206,11 +202,9 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
* Method called when user wants to stop a backup restore job.
|
||||
*
|
||||
* @param context context of application
|
||||
* @param notificationId id of notification
|
||||
*/
|
||||
private fun cancelRestore(context: Context, notificationId: Int) {
|
||||
BackupRestoreService.stop(context)
|
||||
ContextCompat.getMainExecutor(context).execute { dismissNotification(context, notificationId) }
|
||||
private fun cancelRestore(context: Context) {
|
||||
BackupRestoreJob.stop(context)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,7 +86,6 @@
|
||||
<string name="delete_category">Delete category</string>
|
||||
<string name="action_edit_cover">Edit cover</string>
|
||||
<string name="action_view_chapters">View chapters</string>
|
||||
<string name="action_stop">Stop</string>
|
||||
<string name="action_pause">Pause</string>
|
||||
<string name="action_previous_chapter">Previous chapter</string>
|
||||
<string name="action_next_chapter">Next chapter</string>
|
||||
|
Loading…
Reference in New Issue
Block a user