diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
index d97f75ee..914e7a86 100644
Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ
diff --git a/app/build.gradle b/app/build.gradle
index 9dceffa8..3db21e1f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -153,6 +153,8 @@ dependencies {
implementation('com.afollestad.material-dialogs:commons:0.9.2.3', {
exclude group: 'com.android.support'
})
+ // Android job
+ implementation 'com.evernote:android-job:1.2.6'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'
// Optional, if you use support library fragments:
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 816de626..447695b0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -300,13 +300,6 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/org/autojs/autojs/App.kt b/app/src/main/java/org/autojs/autojs/App.kt
index ff06a8d7..2dde69f3 100644
--- a/app/src/main/java/org/autojs/autojs/App.kt
+++ b/app/src/main/java/org/autojs/autojs/App.kt
@@ -13,6 +13,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
+import com.evernote.android.job.JobRequest
import com.flurry.android.FlurryAgent
import com.squareup.leakcanary.LeakCanary
import com.stardust.app.GlobalAppContext
@@ -84,7 +85,7 @@ class App : MultiDexApplication() {
GlobalKeyObserver.init()
}
setupDrawableImageLoader()
- TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(this)
+ TimedTaskScheduler.init(this)
initDynamicBroadcastReceivers()
}
diff --git a/app/src/main/java/org/autojs/autojs/storage/database/TimedTaskDatabase.java b/app/src/main/java/org/autojs/autojs/storage/database/TimedTaskDatabase.java
index 868de3df..b6f343e5 100644
--- a/app/src/main/java/org/autojs/autojs/storage/database/TimedTaskDatabase.java
+++ b/app/src/main/java/org/autojs/autojs/storage/database/TimedTaskDatabase.java
@@ -21,6 +21,7 @@ public class TimedTaskDatabase extends Database {
@Override
protected ContentValues asContentValues(TimedTask model) {
ContentValues values = new ContentValues();
+ values.put("id", model.getId());
values.put("time", model.getTimeFlag());
values.put("scheduled", model.isScheduled());
values.put("delay", model.getDelay());
@@ -34,7 +35,7 @@ public class TimedTaskDatabase extends Database {
@Override
protected TimedTask createModelFromCursor(Cursor cursor) {
TimedTask task = new TimedTask();
- task.setId(cursor.getInt(0));
+ task.setId(cursor.getLong(0));
task.setTimeFlag(cursor.getLong(1));
task.setScheduled(cursor.getInt(2) != 0);
task.setDelay(cursor.getLong(3));
diff --git a/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java b/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java
index 5f1dada0..4ad701ac 100644
--- a/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java
+++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java
@@ -17,6 +17,7 @@ import java.util.List;
import io.reactivex.Flowable;
import io.reactivex.Observable;
+import io.reactivex.functions.Consumer;
/**
* Created by Stardust on 2017/11/27.
@@ -41,14 +42,6 @@ public class TimedTaskManager {
mContext = context;
mTimedTaskDatabase = new TimedTaskDatabase(context);
mIntentTaskDatabase = new IntentTaskDatabase(context);
- mTimedTaskDatabase.getModelChange().subscribe(change -> {
- int action = change.getAction();
- if (action == ModelChange.DELETE && countTasks() == 0) {
- TimedTaskScheduler.stopRtcRepeating(mContext);
- } else if (action == ModelChange.INSERT) {
- TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(mContext);
- }
- });
}
@SuppressLint("CheckResult")
@@ -76,15 +69,17 @@ public class TimedTaskManager {
@SuppressLint("CheckResult")
public void addTask(TimedTask timedTask) {
mTimedTaskDatabase.insert(timedTask)
- .subscribe(Observers.emptyConsumer(), Throwable::printStackTrace);;
- TimedTaskScheduler.scheduleTaskIfNeeded(mContext, timedTask);
+ .subscribe(id -> {
+ timedTask.setId(id);
+ TimedTaskScheduler.scheduleTaskIfNeeded(mContext, timedTask);
+ }, Throwable::printStackTrace);
}
@SuppressLint("CheckResult")
public void addTask(IntentTask intentTask) {
mIntentTaskDatabase.insert(intentTask)
.subscribe(i -> {
- if(!TextUtils.isEmpty(intentTask.getAction())){
+ if (!TextUtils.isEmpty(intentTask.getAction())) {
App.Companion.getApp().getDynamicBroadcastReceivers()
.register(intentTask);
}
@@ -95,7 +90,7 @@ public class TimedTaskManager {
public void removeTask(IntentTask intentTask) {
mIntentTaskDatabase.delete(intentTask)
.subscribe(i -> {
- if(!TextUtils.isEmpty(intentTask.getAction())){
+ if (!TextUtils.isEmpty(intentTask.getAction())) {
App.Companion.getApp().getDynamicBroadcastReceivers()
.unregister(intentTask.getAction());
}
@@ -139,11 +134,17 @@ public class TimedTaskManager {
TimedTaskScheduler.scheduleTaskIfNeeded(mContext, task);
}
+ @SuppressLint("CheckResult")
+ public void updateTaskWithoutReScheduling(TimedTask task) {
+ mTimedTaskDatabase.update(task)
+ .subscribe(Observers.emptyConsumer(), Throwable::printStackTrace);
+ }
+
@SuppressLint("CheckResult")
public void updateTask(IntentTask task) {
mIntentTaskDatabase.update(task)
.subscribe(i -> {
- if(i > 0 && !TextUtils.isEmpty(task.getAction())){
+ if (i > 0 && !TextUtils.isEmpty(task.getAction())) {
App.Companion.getApp().getDynamicBroadcastReceivers()
.register(task);
}
diff --git a/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.java b/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.java
index 62356666..15910892 100644
--- a/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.java
+++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.java
@@ -3,6 +3,8 @@ package org.autojs.autojs.timing;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -10,8 +12,22 @@ import android.os.Build;
import android.provider.AlarmClock;
import android.util.Log;
+import com.evernote.android.job.Job;
+import com.evernote.android.job.JobCreator;
+import com.evernote.android.job.JobManager;
+import com.evernote.android.job.JobRequest;
+import com.evernote.android.job.util.support.PersistableBundleCompat;
+
+import org.autojs.autojs.App;
+import org.autojs.autojs.external.ScriptIntents;
+import org.autojs.autojs.storage.database.TimedTaskDatabase;
+import org.jetbrains.annotations.NotNull;
+
import java.util.concurrent.TimeUnit;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@@ -20,24 +36,17 @@ import io.reactivex.schedulers.Schedulers;
* Created by Stardust on 2017/11/27.
*/
-public class TimedTaskScheduler extends BroadcastReceiver {
+public class TimedTaskScheduler {
- public static final String ACTION_CHECK_TASK = "com.stardust.autojs.action.check_task";
private static final String LOG_TAG = "TimedTaskScheduler";
- private static final int REQUEST_CODE_CHECK_TASK_REPEATEDLY = 4000;
- private static final long INTERVAL = TimeUnit.MINUTES.toMillis(1);
private static final long ONE_HOUR = TimeUnit.HOURS.toMillis(1);
- private static PendingIntent sCheckTasksPendingIntent;
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d(LOG_TAG, "onReceiveRtcWakeup");
- checkTasks(context);
- setupNextRtcWakeup(context, System.currentTimeMillis() + INTERVAL);
- }
+ private static final String JOB_TAG_CHECK_TASKS = "checkTasks";
+
@SuppressLint("CheckResult")
public static void checkTasks(Context context) {
+ Log.d(LOG_TAG, "check tasks");
TimedTaskManager.getInstance().getAllTasks()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@@ -52,73 +61,89 @@ public class TimedTaskScheduler extends BroadcastReceiver {
scheduleTask(context, timedTask, millis);
TimedTaskManager.getInstance()
.notifyTaskScheduled(timedTask);
-
}
-
- private static void scheduleTask(Context context, TimedTask timedTask, long millis) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- if (millis <= System.currentTimeMillis()) {
- context.sendBroadcast(timedTask.createIntent());
+ private synchronized static void scheduleTask(Context context, TimedTask timedTask, long millis) {
+ if (timedTask.isScheduled()) {
return;
}
- assert alarmManager != null;
- // FIXME: 2017/11/28 requestCode may > 65535
- PendingIntent op = timedTask.createPendingIntent(context);
- setExactCompat(alarmManager, op, millis);
- }
-
- private static void setExactCompat(AlarmManager alarmManager, PendingIntent op, long millis) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, millis, op);
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(millis, null), op);
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- alarmManager.setExact(AlarmManager.RTC_WAKEUP, millis, op);
- } else {
- alarmManager.set(AlarmManager.RTC_WAKEUP, millis, op);
+ long timeWindow = millis - System.currentTimeMillis();
+ Log.d(LOG_TAG, "schedule task: task = " + timedTask + ", millis = " + millis + ", timeWindow = " + timeWindow);
+ timedTask.setScheduled(true);
+ TimedTaskManager.getInstance().updateTaskWithoutReScheduling(timedTask);
+ if (timeWindow <= 0) {
+ runTask(context, timedTask);
+ return;
}
+ new JobRequest.Builder(String.valueOf(timedTask.getId()))
+ .setExact(timeWindow)
+ .build()
+ .schedule();
}
-
- public static void checkTasksRepeatedlyIfNeeded(Context context) {
- if (TimedTaskManager.getInstance().countTasks() > 0) {
- setupNextRtcWakeup(context, System.currentTimeMillis() + 5000);
- }
- }
-
- private static void setupNextRtcWakeup(Context context, long millis) {
- Log.v(LOG_TAG, "setupNextRtcWakeup: at " + millis);
- if (millis <= 0) {
- throw new IllegalArgumentException("millis <= 0: " + millis);
- }
- AlarmManager alarmManager = getAlarmManager(context);
- setExactCompat(alarmManager, createTaskCheckPendingIntent(context), millis);
- }
-
-
public static void cancel(Context context, TimedTask timedTask) {
- AlarmManager alarmManager = getAlarmManager(context);
- alarmManager.cancel(timedTask.createPendingIntent(context));
+ Log.d(LOG_TAG, "cancel task: task = " + timedTask);
+ JobManager.instance().cancelAllForTag(String.valueOf(timedTask.getId()));
}
- public static void stopRtcRepeating(Context context) {
- Log.v(LOG_TAG, "stopRtcRepeating");
- AlarmManager alarmManager = getAlarmManager(context);
- alarmManager.cancel(createTaskCheckPendingIntent(context));
+ public static void init(@NotNull Context context) {
+ JobManager.create(context).addJobCreator(tag -> {
+ if (tag.equals(JOB_TAG_CHECK_TASKS)) {
+ return new CheckTasksJob(context);
+ } else {
+ return new TimedTaskJob(context);
+ }
+ });
+ new JobRequest.Builder(JOB_TAG_CHECK_TASKS)
+ .setPeriodic(TimeUnit.MINUTES.toMillis(20))
+ .build()
+ .scheduleAsync();
+ checkTasks(context);
}
- private static AlarmManager getAlarmManager(Context context) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- assert alarmManager != null;
- return alarmManager;
+ private static void runTask(Context context, TimedTask task) {
+ Log.d(LOG_TAG, "run task: task = " + task);
+ Intent intent = task.createIntent();
+ ScriptIntents.handleIntent(context, intent);
+ TimedTaskManager.getInstance().notifyTaskFinished(task.getId());
}
- private static PendingIntent createTaskCheckPendingIntent(Context context) {
- if (sCheckTasksPendingIntent == null) {
- sCheckTasksPendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_CHECK_TASK_REPEATEDLY,
- new Intent(TimedTaskScheduler.ACTION_CHECK_TASK), PendingIntent.FLAG_UPDATE_CURRENT);
+ private static class TimedTaskJob extends Job {
+
+ private final Context mContext;
+
+ TimedTaskJob(Context context) {
+ mContext = context;
+ }
+
+ @NonNull
+ @Override
+ protected Result onRunJob(@NonNull Params params) {
+ long id = Long.parseLong(params.getTag());
+ TimedTask task = TimedTaskManager.getInstance().getTimedTask(id);
+ Log.d(LOG_TAG, "onRunJob: id = " + id + ", task = " + task);
+ if (task == null) {
+ return Result.FAILURE;
+ }
+ runTask(mContext, task);
+ return Result.SUCCESS;
}
- return sCheckTasksPendingIntent;
}
+
+ private static class CheckTasksJob extends Job {
+ private final Context mContext;
+
+ CheckTasksJob(Context context) {
+ mContext = context;
+ }
+
+ @NonNull
+ @Override
+ protected Result onRunJob(@NonNull Params params) {
+ checkTasks(mContext);
+ return Result.SUCCESS;
+ }
+ }
+
+
}
diff --git a/common/release/output.json b/common/release/output.json
index cf367a7b..f27a16b1 100644
--- a/common/release/output.json
+++ b/common/release/output.json
@@ -1 +1 @@
-[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":453,"versionName":"4.1.0 Alpha3","enabled":true,"outputFile":"commonRelease-4.1.0 Alpha3.apk","fullName":"commonRelease","baseName":"common-release"},"path":"commonRelease-4.1.0 Alpha3.apk","properties":{}}]
\ No newline at end of file
+[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":454,"versionName":"4.1.0 Alpha4","enabled":true,"outputFile":"commonRelease-4.1.0 Alpha4.apk","fullName":"commonRelease","baseName":"common-release"},"path":"commonRelease-4.1.0 Alpha4.apk","properties":{}}]
\ No newline at end of file
diff --git a/project-versions.json b/project-versions.json
index 9ff25112..fc5c0f72 100644
--- a/project-versions.json
+++ b/project-versions.json
@@ -1,6 +1,6 @@
{
- "appVersionCode": 453,
- "appVersionName": "4.1.0 Alpha3",
+ "appVersionCode": 454,
+ "appVersionName": "4.1.0 Alpha4",
"target": 28,
"mini": 17,
"compile": 28,