Switch to WorkManager

This commit is contained in:
topjohnwu 2018-12-27 22:07:47 +08:00
parent 58ba0b0b4e
commit da9c6f6e23
13 changed files with 114 additions and 59 deletions

View File

@ -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'

View File

@ -75,10 +75,6 @@
android:name="a.j"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service
android:name="a.k"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<!-- Hardcode GMS version -->
<meta-data

View File

@ -0,0 +1,15 @@
package a;
import android.content.Context;
import com.topjohnwu.magisk.services.UpdateCheckService;
import androidx.annotation.NonNull;
import androidx.work.WorkerParameters;
public class g extends w<UpdateCheckService> {
/* Stub */
public g(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
}

View File

@ -1,7 +0,0 @@
package a;
import com.topjohnwu.magisk.services.UpdateCheckService;
public class k extends UpdateCheckService {
/* stub */
}

View File

@ -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<T extends DelegateWorker> 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<T>) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0]).newInstance();
} catch (IllegalAccessException | InstantiationException ignored) {}
}
@NonNull
@Override
public Result doWork() {
if (base == null)
return Result.failure();
return base.doWork();
}
}

View File

@ -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 <T> Class<T> get(Class c) {
return classMap.get(c);
}
}

View File

@ -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)));

View File

@ -252,7 +252,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
CheckUpdates.check();
break;
case Const.Key.CHECK_UPDATES:
AppUtils.setupUpdateCheck();
AppUtils.scheduleUpdateCheck();
break;
}
Data.loadConfig();

View File

@ -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();
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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<JSONObject> {