diff --git a/app/build.gradle b/app/build.gradle index 882747298..f07c05e8b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -81,6 +81,7 @@ dependencies { fullImplementation "androidx.recyclerview:recyclerview:${rootProject.ext.androidXVersion}" fullImplementation "androidx.cardview:cardview:${rootProject.ext.androidXVersion}" fullImplementation "com.google.android.material:material:${rootProject.ext.androidXVersion}" + fullImplementation 'android.arch.work:work-runtime:1.0.0-beta01' fullImplementation 'com.github.topjohnwu:libsu:2.1.2' fullImplementation 'org.kamranzafar:jtar:2.3' fullImplementation 'ru.noties:markwon:2.0.1' diff --git a/app/src/full/AndroidManifest.xml b/app/src/full/AndroidManifest.xml index 95bc21e6d..dae10ff4c 100644 --- a/app/src/full/AndroidManifest.xml +++ b/app/src/full/AndroidManifest.xml @@ -75,10 +75,6 @@ android:name="a.j" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE" /> - { + /* Stub */ + public g(@NonNull Context context, @NonNull WorkerParameters workerParams) { + super(context, workerParams); + } +} diff --git a/app/src/full/java/a/k.java b/app/src/full/java/a/k.java deleted file mode 100644 index f29cb69be..000000000 --- a/app/src/full/java/a/k.java +++ /dev/null @@ -1,7 +0,0 @@ -package a; - -import com.topjohnwu.magisk.services.UpdateCheckService; - -public class k extends UpdateCheckService { - /* stub */ -} diff --git a/app/src/full/java/a/w.java b/app/src/full/java/a/w.java new file mode 100644 index 000000000..3b8b94fa9 --- /dev/null +++ b/app/src/full/java/a/w.java @@ -0,0 +1,35 @@ +package a; + +import android.content.Context; + +import com.topjohnwu.magisk.services.DelegateWorker; + +import java.lang.reflect.ParameterizedType; + +import androidx.annotation.NonNull; +import androidx.work.Worker; +import androidx.work.WorkerParameters; + +public class w extends Worker { + + /* Wrapper class to workaround Proguard -keep class * extends Worker */ + + private T base; + + @SuppressWarnings("unchecked") + w(@NonNull Context context, @NonNull WorkerParameters workerParams) { + super(context, workerParams); + try { + base = ((Class) ((ParameterizedType) getClass().getGenericSuperclass()) + .getActualTypeArguments()[0]).newInstance(); + } catch (IllegalAccessException | InstantiationException ignored) {} + } + + @NonNull + @Override + public Result doWork() { + if (base == null) + return Result.failure(); + return base.doWork(); + } +} diff --git a/app/src/full/java/com/topjohnwu/magisk/ClassMap.java b/app/src/full/java/com/topjohnwu/magisk/ClassMap.java index 580f2af63..b77dc36b3 100644 --- a/app/src/full/java/com/topjohnwu/magisk/ClassMap.java +++ b/app/src/full/java/com/topjohnwu/magisk/ClassMap.java @@ -20,15 +20,15 @@ public class ClassMap { classMap.put(AboutActivity.class, a.d.class); classMap.put(DonationActivity.class, a.e.class); classMap.put(FlashActivity.class, a.f.class); + classMap.put(UpdateCheckService.class, a.g.class); classMap.put(GeneralReceiver.class, a.h.class); classMap.put(ShortcutReceiver.class, a.i.class); classMap.put(OnBootService.class, a.j.class); - classMap.put(UpdateCheckService.class, a.k.class); classMap.put(AboutCardRow.class, a.l.class); classMap.put(SuRequestActivity.class, a.m.class); } - public static Class get(Class c) { + public static Class get(Class c) { return classMap.get(c); } } diff --git a/app/src/full/java/com/topjohnwu/magisk/SplashActivity.java b/app/src/full/java/com/topjohnwu/magisk/SplashActivity.java index efeca53b2..9e4b2978a 100644 --- a/app/src/full/java/com/topjohnwu/magisk/SplashActivity.java +++ b/app/src/full/java/com/topjohnwu/magisk/SplashActivity.java @@ -42,8 +42,6 @@ public class SplashActivity extends BaseActivity { // Magisk working as expected if (Shell.rootAccess() && Data.magiskVersionCode > 0) { - // Update check service - AppUtils.setupUpdateCheck(); // Load modules Utils.loadModules(); } @@ -53,6 +51,9 @@ public class SplashActivity extends BaseActivity { // Create notification channel on Android O Notifications.setup(this); + // Schedule periodic update checks + AppUtils.scheduleUpdateCheck(); + // Setup shortcuts sendBroadcast(new Intent(this, ClassMap.get(ShortcutReceiver.class))); diff --git a/app/src/full/java/com/topjohnwu/magisk/fragments/SettingsFragment.java b/app/src/full/java/com/topjohnwu/magisk/fragments/SettingsFragment.java index 84ef33fd4..641a1c406 100644 --- a/app/src/full/java/com/topjohnwu/magisk/fragments/SettingsFragment.java +++ b/app/src/full/java/com/topjohnwu/magisk/fragments/SettingsFragment.java @@ -252,7 +252,7 @@ public class SettingsFragment extends PreferenceFragmentCompat CheckUpdates.check(); break; case Const.Key.CHECK_UPDATES: - AppUtils.setupUpdateCheck(); + AppUtils.scheduleUpdateCheck(); break; } Data.loadConfig(); diff --git a/app/src/full/java/com/topjohnwu/magisk/services/DelegateWorker.java b/app/src/full/java/com/topjohnwu/magisk/services/DelegateWorker.java new file mode 100644 index 000000000..4637a372e --- /dev/null +++ b/app/src/full/java/com/topjohnwu/magisk/services/DelegateWorker.java @@ -0,0 +1,9 @@ +package com.topjohnwu.magisk.services; + +import androidx.annotation.NonNull; +import androidx.work.ListenableWorker; + +public abstract class DelegateWorker { + @NonNull + public abstract ListenableWorker.Result doWork(); +} diff --git a/app/src/full/java/com/topjohnwu/magisk/services/UpdateCheckService.java b/app/src/full/java/com/topjohnwu/magisk/services/UpdateCheckService.java index 620f91f05..c23457fb3 100644 --- a/app/src/full/java/com/topjohnwu/magisk/services/UpdateCheckService.java +++ b/app/src/full/java/com/topjohnwu/magisk/services/UpdateCheckService.java @@ -1,32 +1,29 @@ package com.topjohnwu.magisk.services; -import android.app.job.JobParameters; -import android.app.job.JobService; - import com.topjohnwu.core.Data; import com.topjohnwu.core.tasks.CheckUpdates; import com.topjohnwu.magisk.BuildConfig; import com.topjohnwu.magisk.components.Notifications; import com.topjohnwu.superuser.Shell; -public class UpdateCheckService extends JobService { +import androidx.annotation.NonNull; +import androidx.work.ListenableWorker; +public class UpdateCheckService extends DelegateWorker { + + @NonNull @Override - public boolean onStartJob(JobParameters params) { + public ListenableWorker.Result doWork() { Shell.getShell(); - CheckUpdates.check(() -> { - if (BuildConfig.VERSION_CODE < Data.remoteManagerVersionCode) { - Notifications.managerUpdate(); - } else if (Data.magiskVersionCode < Data.remoteMagiskVersionCode) { - Notifications.magiskUpdate(); - } - jobFinished(params, false); - }); - return true; + CheckUpdates.checkNow(this::onCheckDone); + return ListenableWorker.Result.success(); } - @Override - public boolean onStopJob(JobParameters params) { - return true; + private void onCheckDone() { + if (BuildConfig.VERSION_CODE < Data.remoteManagerVersionCode) { + Notifications.managerUpdate(); + } else if (Data.magiskVersionCode < Data.remoteMagiskVersionCode) { + Notifications.magiskUpdate(); + } } } diff --git a/app/src/full/java/com/topjohnwu/magisk/utils/AppUtils.java b/app/src/full/java/com/topjohnwu/magisk/utils/AppUtils.java index 1bd572fb9..a38a550fe 100644 --- a/app/src/full/java/com/topjohnwu/magisk/utils/AppUtils.java +++ b/app/src/full/java/com/topjohnwu/magisk/utils/AppUtils.java @@ -1,8 +1,5 @@ package com.topjohnwu.magisk.utils; -import android.app.job.JobInfo; -import android.app.job.JobScheduler; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -15,25 +12,29 @@ import com.topjohnwu.magisk.ClassMap; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.services.UpdateCheckService; +import java.util.concurrent.TimeUnit; + +import androidx.work.Constraints; +import androidx.work.ExistingPeriodicWorkPolicy; +import androidx.work.NetworkType; +import androidx.work.PeriodicWorkRequest; +import androidx.work.WorkManager; + public class AppUtils { - public static void setupUpdateCheck() { - App app = App.self; - JobScheduler scheduler = (JobScheduler) app.getSystemService(Context.JOB_SCHEDULER_SERVICE); - - if (app.prefs.getBoolean(Const.Key.CHECK_UPDATES, true)) { - if (scheduler.getAllPendingJobs().isEmpty() || - Const.UPDATE_SERVICE_VER > app.prefs.getInt(Const.Key.UPDATE_SERVICE_VER, -1)) { - ComponentName service = new ComponentName(app, ClassMap.get(UpdateCheckService.class)); - JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service) - .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) - .setPersisted(true) - .setPeriodic(8 * 60 * 60 * 1000) - .build(); - scheduler.schedule(info); - } + public static void scheduleUpdateCheck() { + if (App.self.prefs.getBoolean(Const.Key.CHECK_UPDATES, true)) { + Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); + PeriodicWorkRequest request = new PeriodicWorkRequest + .Builder(ClassMap.get(UpdateCheckService.class), 12, TimeUnit.HOURS) + .setConstraints(constraints) + .build(); + WorkManager.getInstance().enqueueUniquePeriodicWork(Const.ID.CHECK_MAGISK_UPDATE_WORKER_ID, + ExistingPeriodicWorkPolicy.REPLACE, request); } else { - scheduler.cancel(Const.UPDATE_SERVICE_VER); + WorkManager.getInstance().cancelUniqueWork(Const.ID.CHECK_MAGISK_UPDATE_WORKER_ID); } } diff --git a/core/src/main/java/com/topjohnwu/core/Const.java b/core/src/main/java/com/topjohnwu/core/Const.java index 16544a635..492bebcc1 100644 --- a/core/src/main/java/com/topjohnwu/core/Const.java +++ b/core/src/main/java/com/topjohnwu/core/Const.java @@ -62,6 +62,7 @@ public class Const { public static final int HIDE_MANAGER_NOTIFICATION_ID = 8; public static final String UPDATE_NOTIFICATION_CHANNEL = "update"; public static final String PROGRESS_NOTIFICATION_CHANNEL = "progress"; + public static final String CHECK_MAGISK_UPDATE_WORKER_ID = "magisk_update"; } public static class Url { diff --git a/core/src/main/java/com/topjohnwu/core/tasks/CheckUpdates.java b/core/src/main/java/com/topjohnwu/core/tasks/CheckUpdates.java index 8d43c836f..4839e08e4 100644 --- a/core/src/main/java/com/topjohnwu/core/tasks/CheckUpdates.java +++ b/core/src/main/java/com/topjohnwu/core/tasks/CheckUpdates.java @@ -5,6 +5,7 @@ import com.topjohnwu.core.Const; import com.topjohnwu.core.Data; import com.topjohnwu.core.utils.Topic; import com.topjohnwu.net.Networking; +import com.topjohnwu.net.Request; import com.topjohnwu.net.ResponseListener; import org.json.JSONException; @@ -40,26 +41,31 @@ public class CheckUpdates { } } - public static void check(Runnable cb) { + private static Request getRequest() { String url; switch (Data.updateChannel) { - case Const.Value.STABLE_CHANNEL: - url = Const.Url.STABLE_URL; - break; case Const.Value.BETA_CHANNEL: url = Const.Url.BETA_URL; break; case Const.Value.CUSTOM_CHANNEL: url = App.self.prefs.getString(Const.Key.CUSTOM_CHANNEL, ""); break; + case Const.Value.STABLE_CHANNEL: default: - return; + url = Const.Url.STABLE_URL; + break; } - Networking.get(url).getAsJSONObject(new UpdateListener(cb)); + return Networking.get(url); } public static void check() { - check(null); + getRequest().getAsJSONObject(new UpdateListener(null)); + } + + public static void checkNow(Runnable cb) { + JSONObject json = getRequest().execForJSONObject().getResult(); + if (json != null) + new UpdateListener(cb).onResponse(json); } private static class UpdateListener implements ResponseListener {