diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 0cf717e23..5af4ef80b 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -123,12 +123,11 @@ dependencies {
implementation("androidx.biometric:biometric:1.1.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.1")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
- implementation("androidx.browser:browser:1.3.0")
+ implementation("androidx.browser:browser:1.4.0")
implementation("androidx.preference:preference:1.1.1")
implementation("androidx.recyclerview:recyclerview:1.2.1")
implementation("androidx.fragment:fragment-ktx:1.3.6")
- implementation("androidx.work:work-runtime-ktx:2.7.0")
implementation("androidx.transition:transition:1.4.1")
- implementation("androidx.core:core-ktx:1.6.0")
+ implementation("androidx.core:core-ktx:1.7.0")
implementation("com.google.android.material:material:1.4.0")
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0d621bda2..70e733f99 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,7 +12,6 @@
android:multiArch="true"
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning">
-
-
-
+
-
-
-
-
+
+
+
-
-
-
-
-
it
- name == JOB_SCHEDULER_SERVICE -> JobSchedulerWrapper(it as JobScheduler)
- else -> it
- }
- }
- }
-}
-
fun Class<*>.cmp(pkg: String) =
ComponentName(pkg, Info.stub?.classToComponent?.get(name) ?: name)
@@ -99,28 +78,6 @@ object AssetHack {
}
}
-@RequiresApi(28)
-private class JobSchedulerWrapper(private val base: JobScheduler) : JobScheduler() {
- override fun schedule(job: JobInfo) = base.schedule(job.patch())
- override fun enqueue(job: JobInfo, work: JobWorkItem) = base.enqueue(job.patch(), work)
- override fun cancel(jobId: Int) = base.cancel(jobId)
- override fun cancelAll() = base.cancelAll()
- override fun getAllPendingJobs(): List = base.allPendingJobs
- override fun getPendingJob(jobId: Int) = base.getPendingJob(jobId)
- private fun JobInfo.patch(): JobInfo {
- // Swap out the service of JobInfo
- val component = service.run {
- ComponentName(packageName,
- Info.stub?.classToComponent?.get(className) ?: className)
- }
- javaClass.getDeclaredField("service").apply {
- isAccessible = true
- }.set(this, component)
-
- return this
- }
-}
-
// Keep a reference to these resources to prevent it from
// being removed when running "remove unused resources"
val shouldKeepResources = listOf(
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/JobService.kt b/app/src/main/java/com/topjohnwu/magisk/core/JobService.kt
new file mode 100644
index 000000000..eb283ddd8
--- /dev/null
+++ b/app/src/main/java/com/topjohnwu/magisk/core/JobService.kt
@@ -0,0 +1,56 @@
+package com.topjohnwu.magisk.core
+
+import android.app.job.JobInfo
+import android.app.job.JobParameters
+import android.app.job.JobScheduler
+import android.content.Context
+import androidx.core.content.getSystemService
+import com.topjohnwu.magisk.BuildConfig
+import com.topjohnwu.magisk.core.base.BaseJobService
+import com.topjohnwu.magisk.di.ServiceLocator
+import com.topjohnwu.magisk.view.Notifications
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import java.util.concurrent.TimeUnit
+
+class JobService : BaseJobService() {
+
+ private val job = Job()
+ private val svc get() = ServiceLocator.networkService
+
+ override fun onStartJob(params: JobParameters): Boolean {
+ val coroutineScope = CoroutineScope(Dispatchers.IO + job)
+ coroutineScope.launch {
+ svc.fetchUpdate()?.run {
+ if (Info.env.isActive && BuildConfig.VERSION_CODE < magisk.versionCode)
+ Notifications.managerUpdate(this@JobService)
+ }
+ jobFinished(params, false)
+ }
+ return false
+ }
+
+ override fun onStopJob(params: JobParameters): Boolean {
+ job.cancel()
+ return false
+ }
+
+ companion object {
+ fun schedule(context: Context) {
+ val svc = context.getSystemService() ?: return
+ if (Config.checkUpdate) {
+ val cmp = JobService::class.java.cmp(context.packageName)
+ val info = JobInfo.Builder(Const.ID.JOB_SERVICE_ID, cmp)
+ .setPeriodic(TimeUnit.HOURS.toMillis(12))
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
+ .setRequiresDeviceIdle(true)
+ .build()
+ svc.schedule(info)
+ } else {
+ svc.cancel(Const.ID.JOB_SERVICE_ID)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt b/app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt
index 6f6d2e9e9..666044b24 100644
--- a/app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt
@@ -15,7 +15,7 @@ import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell
import java.util.concurrent.CountDownLatch
-open class SplashActivity : BaseActivity() {
+class SplashActivity : BaseActivity() {
private val latch = CountDownLatch(1)
@@ -63,7 +63,7 @@ open class SplashActivity : BaseActivity() {
Config.load(prevPkg)
handleRepackage(prevPkg)
Notifications.setup(this)
- UpdateCheckService.schedule(this)
+ JobService.schedule(this)
Shortcuts.setupDynamic(this)
// Pre-fetch network services
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/UpdateCheckService.kt b/app/src/main/java/com/topjohnwu/magisk/core/UpdateCheckService.kt
deleted file mode 100644
index 89d01a111..000000000
--- a/app/src/main/java/com/topjohnwu/magisk/core/UpdateCheckService.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.topjohnwu.magisk.core
-
-import android.annotation.SuppressLint
-import android.content.Context
-import androidx.work.*
-import com.topjohnwu.magisk.BuildConfig
-import com.topjohnwu.magisk.di.ServiceLocator
-import com.topjohnwu.magisk.view.Notifications
-import java.util.concurrent.TimeUnit
-
-class UpdateCheckService(context: Context, workerParams: WorkerParameters)
- : CoroutineWorker(context, workerParams) {
-
- private val svc get() = ServiceLocator.networkService
-
- override suspend fun doWork(): Result {
- return svc.fetchUpdate()?.run {
- if (Info.env.isActive && BuildConfig.VERSION_CODE < magisk.versionCode)
- Notifications.managerUpdate(applicationContext)
- Result.success()
- } ?: Result.failure()
- }
-
- companion object {
- @SuppressLint("NewApi")
- fun schedule(context: Context) {
- if (Config.checkUpdate) {
- val constraints = Constraints.Builder()
- .setRequiredNetworkType(NetworkType.CONNECTED)
- .setRequiresDeviceIdle(true)
- .build()
- val request = PeriodicWorkRequestBuilder(12, TimeUnit.HOURS)
- .setConstraints(constraints)
- .build()
- WorkManager.getInstance(context).enqueueUniquePeriodicWork(
- Const.ID.CHECK_MAGISK_UPDATE_WORKER_ID,
- ExistingPeriodicWorkPolicy.REPLACE, request)
- } else {
- WorkManager.getInstance(context)
- .cancelUniqueWork(Const.ID.CHECK_MAGISK_UPDATE_WORKER_ID)
- }
- }
- }
-}
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseJobService.kt b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseJobService.kt
new file mode 100644
index 000000000..3208be75c
--- /dev/null
+++ b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseJobService.kt
@@ -0,0 +1,11 @@
+package com.topjohnwu.magisk.core.base
+
+import android.app.job.JobService
+import android.content.Context
+import com.topjohnwu.magisk.core.wrap
+
+abstract class BaseJobService : JobService() {
+ override fun attachBaseContext(base: Context) {
+ super.attachBaseContext(base.wrap())
+ }
+}
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseWorkerWrapper.kt b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseWorkerWrapper.kt
deleted file mode 100644
index 52f9ab2e3..000000000
--- a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseWorkerWrapper.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.topjohnwu.magisk.core.base
-
-import android.content.Context
-import android.net.Network
-import android.net.Uri
-import androidx.annotation.MainThread
-import androidx.annotation.RequiresApi
-import androidx.work.Data
-import androidx.work.ListenableWorker
-import com.google.common.util.concurrent.ListenableFuture
-import java.util.*
-
-abstract class BaseWorkerWrapper {
-
- private lateinit var worker: ListenableWorker
-
- val applicationContext: Context
- get() = worker.applicationContext
-
- val id: UUID
- get() = worker.id
-
- val inputData: Data
- get() = worker.inputData
-
- val tags: Set
- get() = worker.tags
-
- val triggeredContentUris: List
- @RequiresApi(24)
- get() = worker.triggeredContentUris
-
- val triggeredContentAuthorities: List
- @RequiresApi(24)
- get() = worker.triggeredContentAuthorities
-
- val network: Network?
- @RequiresApi(28)
- get() = worker.network
-
- val runAttemptCount: Int
- get() = worker.runAttemptCount
-
- val isStopped: Boolean
- get() = worker.isStopped
-
- abstract fun doWork(): ListenableWorker.Result
-
- fun onStopped() {}
-
- fun attachWorker(w: ListenableWorker) {
- worker = w
- }
-
- @MainThread
- fun startWork(): ListenableFuture {
- return worker.startWork()
- }
-}
diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt
index ca51108a0..9ce4dd917 100644
--- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt
@@ -12,7 +12,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
-import com.topjohnwu.magisk.core.UpdateCheckService
+import com.topjohnwu.magisk.core.JobService
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
@@ -185,7 +185,7 @@ object UpdateChecker : BaseSettingsItem.Toggle() {
override var value = Config.checkUpdate
set(value) = setV(value, field, { field = it }) {
Config.checkUpdate = it
- UpdateCheckService.schedule(AppContext)
+ JobService.schedule(AppContext)
}
}
diff --git a/buildSrc/src/main/java/Codegen.kt b/buildSrc/src/main/java/Codegen.kt
index b8df250c0..94f415f14 100644
--- a/buildSrc/src/main/java/Codegen.kt
+++ b/buildSrc/src/main/java/Codegen.kt
@@ -153,7 +153,10 @@ fun genStubManifest(srcDir: File, outDir: File): String {
cmpList.add(Component(
"com.topjohnwu.magisk.ui.MainActivity",
"",
- """|""".ind(2)
+ """
+ |""".ind(2)
))
cmpList.add(Component(
@@ -176,18 +179,19 @@ fun genStubManifest(srcDir: File, outDir: File): String {
cmpList.add(Component(
"com.topjohnwu.magisk.core.download.DownloadService",
"",
- """|""".ind(2)
+ """
+ |""".trimIndent().ind(2)
))
cmpList.add(Component(
- "androidx.work.impl.background.systemjob.SystemJobService",
+ "com.topjohnwu.magisk.core.JobService",
"",
"""
|""".ind(2)
))
diff --git a/gradle.properties b/gradle.properties
index ed1d321fb..60a6c00de 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -30,7 +30,7 @@ android.injected.testOnly=false
kapt.incremental.apt=true
# Magisk
-magisk.stubVersion=21
+magisk.stubVersion=22
magisk.versionCode=23012
magisk.ndkVersion=21e
magisk.fullNdkVersion=21.4.7075529