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.recyclerview:recyclerview:${rootProject.ext.androidXVersion}"
fullImplementation "androidx.cardview:cardview:${rootProject.ext.androidXVersion}" fullImplementation "androidx.cardview:cardview:${rootProject.ext.androidXVersion}"
fullImplementation "com.google.android.material:material:${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 'com.github.topjohnwu:libsu:2.1.2'
fullImplementation 'org.kamranzafar:jtar:2.3' fullImplementation 'org.kamranzafar:jtar:2.3'
fullImplementation 'ru.noties:markwon:2.0.1' fullImplementation 'ru.noties:markwon:2.0.1'

View File

@ -75,10 +75,6 @@
android:name="a.j" android:name="a.j"
android:exported="true" android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" /> 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 --> <!-- Hardcode GMS version -->
<meta-data <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(AboutActivity.class, a.d.class);
classMap.put(DonationActivity.class, a.e.class); classMap.put(DonationActivity.class, a.e.class);
classMap.put(FlashActivity.class, a.f.class); classMap.put(FlashActivity.class, a.f.class);
classMap.put(UpdateCheckService.class, a.g.class);
classMap.put(GeneralReceiver.class, a.h.class); classMap.put(GeneralReceiver.class, a.h.class);
classMap.put(ShortcutReceiver.class, a.i.class); classMap.put(ShortcutReceiver.class, a.i.class);
classMap.put(OnBootService.class, a.j.class); classMap.put(OnBootService.class, a.j.class);
classMap.put(UpdateCheckService.class, a.k.class);
classMap.put(AboutCardRow.class, a.l.class); classMap.put(AboutCardRow.class, a.l.class);
classMap.put(SuRequestActivity.class, a.m.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); return classMap.get(c);
} }
} }

View File

@ -42,8 +42,6 @@ public class SplashActivity extends BaseActivity {
// Magisk working as expected // Magisk working as expected
if (Shell.rootAccess() && Data.magiskVersionCode > 0) { if (Shell.rootAccess() && Data.magiskVersionCode > 0) {
// Update check service
AppUtils.setupUpdateCheck();
// Load modules // Load modules
Utils.loadModules(); Utils.loadModules();
} }
@ -53,6 +51,9 @@ public class SplashActivity extends BaseActivity {
// Create notification channel on Android O // Create notification channel on Android O
Notifications.setup(this); Notifications.setup(this);
// Schedule periodic update checks
AppUtils.scheduleUpdateCheck();
// Setup shortcuts // Setup shortcuts
sendBroadcast(new Intent(this, ClassMap.get(ShortcutReceiver.class))); sendBroadcast(new Intent(this, ClassMap.get(ShortcutReceiver.class)));

View File

@ -252,7 +252,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
CheckUpdates.check(); CheckUpdates.check();
break; break;
case Const.Key.CHECK_UPDATES: case Const.Key.CHECK_UPDATES:
AppUtils.setupUpdateCheck(); AppUtils.scheduleUpdateCheck();
break; break;
} }
Data.loadConfig(); 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; package com.topjohnwu.magisk.services;
import android.app.job.JobParameters;
import android.app.job.JobService;
import com.topjohnwu.core.Data; import com.topjohnwu.core.Data;
import com.topjohnwu.core.tasks.CheckUpdates; import com.topjohnwu.core.tasks.CheckUpdates;
import com.topjohnwu.magisk.BuildConfig; import com.topjohnwu.magisk.BuildConfig;
import com.topjohnwu.magisk.components.Notifications; import com.topjohnwu.magisk.components.Notifications;
import com.topjohnwu.superuser.Shell; 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 @Override
public boolean onStartJob(JobParameters params) { public ListenableWorker.Result doWork() {
Shell.getShell(); Shell.getShell();
CheckUpdates.check(() -> { CheckUpdates.checkNow(this::onCheckDone);
if (BuildConfig.VERSION_CODE < Data.remoteManagerVersionCode) { return ListenableWorker.Result.success();
Notifications.managerUpdate();
} else if (Data.magiskVersionCode < Data.remoteMagiskVersionCode) {
Notifications.magiskUpdate();
}
jobFinished(params, false);
});
return true;
} }
@Override private void onCheckDone() {
public boolean onStopJob(JobParameters params) { if (BuildConfig.VERSION_CODE < Data.remoteManagerVersionCode) {
return true; Notifications.managerUpdate();
} else if (Data.magiskVersionCode < Data.remoteMagiskVersionCode) {
Notifications.magiskUpdate();
}
} }
} }

View File

@ -1,8 +1,5 @@
package com.topjohnwu.magisk.utils; 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.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@ -15,25 +12,29 @@ import com.topjohnwu.magisk.ClassMap;
import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.services.UpdateCheckService; 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 class AppUtils {
public static void setupUpdateCheck() { public static void scheduleUpdateCheck() {
App app = App.self; if (App.self.prefs.getBoolean(Const.Key.CHECK_UPDATES, true)) {
JobScheduler scheduler = (JobScheduler) app.getSystemService(Context.JOB_SCHEDULER_SERVICE); Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
if (app.prefs.getBoolean(Const.Key.CHECK_UPDATES, true)) { .build();
if (scheduler.getAllPendingJobs().isEmpty() || PeriodicWorkRequest request = new PeriodicWorkRequest
Const.UPDATE_SERVICE_VER > app.prefs.getInt(Const.Key.UPDATE_SERVICE_VER, -1)) { .Builder(ClassMap.get(UpdateCheckService.class), 12, TimeUnit.HOURS)
ComponentName service = new ComponentName(app, ClassMap.get(UpdateCheckService.class)); .setConstraints(constraints)
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service) .build();
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) WorkManager.getInstance().enqueueUniquePeriodicWork(Const.ID.CHECK_MAGISK_UPDATE_WORKER_ID,
.setPersisted(true) ExistingPeriodicWorkPolicy.REPLACE, request);
.setPeriodic(8 * 60 * 60 * 1000)
.build();
scheduler.schedule(info);
}
} else { } 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 int HIDE_MANAGER_NOTIFICATION_ID = 8;
public static final String UPDATE_NOTIFICATION_CHANNEL = "update"; public static final String UPDATE_NOTIFICATION_CHANNEL = "update";
public static final String PROGRESS_NOTIFICATION_CHANNEL = "progress"; public static final String PROGRESS_NOTIFICATION_CHANNEL = "progress";
public static final String CHECK_MAGISK_UPDATE_WORKER_ID = "magisk_update";
} }
public static class Url { public static class Url {

View File

@ -5,6 +5,7 @@ import com.topjohnwu.core.Const;
import com.topjohnwu.core.Data; import com.topjohnwu.core.Data;
import com.topjohnwu.core.utils.Topic; import com.topjohnwu.core.utils.Topic;
import com.topjohnwu.net.Networking; import com.topjohnwu.net.Networking;
import com.topjohnwu.net.Request;
import com.topjohnwu.net.ResponseListener; import com.topjohnwu.net.ResponseListener;
import org.json.JSONException; import org.json.JSONException;
@ -40,26 +41,31 @@ public class CheckUpdates {
} }
} }
public static void check(Runnable cb) { private static Request getRequest() {
String url; String url;
switch (Data.updateChannel) { switch (Data.updateChannel) {
case Const.Value.STABLE_CHANNEL:
url = Const.Url.STABLE_URL;
break;
case Const.Value.BETA_CHANNEL: case Const.Value.BETA_CHANNEL:
url = Const.Url.BETA_URL; url = Const.Url.BETA_URL;
break; break;
case Const.Value.CUSTOM_CHANNEL: case Const.Value.CUSTOM_CHANNEL:
url = App.self.prefs.getString(Const.Key.CUSTOM_CHANNEL, ""); url = App.self.prefs.getString(Const.Key.CUSTOM_CHANNEL, "");
break; break;
case Const.Value.STABLE_CHANNEL:
default: default:
return; url = Const.Url.STABLE_URL;
break;
} }
Networking.get(url).getAsJSONObject(new UpdateListener(cb)); return Networking.get(url);
} }
public static void check() { 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> { private static class UpdateListener implements ResponseListener<JSONObject> {