Skip to content

Commit

Permalink
Targeting SDK 33 (Android 13) (#1525)
Browse files Browse the repository at this point in the history
* starting workmanager updates

* Update Download service to download job

Also making downloader use suspend methods like upstream

Co-Authored-By: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>

* Make BackupRestorer a job

* Make LibraryUpdateJob a datasync service type

* Changing Extension auto installer to a job instead of service

* Changing App auto installer to a job instead of service

With it theres no more services, and nearly ready to up the target sdk

* Add runtime permission for notifications

Shows permission when adding to library, seeing the app update in app prompt, or loading library or recents
Tries to show the permission again (or a warning message) when trying to restore a backup or set library update timing
Same warning messages shows when not allowing notifications

* Set target sdk to 33

we made it.

* Clean up ContextExtensions

* Add notification check for incognito mode

* Add last updated timestamp to updates job

* Update LibraryUpdateJob.kt

minor changes to the notifier's placeholder, and making sure it uses localeContext for versions under A13

* update channel logic in library updater

* Change library update channel to just take a Long instead a whole Manga

* Use extensionManager flow in ExtensionInstallerJob

* Update MainActivity.kt

* Fixes to downloadFlow

* reworking running extensions after library update logic

* Change update channel to shared flow in library job

* More updates to the library updates flow

no longer using a suspend, instead holding a buffer for the flow

* updates to the flow in extensionInstaller

from state to shared, also using "tryEmit" less for it

* Fix extension auto installing notification not dismissing/dismissable

* Version 1.7.0

* Update AppDownloadInstallJob.kt

* Refactor DownloadJob

* Version 1.7.0-b02

* Fix uninstalling extensions not refreshing the list

* Show notification permission prompt when pressing update all

* Chunked the extension install job in case too many extensions are being updated at once

The limit is around 62 extensions, but to be safe it runs 32 per job (which jobs still update 3 at a time)

Closes #1584

* Update Java Version

---------

Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
  • Loading branch information
Jays2Kings and ivaniskandar authored Jul 31, 2023
1 parent 21a2705 commit 3140361
Show file tree
Hide file tree
Showing 60 changed files with 2,129 additions and 2,344 deletions.
18 changes: 10 additions & 8 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ android {
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "1.8"
jvmTarget = "17"
}
namespace = "eu.kanade.tachiyomi"
}
Expand Down Expand Up @@ -159,7 +159,6 @@ dependencies {
implementation("androidx.palette:palette:1.0.0")
implementation("androidx.activity:activity-ktx:1.7.0")
implementation("androidx.core:core-ktx:1.10.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
implementation("com.google.android.flexbox:flexbox:3.0.0")
implementation("androidx.window:window:1.0.0")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
Expand All @@ -173,8 +172,11 @@ dependencies {
implementation("com.google.firebase:firebase-analytics-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx")

val lifecycleVersion = "2.5.1"
val lifecycleVersion = "2.6.1"
kapt("androidx.lifecycle:lifecycle-compiler:$lifecycleVersion")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion")
implementation("androidx.lifecycle:lifecycle-common:$lifecycleVersion")
implementation("androidx.lifecycle:lifecycle-process:$lifecycleVersion")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion")

Expand Down Expand Up @@ -213,13 +215,13 @@ dependencies {
// Disk
implementation("com.jakewharton:disklrucache:2.0.2")
implementation("com.github.tachiyomiorg:unifile:17bec43")
implementation("com.github.junrar:junrar:7.5.0")
implementation("com.github.junrar:junrar:7.5.4")

// HTML parser
implementation("org.jsoup:jsoup:1.15.3")
implementation("org.jsoup:jsoup:1.15.4")

// Job scheduling
implementation("androidx.work:work-runtime-ktx:2.6.0")
implementation("androidx.work:work-runtime-ktx:2.8.0")
implementation("com.google.guava:guava:31.1-android")

implementation("com.google.android.gms:play-services-gcm:17.0.0")
Expand Down
21 changes: 3 additions & 18 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -241,24 +241,9 @@
</receiver>

<service
android:name=".data.library.LibraryUpdateService"
android:exported="false" />

<service
android:name=".extension.ExtensionInstallService"
android:exported="false" />

<service
android:name=".data.download.DownloadService"
android:exported="false" />

<service
android:name=".data.updater.AppUpdateService"
android:exported="false" />

<service
android:name=".data.backup.BackupRestoreService"
android:exported="false"/>
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="dataSync"
tools:node="merge" />

<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
Expand Down
13 changes: 10 additions & 3 deletions app/src/main/java/eu/kanade/tachiyomi/App.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package eu.kanade.tachiyomi

import android.Manifest
import android.annotation.SuppressLint
import android.app.Application
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import android.webkit.WebView
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
Expand All @@ -35,9 +38,7 @@ import kotlinx.coroutines.flow.onEach
import org.conscrypt.Conscrypt
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.InjektScope
import uy.kohesive.injekt.injectLazy
import uy.kohesive.injekt.registry.default.DefaultRegistrar
import java.security.Security

open class App : Application(), DefaultLifecycleObserver {
Expand All @@ -62,7 +63,6 @@ open class App : Application(), DefaultLifecycleObserver {
if (packageName != process) WebView.setDataDirectorySuffix(process)
}

Injekt = InjektScope(DefaultRegistrar())
Injekt.importModule(AppModule(this))

CoilSetup(this)
Expand Down Expand Up @@ -101,6 +101,13 @@ open class App : Application(), DefaultLifecycleObserver {
)
setContentIntent(pendingIntent)
}
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS,
) != PackageManager.PERMISSION_GRANTED
) {
return@onEach
}
notificationManager.notify(Notifications.ID_INCOGNITO_MODE, notification)
} else {
disableIncognitoReceiver.unregister()
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/java/eu/kanade/tachiyomi/Migrations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.updater.AppDownloadInstallJob
import eu.kanade.tachiyomi.data.updater.AppUpdateJob
import eu.kanade.tachiyomi.data.updater.AppUpdateService
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
Expand All @@ -37,7 +37,7 @@ object Migrations {
val context = preferences.context
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs.edit {
remove(AppUpdateService.NOTIFY_ON_INSTALL_KEY)
remove(AppDownloadInstallJob.NOTIFY_ON_INSTALL_KEY)
}
val oldVersion = preferences.lastVersionCode().get()
if (oldVersion < BuildConfig.VERSION_CODE) {
Expand Down Expand Up @@ -216,6 +216,10 @@ object Migrations {
preferences.groupChaptersHistory().set(RecentsPresenter.GroupType.Never)
}
}
if (oldVersion < 105) {
LibraryUpdateJob.cancelAllWorks(context)
LibraryUpdateJob.setupTask(context)
}

return true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.chapter.NoChaptersException
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import kotlinx.coroutines.Job
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.text.SimpleDateFormat
Expand All @@ -25,8 +24,6 @@ abstract class AbstractBackupRestore<T : AbstractBackupManager>(protected val co
protected val trackManager: TrackManager by injectLazy()
protected val customMangaManager: CustomMangaManager by injectLazy()

var job: Job? = null

protected lateinit var backupManager: T

protected var restoreAmount = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID

object BackupConst {

private const val NAME = "BackupRestoreServices"
private const val NAME = "BackupRestorer"
const val EXTRA_URI = "$ID.$NAME.EXTRA_URI"

// Filter options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupConst.BACKUP_ALL)
val isAutoBackup = inputData.getBoolean(IS_AUTO_BACKUP_KEY, true)

context.notificationManager.notify(Notifications.ID_BACKUP_PROGRESS, notifier.showBackupProgress().build())
notifier.showBackupProgress()
return try {
val location = BackupManager(context).createBackup(uri, flags, isAutoBackup)
if (!isAutoBackup) notifier.showBackupComplete(UniFile.fromUri(context, location.toUri()))
Expand Down Expand Up @@ -68,7 +68,7 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
.setInputData(workDataOf(IS_AUTO_BACKUP_KEY to true))
.build()

workManager.enqueueUniquePeriodicWork(TAG_AUTO, ExistingPeriodicWorkPolicy.REPLACE, request)
workManager.enqueueUniquePeriodicWork(TAG_AUTO, ExistingPeriodicWorkPolicy.UPDATE, request)
} else {
workManager.cancelUniqueWork(TAG_AUTO)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class BackupNotifier(private val context: Context) {
context.notificationManager.notify(id, build())
}

fun showBackupProgress(): NotificationCompat.Builder {
fun showBackupProgress() {
val builder = with(progressNotificationBuilder) {
setContentTitle(context.getString(R.string.creating_backup))

Expand All @@ -45,8 +45,6 @@ class BackupNotifier(private val context: Context) {
}

builder.show(Notifications.ID_BACKUP_PROGRESS)

return builder
}

fun showBackupError(error: String?) {
Expand Down Expand Up @@ -88,7 +86,7 @@ class BackupNotifier(private val context: Context) {
setContentText(content)
}

setProgress(maxAmount, progress, false)
setProgress(maxAmount, progress, progress == -1)
setOnlyAlertOnce(true)

// Clear old actions if they exist
Expand All @@ -101,7 +99,9 @@ class BackupNotifier(private val context: Context) {
)
}

builder.show(Notifications.ID_RESTORE_PROGRESS)
if (progress != -1) {
builder.show(Notifications.ID_RESTORE_PROGRESS)
}

return builder
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package eu.kanade.tachiyomi.data.backup

import android.content.Context
import android.content.pm.ServiceInfo
import android.net.Uri
import android.os.Build
import androidx.work.CoroutineWorker
import androidx.work.ExistingWorkPolicy
import androidx.work.ForegroundInfo
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
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.jobIsRunning
import eu.kanade.tachiyomi.util.system.localeContext
import eu.kanade.tachiyomi.util.system.tryToSetForeground
import eu.kanade.tachiyomi.util.system.withIOContext
import kotlinx.coroutines.CancellationException

class BackupRestoreJob(val context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) {

private val notifier = BackupNotifier(context.localeContext)
private val restorer = BackupRestorer(context, notifier)

override suspend fun getForegroundInfo(): ForegroundInfo {
val notification = notifier.showRestoreProgress(progress = -1).build()
val id = Notifications.ID_RESTORE_PROGRESS
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ForegroundInfo(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
} else {
ForegroundInfo(id, notification)
}
}

override suspend fun doWork(): Result {
tryToSetForeground()

val uriPath = inputData.getString(BackupConst.EXTRA_URI) ?: return Result.failure()

val uri = Uri.parse(uriPath) ?: return Result.failure()

withIOContext {
try {
if (!restorer.restoreBackup(uri)) {
notifier.showRestoreError(context.getString(R.string.restoring_backup_canceled))
}
} catch (exception: Exception) {
if (exception is CancellationException) {
notifier.showRestoreError(context.getString(R.string.restoring_backup_canceled))
} else {
restorer.writeErrorLog()
notifier.showRestoreError(exception.message)
}
}
}
return Result.success()
}

companion object {
private const val TAG = "BackupRestorer"

fun start(context: Context, uri: Uri) {
val request = OneTimeWorkRequestBuilder<BackupRestoreJob>()
.addTag(TAG)
.setInputData(workDataOf(BackupConst.EXTRA_URI to uri.toString()))
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
WorkManager.getInstance(context)
.enqueueUniqueWork(TAG, ExistingWorkPolicy.REPLACE, request)
}

fun stop(context: Context) {
WorkManager.getInstance(context).cancelUniqueWork(TAG)
}

fun isRunning(context: Context) = WorkManager.getInstance(context).jobIsRunning(TAG)
}
}
Loading

0 comments on commit 3140361

Please sign in to comment.