diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
index 0c7fa5df..e0c1f728 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 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)