优化定时任务调度

This commit is contained in:
TonyJiangWJ 2020-10-23 19:39:27 +08:00
parent fa0a16dee3
commit a8bc506a7b
3 changed files with 20 additions and 194 deletions

View File

@ -42,6 +42,11 @@ public class TimedTaskScheduler {
public void scheduleTaskIfNeeded(Context context, TimedTask timedTask, boolean force) {
long millis = timedTask.getNextTime();
if (millis <= System.currentTimeMillis()) {
Log.d(LOG_TAG, "task out date, just run it: " + timedTask);
runTask(context, timedTask);
return;
}
if ((!force && timedTask.isScheduled()) || millis - System.currentTimeMillis() > SCHEDULE_TASK_MIN_TIME) {
return;
}
@ -63,10 +68,6 @@ public class TimedTaskScheduler {
long timeWindow = millis - System.currentTimeMillis();
timedTask.setScheduled(true);
TimedTaskManager.getInstance().updateTaskWithoutReScheduling(timedTask);
if (timeWindow <= 0) {
runTask(context, timedTask);
return;
}
Log.d(LOG_TAG, "schedule task: task = " + timedTask + ", millis = " + millis + ", timeWindow = " + timeWindow);

View File

@ -1,182 +0,0 @@
package org.autojs.autojs.timing;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.autojs.autojs.external.ScriptIntents;
import org.jetbrains.annotations.NotNull;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import androidx.annotation.NonNull;
import androidx.work.Data;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ExistingWorkPolicy;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkInfo;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created by Stardust on 2017/11/27.
*/
public class TimedTaskScheduler_Bak {
private static final String LOG_TAG = "TimedTaskScheduler";
private static final long SCHEDULE_TASK_MIN_TIME = TimeUnit.DAYS.toMillis(2);
protected static final String JOB_TAG_CHECK_TASKS = "checkTasks";
@SuppressLint("CheckResult")
public static void checkTasks(Context context, boolean force) {
Log.d(LOG_TAG, "check tasks: force = " + force);
TimedTaskManager.getInstance().getAllTasks()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(timedTask -> scheduleTaskIfNeeded(context, timedTask, force));
}
public static void scheduleTaskIfNeeded(Context context, TimedTask timedTask, boolean force) {
long millis = timedTask.getNextTime();
if ((!force && timedTask.isScheduled()) || millis - System.currentTimeMillis() > SCHEDULE_TASK_MIN_TIME) {
return;
}
scheduleTask(context, timedTask, millis, force);
TimedTaskManager.getInstance()
.notifyTaskScheduled(timedTask);
}
private synchronized static void scheduleTask(Context context, TimedTask timedTask, long millis, boolean force) {
if (!force && timedTask.isScheduled()) {
return;
}
long timeWindow = millis - System.currentTimeMillis();
timedTask.setScheduled(true);
TimedTaskManager.getInstance().updateTaskWithoutReScheduling(timedTask);
if (timeWindow <= 0) {
runTask(context, timedTask);
return;
}
Log.d(LOG_TAG, "schedule task: task = " + timedTask + ", millis = " + millis + ", timeWindow = " + timeWindow);
WorkManager.getInstance(context).enqueueUniqueWork(String.valueOf(timedTask.getId()),
ExistingWorkPolicy.KEEP,
new OneTimeWorkRequest
.Builder(TimedTaskWorker.class)
.addTag(String.valueOf(timedTask.getId()))
.setInputData(new Data.Builder().putLong("taskId", timedTask.getId()).build())
.setInitialDelay(timeWindow, TimeUnit.MILLISECONDS)
.build()
);
}
public static void cancel(TimedTask timedTask, Context context) {
WorkManager.getInstance(context).cancelAllWorkByTag(String.valueOf(timedTask.getId()));
Log.d(LOG_TAG, "cancel task: task = " + timedTask);
}
public static void init(@NotNull Context context) {
createCheckWorker(context, 20);
checkTasks(context, true);
}
private static void createCheckWorker(Context context, int delay) {
PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
.Builder(CheckTaskWorker.class, 20, TimeUnit.MINUTES);
if (delay > 0) {
builder.setInitialDelay(delay, TimeUnit.MINUTES);
}
Log.d(LOG_TAG, "创建定期检测任务");
WorkManager.getInstance(context).enqueueUniquePeriodicWork(JOB_TAG_CHECK_TASKS, ExistingPeriodicWorkPolicy.REPLACE, builder.build());
}
protected 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());
ensureCheckTaskWorks(context);
}
public static void ensureCheckTaskWorks(Context context) {
try {
List<WorkInfo> workInfoList = WorkManager.getInstance(context).getWorkInfosForUniqueWork(JOB_TAG_CHECK_TASKS).get();
boolean workFine = false;
if (workInfoList != null && workInfoList.size() > 0) {
for (WorkInfo workInfo : workInfoList) {
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
workFine = true;
}
}
}
// 校验是否有超时未执行的
boolean anyLost = TimedTaskManager.getInstance().getAllTasks().any(task -> task.getMillis() < System.currentTimeMillis()).blockingGet();
if (!workFine || anyLost) {
createCheckWorker(context, 0);
checkTasks(context, true);
}
} catch (Exception e) {
Log.e(LOG_TAG, "获取定时校验任务失败");
}
}
public static class TimedTaskWorker extends Worker {
private static final String DONE_TIME = "DONE_TIME";
public TimedTaskWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
long id = this.getInputData().getLong("taskId", -1);
if (id > -1) {
TimedTask task = TimedTaskManager.getInstance().getTimedTask(id);
Log.d(LOG_TAG, "onRunJob: id = " + id + ", task = " + task + ", currentMillis=" + System.currentTimeMillis());
if (task == null) {
return Result.failure();
}
runTask(getApplicationContext(), task);
return Result.success(
new Data.Builder()
.putString(DONE_TIME, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(new Date()))
.build()
);
}
return Result.failure();
}
}
public static class CheckTaskWorker extends Worker {
public CheckTaskWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
checkTasks(getApplicationContext(), true);
return Result.success();
}
}
}

View File

@ -7,7 +7,6 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.SystemClock;
import android.util.Log;
@ -16,8 +15,7 @@ import com.stardust.app.GlobalAppContext;
import org.autojs.autojs.BuildConfig;
import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.external.receiver.StaticBroadcastReceiver;
import org.autojs.autojs.timing.TaskReceiver;
import org.autojs.autojs.external.ScriptIntents;
import org.autojs.autojs.timing.TimedTask;
import org.autojs.autojs.timing.TimedTaskManager;
@ -124,6 +122,11 @@ public class AlarmManagerProvider extends BroadcastReceiver implements WorkProvi
public void scheduleTaskIfNeeded(Context context, TimedTask timedTask, boolean force) {
long millis = timedTask.getNextTime();
if (millis <= System.currentTimeMillis()) {
autoJsLog( "task out date run:" + timedTask);
runTask(context, timedTask);
return;
}
if (!force && timedTask.isScheduled() || millis - System.currentTimeMillis() > SCHEDULE_TASK_MIN_TIME) {
return;
}
@ -136,11 +139,6 @@ public class AlarmManagerProvider extends BroadcastReceiver implements WorkProvi
return;
}
autoJsLog( "schedule task:" + timedTask);
if (millis <= System.currentTimeMillis()) {
autoJsLog( "task out date run:" + timedTask);
GlobalAppContext.get().sendBroadcast(timedTask.createIntent());
return;
}
if (force) {
cancel(timedTask);
}
@ -148,6 +146,15 @@ public class AlarmManagerProvider extends BroadcastReceiver implements WorkProvi
}
public 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());
// 如果队列中有任务正在等待直接取消
cancel(task);
}
private void setExactCompat(AlarmManager alarmManager, PendingIntent op, long millis) {
int type = AlarmManager.RTC_WAKEUP;
long gapMillis = millis - System.currentTimeMillis();