opt(timing): request for ignore battery optimization; optimize TimedTaskScheduler to schedule task

This commit is contained in:
hyb1996
2018-09-09 15:10:31 +08:00
parent f62958655a
commit e09966505c
8 changed files with 73 additions and 31 deletions

Binary file not shown.

View File

@@ -8,8 +8,8 @@ android {
applicationId "org.autojs.autojs" applicationId "org.autojs.autojs"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 410 versionCode 411
versionName "4.0.2 Alpha5" versionName "4.0.2 Alpha6"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {

View File

@@ -12,6 +12,7 @@
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<!-- 非Auto.js运行必需不会主动申请某些脚本可以自行申请--> <!-- 非Auto.js运行必需不会主动申请某些脚本可以自行申请-->

View File

@@ -27,7 +27,6 @@ import org.autojs.autojs.tool.CrashHandler;
import org.autojs.autojs.ui.error.ErrorReportActivity; import org.autojs.autojs.ui.error.ErrorReportActivity;
import com.stardust.theme.ThemeColor; import com.stardust.theme.ThemeColor;
import com.stardust.theme.ThemeColorManager; import com.stardust.theme.ThemeColorManager;
import com.stardust.util.UiHandler;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@@ -81,7 +80,7 @@ public class App extends MultiDexApplication {
GlobalKeyObserver.init(); GlobalKeyObserver.init();
} }
setupDrawableImageLoader(); setupDrawableImageLoader();
TimedTaskScheduler.setupRepeating(this); TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(this);
MobileAds.initialize(this, Constants.ADMOB_APP_ID); MobileAds.initialize(this, Constants.ADMOB_APP_ID);
} }

View File

@@ -12,13 +12,11 @@ import com.raizlabs.android.dbflow.sql.language.SQLite;
import com.raizlabs.android.dbflow.structure.BaseModel; import com.raizlabs.android.dbflow.structure.BaseModel;
import com.raizlabs.android.dbflow.structure.ModelAdapter; import com.raizlabs.android.dbflow.structure.ModelAdapter;
import com.stardust.app.GlobalAppContext; import com.stardust.app.GlobalAppContext;
import org.autojs.autojs.App;
import org.autojs.autojs.storage.database.ModelChange; import org.autojs.autojs.storage.database.ModelChange;
import org.autojs.autojs.storage.database.TimedTaskDatabase;
import java.util.List; import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Flowable; import io.reactivex.Flowable;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
@@ -53,7 +51,7 @@ public class TimedTaskManager {
if (action == BaseModel.Action.DELETE && countTasks() == 0) { if (action == BaseModel.Action.DELETE && countTasks() == 0) {
TimedTaskScheduler.stopRtcRepeating(mContext); TimedTaskScheduler.stopRtcRepeating(mContext);
} else if (action == BaseModel.Action.INSERT) { } else if (action == BaseModel.Action.INSERT) {
TimedTaskScheduler.startRtcRepeatingIfNeeded(mContext); TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(mContext);
} }
} }

View File

@@ -1,16 +1,14 @@
package org.autojs.autojs.timing; package org.autojs.autojs.timing;
import android.annotation.SuppressLint;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.Parcelable;
import android.util.Log; import android.util.Log;
import com.twofortyfouram.spackle.AlarmManagerCompat;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -25,17 +23,21 @@ public class TimedTaskScheduler extends BroadcastReceiver {
public static final String ACTION_CHECK_TASK = "com.stardust.autojs.action.check_task"; public static final String ACTION_CHECK_TASK = "com.stardust.autojs.action.check_task";
private static final String LOG_TAG = "TimedTaskScheduler"; private static final String LOG_TAG = "TimedTaskScheduler";
private static final int REQUEST_CODE = 4000; private static final int REQUEST_CODE_CHECK_TASK_REPEATEDLY = 4000;
private static final long INTERVAL = 60 * 1000; private static final long INTERVAL = TimeUnit.MINUTES.toMillis(1);
private static final long ONE_HOUR = TimeUnit.HOURS.toMillis(1); private static final long ONE_HOUR = TimeUnit.HOURS.toMillis(1);
private static PendingIntent sCheckTasksPendingIntent;
private static long mNextRtcWakeupMillis = -1;
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG, "onReceive"); Log.d(LOG_TAG, "onReceiveRtcWakeup");
checkTasks(context); checkTasks(context);
setupNextRtcWakeup(context, System.currentTimeMillis() + INTERVAL);
} }
public static void checkTasks(Context context) { @SuppressLint("CheckResult")
private static void checkTasks(Context context) {
TimedTaskManager.getInstance().getAllTasks() TimedTaskManager.getInstance().getAllTasks()
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@@ -63,7 +65,13 @@ public class TimedTaskScheduler extends BroadcastReceiver {
assert alarmManager != null; assert alarmManager != null;
// FIXME: 2017/11/28 requestCode may > 65535 // FIXME: 2017/11/28 requestCode may > 65535
PendingIntent op = timedTask.createPendingIntent(context); PendingIntent op = timedTask.createPendingIntent(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 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); alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(millis, null), op);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, millis, op); alarmManager.setExact(AlarmManager.RTC_WAKEUP, millis, op);
@@ -72,35 +80,46 @@ public class TimedTaskScheduler extends BroadcastReceiver {
} }
} }
public static void setupRepeating(Context context) {
if (TimedTaskManager.getInstance().countTasks() > 0) { public static void checkTasksRepeatedlyIfNeeded(Context context) {
startRtcRepeatingIfNeeded(context); if (TimedTaskManager.getInstance().countTasks() > 0 && mNextRtcWakeupMillis > 0) {
setupNextRtcWakeup(context, System.currentTimeMillis() + 5000);
} }
} }
private static void setupNextRtcWakeup(Context context, long millis) {
public static void startRtcRepeatingIfNeeded(Context context) { Log.v(LOG_TAG, "setupNextRtcWakeup: at " + millis);
Log.v(LOG_TAG, "startRtcRepeating"); if (millis <= 0) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); throw new IllegalArgumentException("millis <= 0: " + millis);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, }
INTERVAL, createTaskCheckPendingIntent(context)); AlarmManager alarmManager = getAlarmManager(context);
setExactCompat(alarmManager, createTaskCheckPendingIntent(context), millis);
mNextRtcWakeupMillis = millis;
} }
public static void cancel(Context context, TimedTask timedTask) { public static void cancel(Context context, TimedTask timedTask) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = getAlarmManager(context);
alarmManager.cancel(timedTask.createPendingIntent(context)); alarmManager.cancel(timedTask.createPendingIntent(context));
} }
public static void stopRtcRepeating(Context context) { public static void stopRtcRepeating(Context context) {
Log.v(LOG_TAG, "stopRtcRepeating"); Log.v(LOG_TAG, "stopRtcRepeating");
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = getAlarmManager(context);
alarmManager.cancel(createTaskCheckPendingIntent(context)); alarmManager.cancel(createTaskCheckPendingIntent(context));
}
private static AlarmManager getAlarmManager(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
assert alarmManager != null;
return alarmManager;
} }
private static PendingIntent createTaskCheckPendingIntent(Context context) { private static PendingIntent createTaskCheckPendingIntent(Context context) {
return PendingIntent.getBroadcast(context, REQUEST_CODE, if (sCheckTasksPendingIntent == null) {
new Intent(TimedTaskScheduler.ACTION_CHECK_TASK), PendingIntent.FLAG_UPDATE_CURRENT); sCheckTasksPendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_CHECK_TASK_REPEATEDLY,
new Intent(TimedTaskScheduler.ACTION_CHECK_TASK), PendingIntent.FLAG_UPDATE_CURRENT);
}
return sCheckTasksPendingIntent;
} }
} }

View File

@@ -3,6 +3,7 @@ package org.autojs.autojs.ui.main;
import android.Manifest; import android.Manifest;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
@@ -32,6 +33,7 @@ import org.autojs.autojs.Pref;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.storage.file.StorageFileProvider; import org.autojs.autojs.storage.file.StorageFileProvider;
import org.autojs.autojs.timing.TimedTaskManager;
import org.autojs.autojs.tool.AccessibilityServiceTool; import org.autojs.autojs.tool.AccessibilityServiceTool;
import org.autojs.autojs.ui.BaseActivity; import org.autojs.autojs.ui.BaseActivity;
import org.autojs.autojs.ui.common.NotAskAgainDialog; import org.autojs.autojs.ui.common.NotAskAgainDialog;

View File

@@ -1,12 +1,19 @@
package org.autojs.autojs.ui.timing; package org.autojs.autojs.ui.timing;
import android.Manifest;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
import android.app.TimePickerDialog; import android.app.TimePickerDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@@ -54,6 +61,8 @@ public class TimedTaskSettingActivity extends BaseActivity {
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormat.forPattern("HH:mm"); private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormat.forPattern("HH:mm");
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yy-MM-dd"); private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yy-MM-dd");
private static final int REQUEST_CODE_IGNORE_BATTERY = 27101;
private static final String LOG_TAG = "TimedTaskSettings";
@ViewById(R.id.toolbar) @ViewById(R.id.toolbar)
Toolbar mToolbar; Toolbar mToolbar;
@@ -199,7 +208,7 @@ public class TimedTaskSettingActivity extends BaseActivity {
LocalDate date = DATE_FORMATTER.parseLocalDate(mDisposableTaskDate.getText().toString()); LocalDate date = DATE_FORMATTER.parseLocalDate(mDisposableTaskDate.getText().toString());
new DatePickerDialog(this, (view, year, month, dayOfMonth) -> new DatePickerDialog(this, (view, year, month, dayOfMonth) ->
mDisposableTaskDate.setText(DATE_FORMATTER.print(new LocalDate(year, month, dayOfMonth))) mDisposableTaskDate.setText(DATE_FORMATTER.print(new LocalDate(year, month, dayOfMonth)))
, date.getYear(), date.getMonthOfYear(), date.getDayOfMonth()) , date.getYear(), date.getMonthOfYear() - 1, date.getDayOfMonth())
.show(); .show();
} }
@@ -254,12 +263,26 @@ public class TimedTaskSettingActivity extends BaseActivity {
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_done) { if (item.getItemId() == R.id.action_done) {
createOrUpdateTimedTask(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !((PowerManager) getSystemService(POWER_SERVICE)).isIgnoringBatteryOptimizations(getPackageName())) {
startActivityForResult(new Intent().setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
.setData(Uri.parse("package:" + getPackageName())), REQUEST_CODE_IGNORE_BATTERY);
} else {
createOrUpdateTimedTask();
}
return true; return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_IGNORE_BATTERY) {
Log.d(LOG_TAG, "result code = " + requestCode);
createOrUpdateTimedTask();
}
super.onActivityResult(requestCode, resultCode, data);
}
private void createOrUpdateTimedTask() { private void createOrUpdateTimedTask() {
TimedTask task = createTimedTask(); TimedTask task = createTimedTask();
if (task == null) if (task == null)