From e09966505c0b46694d0b6dcf1b2cfb286ceb3437 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Sun, 9 Sep 2018 15:10:31 +0800 Subject: [PATCH] opt(timing): request for ignore battery optimization; optimize TimedTaskScheduler to schedule task --- .idea/caches/build_file_checksums.ser | Bin 733 -> 733 bytes app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 1 + app/src/main/java/org/autojs/autojs/App.java | 3 +- .../autojs/timing/TimedTaskManager.java | 6 +- .../autojs/timing/TimedTaskScheduler.java | 61 ++++++++++++------ .../autojs/autojs/ui/main/MainActivity.java | 2 + .../ui/timing/TimedTaskSettingActivity.java | 27 +++++++- 8 files changed, 73 insertions(+), 31 deletions(-) diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 0c7fa5df2dc2aeb8da7bcab468e9a919c6dfb52c..e0c1f728fde291a97167bb372ea15170f328e6ec 100644 GIT binary patch delta 36 ucmV+<0NelF1>FUZm;}8kgWQpvcM!b26VDD7`gf`l3Stv2FUZm;|}GJ$I3ucMwDnfheX=`^lu8O=~VtPLi`D0lEPyp$}>R diff --git a/app/build.gradle b/app/build.gradle index 050627bc..96ddc614 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "org.autojs.autojs" minSdkVersion 17 targetSdkVersion 23 - versionCode 410 - versionName "4.0.2 Alpha5" + versionCode 411 + versionName "4.0.2 Alpha6" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true ndk { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ad608775..0964d242 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,6 +12,7 @@ + diff --git a/app/src/main/java/org/autojs/autojs/App.java b/app/src/main/java/org/autojs/autojs/App.java index e28e0cdb..6ecd91c7 100644 --- a/app/src/main/java/org/autojs/autojs/App.java +++ b/app/src/main/java/org/autojs/autojs/App.java @@ -27,7 +27,6 @@ import org.autojs.autojs.tool.CrashHandler; import org.autojs.autojs.ui.error.ErrorReportActivity; import com.stardust.theme.ThemeColor; import com.stardust.theme.ThemeColorManager; -import com.stardust.util.UiHandler; import java.lang.ref.WeakReference; @@ -81,7 +80,7 @@ public class App extends MultiDexApplication { GlobalKeyObserver.init(); } setupDrawableImageLoader(); - TimedTaskScheduler.setupRepeating(this); + TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(this); MobileAds.initialize(this, Constants.ADMOB_APP_ID); } 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 8efeee9b..a93345ee 100644 --- a/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java +++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.java @@ -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.ModelAdapter; import com.stardust.app.GlobalAppContext; -import org.autojs.autojs.App; + import org.autojs.autojs.storage.database.ModelChange; -import org.autojs.autojs.storage.database.TimedTaskDatabase; import java.util.List; -import io.reactivex.Completable; import io.reactivex.Flowable; import io.reactivex.Observable; import io.reactivex.schedulers.Schedulers; @@ -53,7 +51,7 @@ public class TimedTaskManager { if (action == BaseModel.Action.DELETE && countTasks() == 0) { TimedTaskScheduler.stopRtcRepeating(mContext); } else if (action == BaseModel.Action.INSERT) { - TimedTaskScheduler.startRtcRepeatingIfNeeded(mContext); + TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(mContext); } } 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 41e86084..295c9614 100644 --- a/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.java +++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.java @@ -1,16 +1,14 @@ package org.autojs.autojs.timing; +import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Build; -import android.os.Parcelable; import android.util.Log; -import com.twofortyfouram.spackle.AlarmManagerCompat; - import java.util.concurrent.TimeUnit; 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"; private static final String LOG_TAG = "TimedTaskScheduler"; - private static final int REQUEST_CODE = 4000; - private static final long INTERVAL = 60 * 1000; + 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; + private static long mNextRtcWakeupMillis = -1; @Override public void onReceive(Context context, Intent intent) { - Log.d(LOG_TAG, "onReceive"); + Log.d(LOG_TAG, "onReceiveRtcWakeup"); checkTasks(context); + setupNextRtcWakeup(context, System.currentTimeMillis() + INTERVAL); } - public static void checkTasks(Context context) { + @SuppressLint("CheckResult") + private static void checkTasks(Context context) { TimedTaskManager.getInstance().getAllTasks() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -63,7 +65,13 @@ public class TimedTaskScheduler extends BroadcastReceiver { assert alarmManager != null; // FIXME: 2017/11/28 requestCode may > 65535 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); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 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) { - startRtcRepeatingIfNeeded(context); + + public static void checkTasksRepeatedlyIfNeeded(Context context) { + if (TimedTaskManager.getInstance().countTasks() > 0 && mNextRtcWakeupMillis > 0) { + setupNextRtcWakeup(context, System.currentTimeMillis() + 5000); } } - - public static void startRtcRepeatingIfNeeded(Context context) { - Log.v(LOG_TAG, "startRtcRepeating"); - AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, - INTERVAL, createTaskCheckPendingIntent(context)); + 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); + mNextRtcWakeupMillis = millis; } 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)); } public static void stopRtcRepeating(Context context) { Log.v(LOG_TAG, "stopRtcRepeating"); - AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + AlarmManager alarmManager = getAlarmManager(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) { - return PendingIntent.getBroadcast(context, REQUEST_CODE, - new Intent(TimedTaskScheduler.ACTION_CHECK_TASK), PendingIntent.FLAG_UPDATE_CURRENT); + if (sCheckTasksPendingIntent == null) { + sCheckTasksPendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_CHECK_TASK_REPEATEDLY, + new Intent(TimedTaskScheduler.ACTION_CHECK_TASK), PendingIntent.FLAG_UPDATE_CURRENT); + } + return sCheckTasksPendingIntent; } } diff --git a/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java b/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java index 5fd38696..aee04a89 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.java @@ -3,6 +3,7 @@ package org.autojs.autojs.ui.main; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; +import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; @@ -32,6 +33,7 @@ import org.autojs.autojs.Pref; import org.autojs.autojs.R; import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.storage.file.StorageFileProvider; +import org.autojs.autojs.timing.TimedTaskManager; import org.autojs.autojs.tool.AccessibilityServiceTool; import org.autojs.autojs.ui.BaseActivity; import org.autojs.autojs.ui.common.NotAskAgainDialog; diff --git a/app/src/main/java/org/autojs/autojs/ui/timing/TimedTaskSettingActivity.java b/app/src/main/java/org/autojs/autojs/ui/timing/TimedTaskSettingActivity.java index 0a09569e..b77e98d6 100644 --- a/app/src/main/java/org/autojs/autojs/ui/timing/TimedTaskSettingActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/timing/TimedTaskSettingActivity.java @@ -1,12 +1,19 @@ package org.autojs.autojs.ui.timing; +import android.Manifest; import android.app.DatePickerDialog; import android.app.TimePickerDialog; +import android.content.Intent; +import android.net.Uri; import android.os.Build; 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.v7.widget.Toolbar; import android.text.TextUtils; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; 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 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) Toolbar mToolbar; @@ -199,7 +208,7 @@ public class TimedTaskSettingActivity extends BaseActivity { LocalDate date = DATE_FORMATTER.parseLocalDate(mDisposableTaskDate.getText().toString()); new DatePickerDialog(this, (view, 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(); } @@ -254,12 +263,26 @@ public class TimedTaskSettingActivity extends BaseActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { 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 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() { TimedTask task = createTimedTask(); if (task == null)