Schedule workers only on demand
This commit is contained in:
@@ -104,6 +104,7 @@ dependencies {
|
||||
//noinspection LifecycleAnnotationProcessorWithJava8
|
||||
kapt 'androidx.lifecycle:lifecycle-compiler:2.6.1'
|
||||
|
||||
// TODO https://issuetracker.google.com/issues/254846063
|
||||
implementation 'androidx.work:work-runtime-ktx:2.8.1'
|
||||
//noinspection GradleDependency
|
||||
implementation('com.google.guava:guava:32.0.0-android') {
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.koitharu.kotatsu.local.data.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.local.data.PagesCache
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.settings.work.WorkScheduleManager
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltAndroidApp
|
||||
@@ -51,6 +52,9 @@ class KotatsuApp : Application(), Configuration.Provider {
|
||||
@Inject
|
||||
lateinit var appValidator: AppValidator
|
||||
|
||||
@Inject
|
||||
lateinit var workScheduleManager: WorkScheduleManager
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
ACRA.errorReporter.putCustomData("isOriginalApp", appValidator.isOriginalApp.toString())
|
||||
@@ -63,6 +67,7 @@ class KotatsuApp : Application(), Configuration.Provider {
|
||||
processLifecycleScope.launch(Dispatchers.Default) {
|
||||
setupDatabaseObservers()
|
||||
}
|
||||
workScheduleManager.init()
|
||||
WorkServiceStopHelper(applicationContext).setup()
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,10 @@ class WorkManagerHelper(
|
||||
return workManagerImpl.getWorkInfoById(id).await()
|
||||
}
|
||||
|
||||
suspend fun getUniqueWorkInfoByName(name: String): List<WorkInfo> {
|
||||
return workManagerImpl.getWorkInfosForUniqueWork(name).await().orEmpty()
|
||||
}
|
||||
|
||||
suspend fun updateWork(request: WorkRequest): WorkManager.UpdateResult {
|
||||
return workManagerImpl.updateWork(request).await()
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.await
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import org.koitharu.kotatsu.local.data.LocalMangaRepository
|
||||
@@ -33,7 +34,7 @@ class LocalStorageCleanupWorker @AssistedInject constructor(
|
||||
|
||||
private const val TAG = "cleanup"
|
||||
|
||||
fun enqueue(context: Context) {
|
||||
suspend fun enqueue(context: Context) {
|
||||
val constraints = Constraints.Builder()
|
||||
.setRequiresBatteryNotLow(true)
|
||||
.build()
|
||||
@@ -42,7 +43,7 @@ class LocalStorageCleanupWorker @AssistedInject constructor(
|
||||
.addTag(TAG)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, 1, TimeUnit.MINUTES)
|
||||
.build()
|
||||
WorkManager.getInstance(context).enqueueUniqueWork(TAG, ExistingWorkPolicy.KEEP, request)
|
||||
WorkManager.getInstance(context).enqueueUniqueWork(TAG, ExistingWorkPolicy.KEEP, request).await()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +69,6 @@ import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel
|
||||
import org.koitharu.kotatsu.settings.newsources.NewSourcesDialogFragment
|
||||
import org.koitharu.kotatsu.settings.onboard.OnboardDialogFragment
|
||||
import org.koitharu.kotatsu.shelf.ui.ShelfFragment
|
||||
import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker
|
||||
import org.koitharu.kotatsu.tracker.work.TrackWorker
|
||||
import javax.inject.Inject
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@@ -321,8 +319,6 @@ class MainActivity :
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.Default) {
|
||||
TrackWorker.setup(applicationContext)
|
||||
SuggestionsWorker.setup(applicationContext)
|
||||
LocalStorageCleanupWorker.enqueue(applicationContext)
|
||||
}
|
||||
withResumed {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.settings.work
|
||||
|
||||
import android.content.Context
|
||||
|
||||
interface PeriodicWorkScheduler {
|
||||
|
||||
suspend fun schedule(context: Context)
|
||||
|
||||
suspend fun unschedule(context: Context)
|
||||
|
||||
suspend fun isScheduled(context: Context): Boolean
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.koitharu.kotatsu.settings.work
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.ext.processLifecycleScope
|
||||
import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker
|
||||
import org.koitharu.kotatsu.tracker.work.TrackWorker
|
||||
import javax.inject.Inject
|
||||
|
||||
class WorkScheduleManager @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val settings: AppSettings,
|
||||
) : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
when (key) {
|
||||
AppSettings.KEY_TRACKER_ENABLED -> updateWorker(TrackWorker, settings.isTrackerEnabled)
|
||||
AppSettings.KEY_SUGGESTIONS -> updateWorker(SuggestionsWorker, settings.isSuggestionsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
fun init() {
|
||||
settings.subscribe(this)
|
||||
processLifecycleScope.launch(Dispatchers.Default) {
|
||||
updateWorkerImpl(TrackWorker, settings.isTrackerEnabled)
|
||||
updateWorkerImpl(SuggestionsWorker, settings.isSuggestionsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWorker(scheduler: PeriodicWorkScheduler, isEnabled: Boolean) {
|
||||
processLifecycleScope.launch(Dispatchers.Default) {
|
||||
updateWorkerImpl(scheduler, isEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateWorkerImpl(scheduler: PeriodicWorkScheduler, isEnabled: Boolean) {
|
||||
if (scheduler.isScheduled(context) != isEnabled) {
|
||||
if (isEnabled) {
|
||||
scheduler.schedule(context)
|
||||
} else {
|
||||
scheduler.unschedule(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import androidx.work.OutOfQuotaPolicy
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.await
|
||||
import androidx.work.workDataOf
|
||||
import coil.ImageLoader
|
||||
import coil.request.ImageRequest
|
||||
@@ -38,6 +39,7 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.distinctById
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.WorkManagerHelper
|
||||
import org.koitharu.kotatsu.core.util.ext.almostEquals
|
||||
import org.koitharu.kotatsu.core.util.ext.asArrayList
|
||||
import org.koitharu.kotatsu.core.util.ext.flatten
|
||||
@@ -55,6 +57,7 @@ import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.settings.work.PeriodicWorkScheduler
|
||||
import org.koitharu.kotatsu.suggestions.domain.MangaSuggestion
|
||||
import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository
|
||||
import org.koitharu.kotatsu.suggestions.domain.TagsBlacklist
|
||||
@@ -75,11 +78,11 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
) : CoroutineWorker(appContext, params) {
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
trySetForeground()
|
||||
if (!appSettings.isSuggestionsEnabled) {
|
||||
suggestionRepository.clear()
|
||||
return Result.success()
|
||||
}
|
||||
trySetForeground()
|
||||
val count = doWorkImpl()
|
||||
val outputData = workDataOf(DATA_COUNT to count)
|
||||
return Result.success(outputData)
|
||||
@@ -303,7 +306,7 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
return -1
|
||||
}
|
||||
|
||||
companion object {
|
||||
companion object : PeriodicWorkScheduler {
|
||||
|
||||
private const val TAG = "suggestions"
|
||||
private const val TAG_ONESHOT = "suggestions_oneshot"
|
||||
@@ -324,7 +327,7 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
SortOrder.RATING,
|
||||
)
|
||||
|
||||
fun setup(context: Context) {
|
||||
override suspend fun schedule(context: Context) {
|
||||
val constraints = Constraints.Builder()
|
||||
.setRequiredNetworkType(NetworkType.UNMETERED)
|
||||
.setRequiresBatteryNotLow(true)
|
||||
@@ -336,6 +339,19 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
.build()
|
||||
WorkManager.getInstance(context)
|
||||
.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP, request)
|
||||
.await()
|
||||
}
|
||||
|
||||
override suspend fun unschedule(context: Context) {
|
||||
WorkManager.getInstance(context)
|
||||
.cancelUniqueWork(TAG)
|
||||
.await()
|
||||
}
|
||||
|
||||
override suspend fun isScheduled(context: Context): Boolean {
|
||||
return WorkManagerHelper(WorkManager.getInstance(context))
|
||||
.getUniqueWorkInfoByName(TAG)
|
||||
.any { !it.state.isFinished }
|
||||
}
|
||||
|
||||
fun startNow(context: Context) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkQuery
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.await
|
||||
import coil.ImageLoader
|
||||
import coil.request.ImageRequest
|
||||
import dagger.assisted.Assisted
|
||||
@@ -42,12 +43,14 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.logs.FileLogger
|
||||
import org.koitharu.kotatsu.core.logs.TrackerLogger
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.WorkManagerHelper
|
||||
import org.koitharu.kotatsu.core.util.ext.toBitmapOrNull
|
||||
import org.koitharu.kotatsu.core.util.ext.trySetForeground
|
||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import org.koitharu.kotatsu.settings.work.PeriodicWorkScheduler
|
||||
import org.koitharu.kotatsu.tracker.domain.Tracker
|
||||
import org.koitharu.kotatsu.tracker.domain.model.MangaUpdates
|
||||
import java.util.concurrent.TimeUnit
|
||||
@@ -67,6 +70,7 @@ class TrackWorker @AssistedInject constructor(
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
trySetForeground()
|
||||
logger.log("doWork()")
|
||||
try {
|
||||
return doWorkImpl()
|
||||
@@ -85,7 +89,6 @@ class TrackWorker @AssistedInject constructor(
|
||||
if (!settings.isTrackerEnabled) {
|
||||
return Result.success(workDataOf(0, 0))
|
||||
}
|
||||
trySetForeground()
|
||||
val tracks = tracker.getAllTracks()
|
||||
logger.log("Total ${tracks.size} tracks")
|
||||
if (tracks.isEmpty()) {
|
||||
@@ -234,7 +237,7 @@ class TrackWorker @AssistedInject constructor(
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
companion object : PeriodicWorkScheduler {
|
||||
|
||||
private const val WORKER_CHANNEL_ID = "track_worker"
|
||||
private const val WORKER_NOTIFICATION_ID = 35
|
||||
@@ -244,14 +247,28 @@ class TrackWorker @AssistedInject constructor(
|
||||
private const val DATA_KEY_SUCCESS = "success"
|
||||
private const val DATA_KEY_FAILED = "failed"
|
||||
|
||||
fun setup(context: Context) {
|
||||
override suspend fun schedule(context: Context) {
|
||||
val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
|
||||
val request = PeriodicWorkRequestBuilder<TrackWorker>(4, TimeUnit.HOURS)
|
||||
.setConstraints(constraints)
|
||||
.addTag(TAG)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES)
|
||||
.build()
|
||||
WorkManager.getInstance(context).enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP, request)
|
||||
WorkManager.getInstance(context)
|
||||
.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP, request)
|
||||
.await()
|
||||
}
|
||||
|
||||
override suspend fun unschedule(context: Context) {
|
||||
WorkManager.getInstance(context)
|
||||
.cancelUniqueWork(TAG)
|
||||
.await()
|
||||
}
|
||||
|
||||
override suspend fun isScheduled(context: Context): Boolean {
|
||||
return WorkManagerHelper(WorkManager.getInstance(context))
|
||||
.getUniqueWorkInfoByName(TAG)
|
||||
.any { !it.state.isFinished }
|
||||
}
|
||||
|
||||
fun startNow(context: Context) {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrier_top"
|
||||
app:trackColor="?colorPrimaryContainer"
|
||||
app:trackColor="?android:colorBackground"
|
||||
tools:progress="25" />
|
||||
|
||||
<TextView
|
||||
|
||||
Reference in New Issue
Block a user