mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-21 21:01:43 +08:00
feat: intent task
This commit is contained in:
parent
cf16739e75
commit
025e594a01
Binary file not shown.
@ -3,6 +3,7 @@
|
||||
<words>
|
||||
<w>capturer</w>
|
||||
<w>dismissable</w>
|
||||
<w>flowable</w>
|
||||
<w>interruptible</w>
|
||||
<w>loopers</w>
|
||||
<w>prefill</w>
|
||||
|
||||
@ -129,11 +129,6 @@ dependencies {
|
||||
exclude group: 'com.android.support'
|
||||
})
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0'
|
||||
//dbflow
|
||||
annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:4.1.2"
|
||||
compile "com.github.Raizlabs.DBFlow:dbflow-core:4.1.2"
|
||||
compile "com.github.Raizlabs.DBFlow:dbflow:4.1.2"
|
||||
compile "com.github.Raizlabs.DBFlow:dbflow-rx2:4.1.2"
|
||||
//joda time
|
||||
compile 'joda-time:joda-time:2.9.9'
|
||||
// Tasker Plugin
|
||||
|
||||
@ -133,10 +133,36 @@
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<receiver android:name="org.autojs.autojs.external.boot.BootCompleteReceiver" >
|
||||
<receiver android:name="org.autojs.autojs.external.receiver.StaticBroadcastReceiver" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||
<action android:name="android.intent.action.TIME_SET"/>
|
||||
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_ADDED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_CHANGED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_DATA_CLEARED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_RESTARTED"/>
|
||||
<action android:name="android.intent.action.UID_REMOVED"/>
|
||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
||||
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
|
||||
<action android:name="android.intent.action.ACTION_SHUTDOWN"/>
|
||||
<action android:name="android.intent.action.DATE_CHANGED"/>
|
||||
<action android:name="android.intent.action.DREAMING_STARTED"/>
|
||||
<action android:name="android.intent.action.DREAMING_STOPPED"/>
|
||||
<action android:name="android.intent.action.HEADSET_PLUG"/>
|
||||
<action android:name="android.intent.action.INPUT_METHOD_CHANGED"/>
|
||||
<action android:name="android.intent.action.LOCALE_CHANGED"/>
|
||||
<action android:name="android.intent.action.MEDIA_BUTTON"/>
|
||||
<action android:name="android.intent.action.MEDIA_CHECKING"/>
|
||||
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_FIRST_LAUNCH"/>
|
||||
<action android:name="android.intent.action.PROVIDER_CHANGED"/>
|
||||
<action android:name="android.intent.action.WALLPAPER_CHANGED"/>
|
||||
<action android:name="android.intent.action.USER_UNLOCKED"/>
|
||||
<action android:name="android.intent.action.USER_PRESENT"/>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
package org.autojs.autojs;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.multidex.MultiDex;
|
||||
import android.support.multidex.MultiDexApplication;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
@ -13,17 +11,17 @@ import android.widget.ImageView;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.flurry.android.FlurryAgent;
|
||||
import com.raizlabs.android.dbflow.config.DatabaseConfig;
|
||||
import com.raizlabs.android.dbflow.config.FlowConfig;
|
||||
import com.raizlabs.android.dbflow.config.FlowManager;
|
||||
import com.raizlabs.android.dbflow.runtime.DirectModelNotifier;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
import com.stardust.app.GlobalAppContext;
|
||||
import com.stardust.autojs.core.ui.inflater.ImageLoader;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Drawables;
|
||||
import com.stardust.theme.ThemeColor;
|
||||
import com.stardust.theme.ThemeColorManager;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.autojs.key.GlobalKeyObserver;
|
||||
import org.autojs.autojs.external.receiver.DynamicBroadcastReceiver;
|
||||
import org.autojs.autojs.network.GlideApp;
|
||||
import org.autojs.autojs.storage.database.IntentTaskDatabase;
|
||||
import org.autojs.autojs.storage.database.TimedTaskDatabase;
|
||||
@ -31,11 +29,6 @@ import org.autojs.autojs.timing.TimedTaskScheduler;
|
||||
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.tencent.bugly.crashreport.CrashReport;
|
||||
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
@ -48,6 +41,7 @@ public class App extends MultiDexApplication {
|
||||
private static final String BUGLY_APP_ID = "19b3607b53";
|
||||
|
||||
private static WeakReference<App> instance;
|
||||
private DynamicBroadcastReceiver mDynamicBroadcastReceiver;
|
||||
|
||||
public static App getApp() {
|
||||
return instance.get();
|
||||
@ -92,17 +86,10 @@ public class App extends MultiDexApplication {
|
||||
return;
|
||||
}
|
||||
//LeakCanary.install(this);
|
||||
|
||||
}
|
||||
|
||||
private void init() {
|
||||
FlowManager.init(FlowConfig.builder(this)
|
||||
.addDatabaseConfig(DatabaseConfig.builder(TimedTaskDatabase.class)
|
||||
.modelNotifier(DirectModelNotifier.get())
|
||||
.build())
|
||||
.addDatabaseConfig(DatabaseConfig.builder(IntentTaskDatabase.class)
|
||||
.modelNotifier(DirectModelNotifier.get())
|
||||
.build())
|
||||
.build());
|
||||
ThemeColorManager.setDefaultThemeColor(new ThemeColor(getResources().getColor(R.color.colorPrimary), getResources().getColor(R.color.colorPrimaryDark), getResources().getColor(R.color.colorAccent)));
|
||||
ThemeColorManager.init(this);
|
||||
AutoJs.initInstance(this);
|
||||
@ -111,6 +98,7 @@ public class App extends MultiDexApplication {
|
||||
}
|
||||
setupDrawableImageLoader();
|
||||
TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(this);
|
||||
mDynamicBroadcastReceiver = new DynamicBroadcastReceiver(this);
|
||||
}
|
||||
|
||||
private void setupDrawableImageLoader() {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package org.autojs.autojs.external.boot;
|
||||
package org.autojs.autojs.external.receiver;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
@ -7,6 +7,7 @@ import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.app.GlobalAppContext;
|
||||
import com.stardust.autojs.execution.ExecutionConfig;
|
||||
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
@ -17,23 +18,25 @@ import org.autojs.autojs.timing.TimedTaskManager;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class BootCompleteReceiver extends BroadcastReceiver {
|
||||
public class BaseBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String LOG_TAG = "BootCompleteReceiver";
|
||||
private static final String LOG_TAG = "BaseBroadcastReceiver";
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
|
||||
Log.i(LOG_TAG, "on boot complete");
|
||||
Log.d(LOG_TAG, "onReceive: action = " + intent.getAction() + ", intent = " + intent);
|
||||
try {
|
||||
TimedTaskManager.getInstance().getIntentTaskOfAction(intent.getAction())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(intentTask -> runTask(context, intent, intentTask), Throwable::printStackTrace);
|
||||
} catch (Exception e) {
|
||||
GlobalAppContext.toast(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void runTask(Context context, Intent intent, IntentTask task) {
|
||||
static void runTask(Context context, Intent intent, IntentTask task) {
|
||||
Log.d(LOG_TAG, "runTask: action = " + intent.getAction() + ", script = " + task.getScriptPath());
|
||||
ScriptFile file = new ScriptFile(task.getScriptPath());
|
||||
ExecutionConfig config = new ExecutionConfig();
|
||||
config.setArgument("intent", intent.clone());
|
||||
@ -45,4 +48,5 @@ public class BootCompleteReceiver extends BroadcastReceiver {
|
||||
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
79
app/src/main/java/org/autojs/autojs/external/receiver/DynamicBroadcastReceiver.java
vendored
Normal file
79
app/src/main/java/org/autojs/autojs/external/receiver/DynamicBroadcastReceiver.java
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
package org.autojs.autojs.external.receiver;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
|
||||
import org.autojs.autojs.BuildConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static android.content.Intent.ACTION_BATTERY_CHANGED;
|
||||
import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
|
||||
import static android.content.Intent.ACTION_DATE_CHANGED;
|
||||
import static android.content.Intent.ACTION_PACKAGES_SUSPENDED;
|
||||
import static android.content.Intent.ACTION_PACKAGES_UNSUSPENDED;
|
||||
import static android.content.Intent.ACTION_PACKAGE_ADDED;
|
||||
import static android.content.Intent.ACTION_PACKAGE_CHANGED;
|
||||
import static android.content.Intent.ACTION_PACKAGE_DATA_CLEARED;
|
||||
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
|
||||
import static android.content.Intent.ACTION_PACKAGE_RESTARTED;
|
||||
import static android.content.Intent.ACTION_POWER_CONNECTED;
|
||||
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
|
||||
import static android.content.Intent.ACTION_SHUTDOWN;
|
||||
import static android.content.Intent.ACTION_TIMEZONE_CHANGED;
|
||||
import static android.content.Intent.ACTION_TIME_CHANGED;
|
||||
import static android.content.Intent.ACTION_TIME_TICK;
|
||||
import static android.content.Intent.ACTION_UID_REMOVED;
|
||||
|
||||
public class DynamicBroadcastReceiver extends BaseBroadcastReceiver {
|
||||
|
||||
private static final List<String> DEFAULT_ACTIONS = new ArrayList<>(Arrays.asList(
|
||||
ACTION_TIME_TICK,
|
||||
ACTION_BATTERY_CHANGED,
|
||||
ACTION_CONFIGURATION_CHANGED
|
||||
));
|
||||
|
||||
static {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
DEFAULT_ACTIONS.addAll(Arrays.asList(
|
||||
ACTION_PACKAGES_SUSPENDED,
|
||||
ACTION_PACKAGES_UNSUSPENDED
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mRegistered = false;
|
||||
private final Set<String> mActions = new LinkedHashSet<>();
|
||||
private final Context mContext;
|
||||
|
||||
|
||||
public DynamicBroadcastReceiver(Context context) {
|
||||
mContext = context;
|
||||
register(DEFAULT_ACTIONS);
|
||||
}
|
||||
|
||||
public void register(List<String> actions) {
|
||||
int oldSize = mActions.size();
|
||||
mActions.addAll(actions);
|
||||
if (oldSize == mActions.size()) {
|
||||
return;
|
||||
}
|
||||
IntentFilter filter = new IntentFilter();
|
||||
for (String action : mActions) {
|
||||
filter.addAction(action);
|
||||
}
|
||||
if(mRegistered){
|
||||
mContext.unregisterReceiver(this);
|
||||
}
|
||||
mContext.registerReceiver(this, filter);
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
}
|
||||
40
app/src/main/java/org/autojs/autojs/external/receiver/StaticBroadcastReceiver.java
vendored
Normal file
40
app/src/main/java/org/autojs/autojs/external/receiver/StaticBroadcastReceiver.java
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
package org.autojs.autojs.external.receiver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class StaticBroadcastReceiver extends BaseBroadcastReceiver {
|
||||
|
||||
static final List<String> ACTIONS = new ArrayList<>(Arrays.asList(
|
||||
"android.intent.action.BOOT_COMPLETED",
|
||||
"android.intent.action.QUICKBOOT_POWERON",
|
||||
"android.intent.action.TIME_SET",
|
||||
"android.intent.action.TIMEZONE_CHANGED",
|
||||
"android.intent.action.PACKAGE_ADDED",
|
||||
"android.intent.action.PACKAGE_CHANGED",
|
||||
"android.intent.action.PACKAGE_DATA_CLEARED",
|
||||
"android.intent.action.PACKAGE_REMOVED",
|
||||
"android.intent.action.PACKAGE_RESTARTED",
|
||||
"android.intent.action.UID_REMOVED",
|
||||
"android.intent.action.ACTION_POWER_CONNECTED",
|
||||
"android.intent.action.ACTION_POWER_DISCONNECTED",
|
||||
"android.intent.action.ACTION_SHUTDOWN",
|
||||
"android.intent.action.DATE_CHANGED",
|
||||
"android.intent.action.DREAMING_STARTED",
|
||||
"android.intent.action.DREAMING_STOPPED",
|
||||
"android.intent.action.HEADSET_PLUG",
|
||||
"android.intent.action.INPUT_METHOD_CHANGED",
|
||||
"android.intent.action.LOCALE_CHANGED",
|
||||
"android.intent.action.MEDIA_BUTTON",
|
||||
"android.intent.action.MEDIA_CHECKING",
|
||||
"android.intent.action.MEDIA_MOUNTED",
|
||||
"android.intent.action.PACKAGE_FIRST_LAUNCH",
|
||||
"android.intent.action.PROVIDER_CHANGED",
|
||||
"android.intent.action.WALLPAPER_CHANGED",
|
||||
"android.intent.action.USER_UNLOCKED",
|
||||
"android.intent.action.USER_PRESENT",
|
||||
"android.net.conn.CONNECTIVITY_CHANGE"
|
||||
));
|
||||
|
||||
}
|
||||
@ -6,6 +6,7 @@ import android.content.Intent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.timing.TaskReceiver;
|
||||
import org.autojs.autojs.tool.EmptyObservers;
|
||||
import org.autojs.autojs.ui.BaseActivity;
|
||||
import org.autojs.autojs.ui.edit.EditorView;
|
||||
@ -29,7 +30,9 @@ import static org.autojs.autojs.ui.edit.EditorView.EXTRA_SAVE_ENABLED;
|
||||
@EActivity(R.layout.activity_tasker_script_edit)
|
||||
public class TaskerScriptEditActivity extends BaseActivity {
|
||||
|
||||
public static final int REQUEST_CODE = "Love you. Can we go back?".hashCode() >> 16;
|
||||
public static final int REQUEST_CODE = 10016;
|
||||
public static final String EXTRA_INTENT_TASK_ID = "intent_task_id";
|
||||
public static final String EXTRA_TASK_ID = TaskReceiver.EXTRA_TASK_ID;
|
||||
|
||||
public static void edit(Activity activity, String title, String summary, String content) {
|
||||
activity.startActivityForResult(new Intent(activity, TaskerScriptEditActivity_.class)
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
|
||||
public abstract class BaseModel {
|
||||
private long mId;
|
||||
|
||||
public void setId(long id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BaseModel baseModel = (BaseModel) o;
|
||||
return mId == baseModel.mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int)(mId ^ (mId >>> 32));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,173 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.reactivex.subjects.PublishSubject;
|
||||
|
||||
public abstract class Database<M extends BaseModel> {
|
||||
|
||||
private final SQLiteDatabase mWritableSQLiteDatabase;
|
||||
private final SQLiteDatabase mReadableSQLiteDatabase;
|
||||
private final String mTable;
|
||||
private final PublishSubject<ModelChange<M>> mModelChange = PublishSubject.create();
|
||||
|
||||
public Database(SQLiteOpenHelper sqLiteOpenHelper, String table) {
|
||||
mWritableSQLiteDatabase = sqLiteOpenHelper.getWritableDatabase();
|
||||
mReadableSQLiteDatabase = sqLiteOpenHelper.getWritableDatabase();
|
||||
mTable = table;
|
||||
}
|
||||
|
||||
public <T> Observable<T> exec(Callable<T> callable) {
|
||||
return Observable.fromCallable(callable)
|
||||
.subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
public <T> Flowable<T> execFlowable(Callable<T> callable) {
|
||||
return Flowable.fromCallable(callable)
|
||||
.subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
public PublishSubject<ModelChange<M>> getModelChange() {
|
||||
return mModelChange;
|
||||
}
|
||||
|
||||
public Observable<Integer> delete(M model) {
|
||||
return exec(() -> {
|
||||
int delete = mWritableSQLiteDatabase.delete(mTable, "id = ?",
|
||||
new String[]{String.valueOf(model.getId())});
|
||||
if (delete >= 1) {
|
||||
mModelChange.onNext(new ModelChange<>(model, ModelChange.DELETE));
|
||||
}
|
||||
return delete;
|
||||
});
|
||||
}
|
||||
|
||||
public Observable<Integer> update(M model) {
|
||||
return exec(() -> {
|
||||
ContentValues values = asContentValues(model);
|
||||
int update = mWritableSQLiteDatabase.update(mTable, values, "id = ?", arg(model.getId()));
|
||||
if (update >= 1) {
|
||||
mModelChange.onNext(new ModelChange<>(model, ModelChange.UPDATE));
|
||||
}
|
||||
return update;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public Observable<Long> insert(M model) {
|
||||
return exec(() -> {
|
||||
ContentValues values = asContentValues(model);
|
||||
long id = mWritableSQLiteDatabase.insertOrThrow(mTable, null, values);
|
||||
if (id >= 0) {
|
||||
model.setId(id);
|
||||
mModelChange.onNext(new ModelChange<>(model, ModelChange.INSERT));
|
||||
}
|
||||
return id;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected abstract M createModelFromCursor(Cursor cursor);
|
||||
|
||||
protected abstract ContentValues asContentValues(M model);
|
||||
|
||||
public M queryById(long id) {
|
||||
Cursor cursor = mReadableSQLiteDatabase.rawQuery("SELECT * FROM " + mTable + " WHERE id = ?", arg(id));
|
||||
if (!cursor.moveToFirst()) {
|
||||
return null;
|
||||
}
|
||||
M model = createModelFromCursor(cursor);
|
||||
cursor.close();
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
public Flowable<M> queryAllAsFlowable() {
|
||||
return execFlowable(() ->
|
||||
mReadableSQLiteDatabase.rawQuery("SELECT * FROM " + mTable, null)
|
||||
)
|
||||
.flatMap(cursor -> Flowable.fromIterable(() -> new CursorIterator(cursor)))
|
||||
.map(this::createModelFromCursor);
|
||||
}
|
||||
|
||||
public List<M> queryAll() {
|
||||
ArrayList<M> list = new ArrayList<>();
|
||||
Cursor cursor = mReadableSQLiteDatabase.rawQuery("SELECT * FROM " + mTable, null);
|
||||
while (cursor.moveToNext()) {
|
||||
list.add(createModelFromCursor(cursor));
|
||||
}
|
||||
cursor.close();
|
||||
return list;
|
||||
}
|
||||
|
||||
public long count() {
|
||||
Cursor cursor = mReadableSQLiteDatabase.rawQuery("SELECT COUNT(*) FROM " + mTable, null);
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getLong(0);
|
||||
}
|
||||
cursor.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public Flowable<M> query(String sql, Object... args) {
|
||||
String[] strArgs = args(args);
|
||||
return execFlowable(() ->
|
||||
mReadableSQLiteDatabase.query(mTable, null, sql, strArgs, null, null, null)
|
||||
)
|
||||
.flatMap(cursor -> Flowable.fromIterable(() -> new CursorIterator(cursor)))
|
||||
.map(this::createModelFromCursor);
|
||||
}
|
||||
|
||||
private String[] args(Object[] args) {
|
||||
if (args == null || args.length == 0) {
|
||||
return null;
|
||||
}
|
||||
String[] a = new String[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
a[i] = String.valueOf(args[i]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
private String[] arg(Object value) {
|
||||
return new String[]{String.valueOf(value)};
|
||||
}
|
||||
|
||||
|
||||
private static class CursorIterator implements Iterator<Cursor> {
|
||||
|
||||
private final Cursor mCursor;
|
||||
|
||||
private CursorIterator(Cursor cursor) {
|
||||
mCursor = cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
boolean next = mCursor.moveToNext();
|
||||
if (!next) {
|
||||
mCursor.close();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor next() {
|
||||
return mCursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,64 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Database;
|
||||
|
||||
@Database(version = 1)
|
||||
public class IntentTaskDatabase {
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
|
||||
public class IntentTaskDatabase extends Database<IntentTask> {
|
||||
|
||||
private static final int VERSION = 1;
|
||||
private static final String NAME = "IntentTaskDatabase";
|
||||
|
||||
public IntentTaskDatabase(Context context){
|
||||
super(new SQLHelper(context), IntentTask.TABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContentValues asContentValues(IntentTask model) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("script_path", model.getScriptPath());
|
||||
values.put("action", model.getAction());
|
||||
values.put("category", model.getCategory());
|
||||
values.put("data_type", model.getDataType());
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntentTask createModelFromCursor(Cursor cursor) {
|
||||
IntentTask task = new IntentTask();
|
||||
task.setId(cursor.getInt(0));
|
||||
task.setScriptPath(cursor.getString(1));
|
||||
task.setAction(cursor.getString(2));
|
||||
task.setCategory(cursor.getString(3));
|
||||
task.setDataType(cursor.getString(4));
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
private static class SQLHelper extends SQLiteOpenHelper {
|
||||
|
||||
public SQLHelper(Context context) {
|
||||
super(context, NAME + ".db", null, VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE `" + IntentTask.TABLE + "`(" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"`script_path` TEXT NOT NULL ON CONFLICT FAIL, " +
|
||||
"`action` TEXT, " +
|
||||
"`category` TEXT, " +
|
||||
"`data_type` TEXT);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
import com.raizlabs.android.dbflow.structure.BaseModel;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/28.
|
||||
@ -8,10 +7,15 @@ import com.raizlabs.android.dbflow.structure.BaseModel;
|
||||
|
||||
public class ModelChange<M> {
|
||||
|
||||
private final M mData;
|
||||
private final BaseModel.Action mAction;
|
||||
public static final int INSERT = 1;
|
||||
public static final int UPDATE = 2;
|
||||
public static final int DELETE = 3;
|
||||
|
||||
public ModelChange(M data, BaseModel.Action action) {
|
||||
|
||||
private final M mData;
|
||||
private final int mAction;
|
||||
|
||||
public ModelChange(M data, int action) {
|
||||
mData = data;
|
||||
mAction = action;
|
||||
}
|
||||
@ -20,7 +24,7 @@ public class ModelChange<M> {
|
||||
return mData;
|
||||
}
|
||||
|
||||
public BaseModel.Action getAction() {
|
||||
public int getAction() {
|
||||
return mAction;
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +1,74 @@
|
||||
package org.autojs.autojs.storage.database;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Database;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/28.
|
||||
*/
|
||||
@Database(version = 1)
|
||||
public class TimedTaskDatabase {
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import org.autojs.autojs.timing.TimedTask;
|
||||
|
||||
public class TimedTaskDatabase extends Database<TimedTask> {
|
||||
|
||||
private static final int VERSION = 3;
|
||||
private static final String NAME = "TimedTaskDatabase";
|
||||
|
||||
public TimedTaskDatabase(Context context) {
|
||||
super(new SQLHelper(context), TimedTask.TABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContentValues asContentValues(TimedTask model) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("time", model.getTimeFlag());
|
||||
values.put("scheduled", model.isScheduled());
|
||||
values.put("delay", model.getDelay());
|
||||
values.put("interval", model.getInterval());
|
||||
values.put("loop_times", model.getLoopTimes());
|
||||
values.put("millis", model.getMillis());
|
||||
values.put("script_path", model.getScriptPath());
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TimedTask createModelFromCursor(Cursor cursor) {
|
||||
TimedTask task = new TimedTask();
|
||||
task.setId(cursor.getInt(0));
|
||||
task.setTimeFlag(cursor.getLong(1));
|
||||
task.setScheduled(cursor.getInt(2) != 0);
|
||||
task.setDelay(cursor.getLong(3));
|
||||
task.setInterval(cursor.getLong(4));
|
||||
task.setLoopTimes(cursor.getInt(5));
|
||||
task.setMillis(cursor.getLong(6));
|
||||
task.setScriptPath(cursor.getString(7));
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
private static class SQLHelper extends SQLiteOpenHelper {
|
||||
|
||||
public SQLHelper(Context context) {
|
||||
super(context, NAME + ".db", null, VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE `" + TimedTask.TABLE + "`(" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"`time` INTEGER, " +
|
||||
"`scheduled` INTEGER, " +
|
||||
"`delay` INTEGER, " +
|
||||
"`interval` INTEGER, " +
|
||||
"`loop_times` INTEGER, " +
|
||||
"`millis` INTEGER, " +
|
||||
"`script_path` TEXT);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,33 +2,19 @@ package org.autojs.autojs.timing;
|
||||
|
||||
import android.content.IntentFilter;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Column;
|
||||
import com.raizlabs.android.dbflow.annotation.NotNull;
|
||||
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
|
||||
import com.raizlabs.android.dbflow.annotation.Table;
|
||||
import org.autojs.autojs.storage.database.BaseModel;
|
||||
|
||||
import org.autojs.autojs.storage.database.IntentTaskDatabase;
|
||||
import org.autojs.autojs.storage.database.TimedTaskDatabase;
|
||||
public class IntentTask extends BaseModel {
|
||||
|
||||
@Table(database = IntentTaskDatabase.class)
|
||||
public class IntentTask {
|
||||
public static final String TABLE = "IntentTask";
|
||||
|
||||
@PrimaryKey(autoincrement = true, quickCheckAutoIncrement = true)
|
||||
@Column(name = "id")
|
||||
int mId = -1;
|
||||
private String mScriptPath;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "script_path")
|
||||
String mScriptPath;
|
||||
private String mAction;
|
||||
|
||||
@Column(name = "action")
|
||||
String mAction;
|
||||
private String mCategory;
|
||||
|
||||
@Column(name = "category")
|
||||
String mCategory;
|
||||
|
||||
@Column(name = "data_type")
|
||||
String mDataType;
|
||||
private String mDataType;
|
||||
|
||||
public IntentFilter getIntentFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
@ -48,14 +34,6 @@ public class IntentTask {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public String getScriptPath() {
|
||||
return mScriptPath;
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ public class TaskReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
ScriptIntents.handleIntent(context, intent);
|
||||
int id = intent.getIntExtra(EXTRA_TASK_ID, -1);
|
||||
long id = intent.getLongExtra(EXTRA_TASK_ID, -1);
|
||||
if (id >= 0) {
|
||||
TimedTaskManager.getInstance().notifyTaskFinished(id);
|
||||
}
|
||||
|
||||
@ -4,13 +4,10 @@ import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.raizlabs.android.dbflow.annotation.Column;
|
||||
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
|
||||
import com.raizlabs.android.dbflow.annotation.Table;
|
||||
import com.stardust.autojs.execution.ExecutionConfig;
|
||||
import org.autojs.autojs.external.ScriptIntents;
|
||||
import org.autojs.autojs.storage.database.TimedTaskDatabase;
|
||||
|
||||
import org.autojs.autojs.external.ScriptIntents;
|
||||
import org.autojs.autojs.storage.database.BaseModel;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeConstants;
|
||||
import org.joda.time.LocalDateTime;
|
||||
@ -19,11 +16,9 @@ import org.joda.time.LocalTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/27.
|
||||
*/
|
||||
@Table(database = TimedTaskDatabase.class)
|
||||
public class TimedTask {
|
||||
public class TimedTask extends BaseModel {
|
||||
|
||||
public static final String TABLE = "TimedTask";
|
||||
|
||||
private static final int FLAG_DISPOSABLE = 0;
|
||||
public final static int FLAG_SUNDAY = 0x1;
|
||||
@ -36,29 +31,18 @@ public class TimedTask {
|
||||
private static final int FLAG_EVERYDAY = 0x7F;
|
||||
private static final int REQUEST_CODE = 2000;
|
||||
|
||||
@PrimaryKey(autoincrement = true, quickCheckAutoIncrement = true)
|
||||
@Column(name = "id")
|
||||
int mId = -1;
|
||||
|
||||
@Column(name = "time")
|
||||
long mTimeFlag;
|
||||
|
||||
@Column(name = "scheduled")
|
||||
boolean mScheduled;
|
||||
|
||||
@Column(name = "delay")
|
||||
long mDelay = 0;
|
||||
|
||||
@Column(name = "interval")
|
||||
long mInterval = 0;
|
||||
|
||||
@Column(name = "loop_times")
|
||||
int mLoopTimes = 1;
|
||||
|
||||
@Column(name = "millis")
|
||||
long mMillis;
|
||||
|
||||
@Column(name = "script_path")
|
||||
String mScriptPath;
|
||||
|
||||
public TimedTask() {
|
||||
@ -148,19 +132,10 @@ public class TimedTask {
|
||||
return mMillis;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public String getScriptPath() {
|
||||
return mScriptPath;
|
||||
}
|
||||
|
||||
|
||||
public void setId(int id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
public long getTimeFlag() {
|
||||
return mTimeFlag;
|
||||
}
|
||||
@ -207,7 +182,7 @@ public class TimedTask {
|
||||
|
||||
public Intent createIntent() {
|
||||
return new Intent(TaskReceiver.ACTION_TASK)
|
||||
.putExtra(TaskReceiver.EXTRA_TASK_ID, mId)
|
||||
.putExtra(TaskReceiver.EXTRA_TASK_ID, getId())
|
||||
.putExtra(ScriptIntents.EXTRA_KEY_PATH, mScriptPath)
|
||||
.putExtra(ScriptIntents.EXTRA_KEY_DELAY, mDelay)
|
||||
.putExtra(ScriptIntents.EXTRA_KEY_LOOP_TIMES, mLoopTimes)
|
||||
@ -216,14 +191,14 @@ public class TimedTask {
|
||||
|
||||
|
||||
public PendingIntent createPendingIntent(Context context) {
|
||||
return PendingIntent.getBroadcast(context, REQUEST_CODE + 1 + getId(),
|
||||
return PendingIntent.getBroadcast(context, (int) ((REQUEST_CODE + 1 + getId()) % 65535),
|
||||
createIntent(), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimedTask{" +
|
||||
"mId=" + mId +
|
||||
"mId=" + getId() +
|
||||
", mTimeFlag=" + mTimeFlag +
|
||||
", mScheduled=" + mScheduled +
|
||||
", mDelay=" + mDelay +
|
||||
@ -234,20 +209,6 @@ public class TimedTask {
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
TimedTask timedTask = (TimedTask) o;
|
||||
|
||||
return mId == timedTask.mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public static TimedTask dailyTask(LocalTime time, String scriptPath, ExecutionConfig config) {
|
||||
return new TimedTask(time.getMillisOfDay(), FLAG_EVERYDAY, scriptPath, config);
|
||||
|
||||
@ -1,28 +1,20 @@
|
||||
package org.autojs.autojs.timing;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.raizlabs.android.dbflow.config.FlowManager;
|
||||
import com.raizlabs.android.dbflow.runtime.DirectModelNotifier;
|
||||
import com.raizlabs.android.dbflow.rx2.language.RXSQLite;
|
||||
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.Pref;
|
||||
import org.autojs.autojs.storage.database.IntentTaskDatabase;
|
||||
import org.autojs.autojs.storage.database.ModelChange;
|
||||
import org.autojs.autojs.storage.database.TimedTaskDatabase;
|
||||
import org.autojs.autojs.tool.EmptyObservers;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.reactivex.subjects.PublishSubject;
|
||||
|
||||
/**
|
||||
@ -31,12 +23,10 @@ import io.reactivex.subjects.PublishSubject;
|
||||
//TODO rx
|
||||
public class TimedTaskManager {
|
||||
|
||||
|
||||
private static TimedTaskManager sInstance;
|
||||
private ModelAdapter<TimedTask> mTimedTaskModelAdapter;
|
||||
private ModelAdapter<IntentTask> mIntentTaskModelAdapter;
|
||||
private Context mContext;
|
||||
private PublishSubject<ModelChange<TimedTask>> mTimedTaskChanges = PublishSubject.create();
|
||||
private TimedTaskDatabase mTimedTaskDatabase;
|
||||
private IntentTaskDatabase mIntentTaskDatabase;
|
||||
|
||||
public static TimedTaskManager getInstance() {
|
||||
if (sInstance == null) {
|
||||
@ -45,104 +35,108 @@ public class TimedTaskManager {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public TimedTaskManager(Context context) {
|
||||
mContext = context;
|
||||
mTimedTaskModelAdapter = FlowManager.getModelAdapter(TimedTask.class);
|
||||
mIntentTaskModelAdapter = FlowManager.getModelAdapter(IntentTask.class);
|
||||
DirectModelNotifier.get().registerForModelChanges(TimedTask.class, new DirectModelNotifier.ModelChangedListener<TimedTask>() {
|
||||
@Override
|
||||
public void onModelChanged(@NonNull TimedTask model, @NonNull BaseModel.Action action) {
|
||||
mTimedTaskChanges.onNext(new ModelChange<>(model, action));
|
||||
if (action == BaseModel.Action.DELETE && countTasks() == 0) {
|
||||
TimedTaskScheduler.stopRtcRepeating(mContext);
|
||||
} else if (action == BaseModel.Action.INSERT) {
|
||||
TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTableChanged(@Nullable Class<?> tableChanged, @NonNull BaseModel.Action action) {
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void notifyTaskFinished(int id) {
|
||||
@SuppressLint("CheckResult")
|
||||
public void notifyTaskFinished(long id) {
|
||||
TimedTask task = getTimedTask(id);
|
||||
if (task == null)
|
||||
return;
|
||||
if (task.isDisposable()) {
|
||||
mTimedTaskModelAdapter.delete(task);
|
||||
mTimedTaskDatabase.delete(task)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
} else {
|
||||
task.setScheduled(false);
|
||||
mTimedTaskModelAdapter.update(task);
|
||||
mTimedTaskDatabase.update(task)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void removeTask(TimedTask timedTask) {
|
||||
TimedTaskScheduler.cancel(mContext, timedTask);
|
||||
mTimedTaskModelAdapter.delete(timedTask);
|
||||
mTimedTaskDatabase.delete(timedTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void addTask(TimedTask timedTask) {
|
||||
mTimedTaskModelAdapter.insert(timedTask);
|
||||
mTimedTaskDatabase.insert(timedTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);;
|
||||
TimedTaskScheduler.scheduleTaskIfNeeded(mContext, timedTask);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void addTask(IntentTask intentTask) {
|
||||
mIntentTaskModelAdapter.insert(intentTask);
|
||||
mIntentTaskDatabase.insert(intentTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void removeTask(IntentTask intentTask) {
|
||||
mIntentTaskModelAdapter.delete(intentTask);
|
||||
mIntentTaskDatabase.delete(intentTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);;
|
||||
}
|
||||
|
||||
public Flowable<TimedTask> getAllTasks() {
|
||||
return RXSQLite.rx(SQLite.select().from(TimedTask.class))
|
||||
.queryStreamResults()
|
||||
.subscribeOn(Schedulers.io());
|
||||
return mTimedTaskDatabase.queryAllAsFlowable();
|
||||
}
|
||||
|
||||
public Flowable<IntentTask> getIntentTaskOfAction(String action) {
|
||||
IntentTask intentTask = new IntentTask();
|
||||
intentTask.setAction(Intent.ACTION_BOOT_COMPLETED);
|
||||
intentTask.setScriptPath(new File(Pref.getScriptDirPath(), "boot.js").getPath());
|
||||
return Flowable.just(intentTask);
|
||||
// return RXSQLite.rx(SQLite.select().from(IntentTask.class))
|
||||
// .queryStreamResults()
|
||||
// .subscribeOn(Schedulers.io());
|
||||
return mIntentTaskDatabase.query("action = ?", action);
|
||||
}
|
||||
|
||||
|
||||
public Observable<ModelChange<TimedTask>> getTimeTaskChanges() {
|
||||
return mTimedTaskChanges;
|
||||
return mTimedTaskDatabase.getModelChange();
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void notifyTaskScheduled(TimedTask timedTask) {
|
||||
timedTask.setScheduled(true);
|
||||
mTimedTaskModelAdapter.update(timedTask);
|
||||
mTimedTaskDatabase.update(timedTask)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
|
||||
}
|
||||
|
||||
public List<TimedTask> getAllTasksAsList() {
|
||||
return SQLite.select().from(TimedTask.class)
|
||||
.queryList();
|
||||
return mTimedTaskDatabase.queryAll();
|
||||
}
|
||||
|
||||
public TimedTask getTimedTask(int taskId) {
|
||||
return SQLite.select()
|
||||
.from(TimedTask.class)
|
||||
.where(TimedTask_Table.id.is(taskId))
|
||||
.querySingle();
|
||||
public TimedTask getTimedTask(long taskId) {
|
||||
return mTimedTaskDatabase.queryById(taskId);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void updateTask(TimedTask task) {
|
||||
mTimedTaskModelAdapter.update(task);
|
||||
mTimedTaskDatabase.update(task)
|
||||
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);
|
||||
TimedTaskScheduler.cancel(mContext, task);
|
||||
TimedTaskScheduler.scheduleTaskIfNeeded(mContext, task);
|
||||
}
|
||||
|
||||
public long countTasks() {
|
||||
return SQLite.select().from(TimedTask.class).count();
|
||||
return mTimedTaskDatabase.count();
|
||||
}
|
||||
|
||||
public List<IntentTask> getAllIntentTasksAsList() {
|
||||
return mIntentTaskDatabase.queryAll();
|
||||
}
|
||||
|
||||
public Observable<ModelChange<IntentTask>> getIntentTaskChanges() {
|
||||
return mIntentTaskDatabase.getModelChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,6 @@ public class TimedTaskScheduler extends BroadcastReceiver {
|
||||
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) {
|
||||
@ -38,7 +37,7 @@ public class TimedTaskScheduler extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private static void checkTasks(Context context) {
|
||||
public static void checkTasks(Context context) {
|
||||
TimedTaskManager.getInstance().getAllTasks()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -83,7 +82,7 @@ public class TimedTaskScheduler extends BroadcastReceiver {
|
||||
|
||||
|
||||
public static void checkTasksRepeatedlyIfNeeded(Context context) {
|
||||
if (TimedTaskManager.getInstance().countTasks() > 0 && mNextRtcWakeupMillis > 0) {
|
||||
if (TimedTaskManager.getInstance().countTasks() > 0) {
|
||||
setupNextRtcWakeup(context, System.currentTimeMillis() + 5000);
|
||||
}
|
||||
}
|
||||
@ -95,7 +94,6 @@ public class TimedTaskScheduler extends BroadcastReceiver {
|
||||
}
|
||||
AlarmManager alarmManager = getAlarmManager(context);
|
||||
setExactCompat(alarmManager, createTaskCheckPendingIntent(context), millis);
|
||||
mNextRtcWakeupMillis = millis;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ import com.stardust.app.GlobalAppContext;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.stardust.pio.PFiles;
|
||||
import com.stardust.pio.UncheckedIOException;
|
||||
import com.tencent.bugly.crashreport.BuglyLog;
|
||||
|
||||
import org.autojs.autojs.Pref;
|
||||
import org.autojs.autojs.R;
|
||||
@ -319,6 +320,7 @@ public class ScriptOperations {
|
||||
|
||||
|
||||
public Observable<ScriptFile> download(String url) {
|
||||
BuglyLog.i(LOG_TAG, "dir = " + Pref.getScriptDirPath() + ", sdcard = " + Environment.getExternalStorageDirectory() + ", url = " + url);
|
||||
String fileName = DownloadManager.parseFileNameLocally(url);
|
||||
return new FileChooserDialogBuilder(mContext)
|
||||
.title(R.string.text_select_save_path)
|
||||
|
||||
@ -6,6 +6,7 @@ import android.support.annotation.StringRes;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.pio.PFile;
|
||||
import com.tencent.bugly.crashreport.BuglyLog;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.model.explorer.Explorer;
|
||||
@ -66,7 +67,6 @@ public class FileChooserDialogBuilder extends ThemeColorMaterialDialogBuilder {
|
||||
public FileChooserDialogBuilder dir(String rootDir, String initialDir) {
|
||||
mRootDir = rootDir;
|
||||
mInitialDir = initialDir;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import com.stardust.autojs.script.JavaScriptSource;
|
||||
import com.stardust.pio.PFiles;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
import org.autojs.autojs.timing.TimedTask;
|
||||
import org.autojs.autojs.timing.TimedTaskManager;
|
||||
|
||||
@ -30,10 +31,24 @@ public abstract class Task {
|
||||
public static class PendingTask extends Task {
|
||||
|
||||
private TimedTask mTimedTask;
|
||||
private IntentTask mIntentTask;
|
||||
|
||||
|
||||
public PendingTask(TimedTask timedTask) {
|
||||
mTimedTask = timedTask;
|
||||
mIntentTask = null;
|
||||
}
|
||||
|
||||
public PendingTask(IntentTask intentTask) {
|
||||
mIntentTask = intentTask;
|
||||
mTimedTask = null;
|
||||
}
|
||||
|
||||
public boolean taskEquals(Object task){
|
||||
if(mTimedTask != null){
|
||||
return mTimedTask.equals(task);
|
||||
}
|
||||
return mIntentTask.equals(task);
|
||||
}
|
||||
|
||||
public TimedTask getTimedTask() {
|
||||
@ -42,14 +57,20 @@ public abstract class Task {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return PFiles.getSimplifiedPath(mTimedTask.getScriptPath());
|
||||
return PFiles.getSimplifiedPath(getScriptPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDesc() {
|
||||
long nextTime = mTimedTask.getNextTime();
|
||||
return GlobalAppContext.getString(R.string.text_next_run_time) + ": " +
|
||||
DateTimeFormat.shortDateTime().print(nextTime);
|
||||
if (mTimedTask != null) {
|
||||
long nextTime = mTimedTask.getNextTime();
|
||||
return GlobalAppContext.getString(R.string.text_next_run_time) + ": " +
|
||||
DateTimeFormat.shortDateTime().print(nextTime);
|
||||
} else {
|
||||
assert mIntentTask != null;
|
||||
return mIntentTask.getAction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -57,9 +78,18 @@ public abstract class Task {
|
||||
TimedTaskManager.getInstance().removeTask(mTimedTask);
|
||||
}
|
||||
|
||||
private String getScriptPath() {
|
||||
if (mTimedTask != null) {
|
||||
return mTimedTask.getScriptPath();
|
||||
} else {
|
||||
assert mIntentTask != null;
|
||||
return mIntentTask.getScriptPath();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEngineName() {
|
||||
if (mTimedTask.getScriptPath().endsWith(".js")) {
|
||||
if (getScriptPath().endsWith(".js")) {
|
||||
return JavaScriptSource.ENGINE;
|
||||
} else {
|
||||
return AutoFileSource.ENGINE;
|
||||
@ -69,6 +99,10 @@ public abstract class Task {
|
||||
public void setTimedTask(TimedTask timedTask) {
|
||||
mTimedTask = timedTask;
|
||||
}
|
||||
|
||||
public void setIntentTask(IntentTask intentTask) {
|
||||
mIntentTask = intentTask;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RunningTask extends Task {
|
||||
|
||||
@ -8,6 +8,7 @@ import com.stardust.autojs.execution.ScriptExecution;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
import org.autojs.autojs.timing.TimedTask;
|
||||
import org.autojs.autojs.timing.TimedTaskManager;
|
||||
|
||||
@ -55,39 +56,55 @@ public abstract class TaskGroup implements Parent<Task> {
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
List<TimedTask> timedTasks = TimedTaskManager.getInstance().getAllTasksAsList();
|
||||
mTasks.clear();
|
||||
for (TimedTask timedTask : timedTasks) {
|
||||
for (TimedTask timedTask : TimedTaskManager.getInstance().getAllTasksAsList()) {
|
||||
mTasks.add(new Task.PendingTask(timedTask));
|
||||
}
|
||||
for (IntentTask intentTask : TimedTaskManager.getInstance().getAllIntentTasksAsList()) {
|
||||
mTasks.add(new Task.PendingTask(intentTask));
|
||||
}
|
||||
}
|
||||
|
||||
public int addTask(TimedTask timedTask) {
|
||||
public int addTask(Object task) {
|
||||
int pos = mTasks.size();
|
||||
mTasks.add(new Task.PendingTask(timedTask));
|
||||
if (task instanceof TimedTask) {
|
||||
mTasks.add(new Task.PendingTask((TimedTask) task));
|
||||
} else if (task instanceof IntentTask) {
|
||||
mTasks.add(new Task.PendingTask((IntentTask) task));
|
||||
} else {
|
||||
throw new IllegalArgumentException("task = " + task);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
public int removeTask(TimedTask data) {
|
||||
public int removeTask(Object data) {
|
||||
int i = indexOf(data);
|
||||
if (i >= 0)
|
||||
mTasks.remove(i);
|
||||
return i;
|
||||
}
|
||||
|
||||
private int indexOf(TimedTask data) {
|
||||
private int indexOf(Object data) {
|
||||
for (int i = 0; i < mTasks.size(); i++) {
|
||||
if (((Task.PendingTask) mTasks.get(i)).getTimedTask().equals(data)) {
|
||||
Task.PendingTask task = (Task.PendingTask) mTasks.get(i);
|
||||
if (task.taskEquals(data)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int updateTask(TimedTask task) {
|
||||
|
||||
public int updateTask(Object task) {
|
||||
int i = indexOf(task);
|
||||
if (i >= 0)
|
||||
((Task.PendingTask) mTasks.get(i)).setTimedTask(task);
|
||||
if (i >= 0) {
|
||||
if (task instanceof TimedTask) {
|
||||
((Task.PendingTask) mTasks.get(i)).setTimedTask((TimedTask) task);
|
||||
} else if (task instanceof IntentTask) {
|
||||
((Task.PendingTask) mTasks.get(i)).setIntentTask((IntentTask) task);
|
||||
} else {
|
||||
throw new IllegalArgumentException("task = " + task);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,30 +13,27 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.autojs.workground.WrapContentLinearLayoutManager;
|
||||
|
||||
import com.bignerdranch.expandablerecyclerview.ChildViewHolder;
|
||||
import com.bignerdranch.expandablerecyclerview.ExpandableRecyclerAdapter;
|
||||
import com.bignerdranch.expandablerecyclerview.ParentViewHolder;
|
||||
import com.raizlabs.android.dbflow.structure.BaseModel;
|
||||
import com.stardust.autojs.ScriptEngineService;
|
||||
import com.stardust.autojs.engine.ScriptEngineManager;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.execution.ScriptExecutionListener;
|
||||
import com.stardust.autojs.execution.SimpleScriptExecutionListener;
|
||||
import com.stardust.autojs.engine.ScriptEngine;
|
||||
import com.stardust.autojs.script.AutoFileSource;
|
||||
import com.stardust.autojs.workground.WrapContentLinearLayoutManager;
|
||||
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.external.tasker.TaskerScriptEditActivity;
|
||||
import org.autojs.autojs.storage.database.ModelChange;
|
||||
import org.autojs.autojs.timing.IntentTask;
|
||||
import org.autojs.autojs.timing.TaskReceiver;
|
||||
import org.autojs.autojs.timing.TimedTask;
|
||||
import org.autojs.autojs.timing.TimedTaskManager;
|
||||
import org.autojs.autojs.ui.timing.TimedTaskSettingActivity_;
|
||||
|
||||
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -60,7 +57,7 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
private TaskGroup.PendingTaskGroup mPendingTaskGroup;
|
||||
private Adapter mAdapter;
|
||||
private Disposable mTimedTaskChangeDisposable;
|
||||
private final ScriptEngineService mScriptEngineService = AutoJs.getInstance().getScriptEngineService();
|
||||
private Disposable mIntentTaskChangeDisposable;
|
||||
private ScriptExecutionListener mScriptExecutionListener = new SimpleScriptExecutionListener() {
|
||||
@Override
|
||||
public void onStart(final ScriptExecution execution) {
|
||||
@ -135,7 +132,10 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
AutoJs.getInstance().getScriptEngineService().registerGlobalScriptExecutionListener(mScriptExecutionListener);
|
||||
mTimedTaskChangeDisposable = TimedTaskManager.getInstance().getTimeTaskChanges()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::onTimedTaskChange);
|
||||
.subscribe(this::onTaskChange);
|
||||
mIntentTaskChangeDisposable = TimedTaskManager.getInstance().getIntentTaskChanges()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::onTaskChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -151,26 +151,25 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
super.onDetachedFromWindow();
|
||||
AutoJs.getInstance().getScriptEngineService().unregisterGlobalScriptExecutionListener(mScriptExecutionListener);
|
||||
mTimedTaskChangeDisposable.dispose();
|
||||
mIntentTaskChangeDisposable.dispose();
|
||||
}
|
||||
|
||||
void onTimedTaskChange(ModelChange<TimedTask> taskChange) {
|
||||
if (taskChange.getAction() == BaseModel.Action.INSERT) {
|
||||
void onTaskChange(ModelChange taskChange) {
|
||||
if (taskChange.getAction() == ModelChange.INSERT) {
|
||||
mAdapter.notifyChildInserted(1, mPendingTaskGroup.addTask(taskChange.getData()));
|
||||
} else if (taskChange.getAction() == BaseModel.Action.DELETE) {
|
||||
} else if (taskChange.getAction() == ModelChange.DELETE) {
|
||||
final int i = mPendingTaskGroup.removeTask(taskChange.getData());
|
||||
// FIXME: 2017/11/28 task id is always 0
|
||||
if (i >= 0) {
|
||||
mAdapter.notifyChildRemoved(1, i);
|
||||
} else {
|
||||
Log.w(LOG_TAG, "data inconsistent on change: " + taskChange);
|
||||
refresh();
|
||||
}
|
||||
} else if (taskChange.getAction() == BaseModel.Action.UPDATE) {
|
||||
} else if (taskChange.getAction() == ModelChange.UPDATE) {
|
||||
final int i = mPendingTaskGroup.updateTask(taskChange.getData());
|
||||
if (i >= 0) {
|
||||
mAdapter.notifyChildChanged(1, i);
|
||||
} else {
|
||||
Log.w(LOG_TAG, "data inconsistent on change: " + taskChange);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
@ -250,7 +249,7 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
void onItemClick(View view) {
|
||||
if (mTask instanceof Task.PendingTask) {
|
||||
TimedTaskSettingActivity_.intent(getContext())
|
||||
.extra(TaskReceiver.EXTRA_TASK_ID, ((Task.PendingTask) mTask).getTimedTask().getId())
|
||||
.extra(TaskerScriptEditActivity.EXTRA_TASK_ID, ((Task.PendingTask) mTask).getTimedTask().getId())
|
||||
.start();
|
||||
}
|
||||
}
|
||||
@ -263,8 +262,8 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
|
||||
|
||||
TaskGroupViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
title = (TextView) itemView.findViewById(R.id.title);
|
||||
icon = (ImageView) itemView.findViewById(R.id.icon);
|
||||
title = itemView.findViewById(R.id.title);
|
||||
icon = itemView.findViewById(R.id.icon);
|
||||
itemView.setOnClickListener(view -> {
|
||||
if (isExpanded()) {
|
||||
collapseView();
|
||||
|
||||
@ -18,6 +18,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
@ -27,6 +28,9 @@ import android.widget.Toast;
|
||||
|
||||
import com.github.aakira.expandablelayout.ExpandableRelativeLayout;
|
||||
import com.stardust.autojs.execution.ExecutionConfig;
|
||||
import com.stardust.util.BiMap;
|
||||
import com.stardust.util.BiMaps;
|
||||
import com.stardust.util.MapEntries;
|
||||
|
||||
import org.androidannotations.annotations.AfterViews;
|
||||
import org.androidannotations.annotations.CheckedChange;
|
||||
@ -49,6 +53,7 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/11/28.
|
||||
@ -62,6 +67,13 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
private static final int REQUEST_CODE_IGNORE_BATTERY = 27101;
|
||||
private static final String LOG_TAG = "TimedTaskSettings";
|
||||
|
||||
private static final BiMap<Integer, String> ACTIONS = BiMaps.<Integer, String>newBuilder()
|
||||
.put(R.id.run_on_boot, Intent.ACTION_BOOT_COMPLETED)
|
||||
.put(R.id.run_on_screen_off, Intent.ACTION_SCREEN_OFF)
|
||||
.put(R.id.run_on_screen_on, Intent.ACTION_SCREEN_ON)
|
||||
.build();
|
||||
|
||||
|
||||
@ViewById(R.id.toolbar)
|
||||
Toolbar mToolbar;
|
||||
|
||||
@ -77,9 +89,14 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
@ViewById(R.id.weekly_task_radio)
|
||||
RadioButton mWeeklyTaskRadio;
|
||||
|
||||
@ViewById(R.id.run_on_boot_radio)
|
||||
RadioButton mRunOnBootRadio;
|
||||
@ViewById(R.id.run_on_broadcast)
|
||||
RadioButton mRunOnBroadcast;
|
||||
|
||||
@ViewById(R.id.action)
|
||||
EditText mOtherBroadcastAction;
|
||||
|
||||
@ViewById(R.id.broadcast_group)
|
||||
RadioGroup mBroadcastGroup;
|
||||
|
||||
@ViewById(R.id.disposable_task_time)
|
||||
TextView mDisposableTaskTime;
|
||||
@ -98,14 +115,13 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
|
||||
private List<CheckBox> mDayOfWeekCheckBoxes = new ArrayList<>();
|
||||
|
||||
|
||||
private ScriptFile mScriptFile;
|
||||
private TimedTask mTimedTask;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
int taskId = getIntent().getIntExtra(TaskReceiver.EXTRA_TASK_ID, -1);
|
||||
long taskId = getIntent().getLongExtra(TaskReceiver.EXTRA_TASK_ID, -1);
|
||||
if (taskId != -1) {
|
||||
mTimedTask = TimedTaskManager.getInstance().getTimedTask(taskId);
|
||||
if (mTimedTask != null) {
|
||||
@ -175,7 +191,7 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
|
||||
@CheckedChange({R.id.daily_task_radio, R.id.weekly_task_radio, R.id.disposable_task_radio})
|
||||
@CheckedChange({R.id.daily_task_radio, R.id.weekly_task_radio, R.id.disposable_task_radio, R.id.run_on_broadcast})
|
||||
void onCheckedChanged(CompoundButton button) {
|
||||
ExpandableRelativeLayout relativeLayout = findExpandableLayoutOf(button);
|
||||
if (button.isChecked()) {
|
||||
@ -271,8 +287,6 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
} else {
|
||||
createOrUpdateTimedTask();
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
@ -288,12 +302,8 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
private void createOrUpdateTimedTask() {
|
||||
if (mRunOnBootRadio.isChecked()) {
|
||||
IntentTask task = new IntentTask();
|
||||
task.setAction(Intent.ACTION_BOOT_COMPLETED);
|
||||
task.setScriptPath(mScriptFile.getPath());
|
||||
TimedTaskManager.getInstance().addTask(task);
|
||||
finish();
|
||||
if (mRunOnBroadcast.isChecked()) {
|
||||
createIntentTask();
|
||||
return;
|
||||
}
|
||||
TimedTask task = createTimedTask();
|
||||
@ -308,4 +318,24 @@ public class TimedTaskSettingActivity extends BaseActivity {
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
private void createIntentTask() {
|
||||
int buttonId = mBroadcastGroup.getCheckedRadioButtonId();
|
||||
String action;
|
||||
if(buttonId == R.id.run_on_other_broadcast){
|
||||
action = mOtherBroadcastAction.getText().toString();
|
||||
if(action.isEmpty()){
|
||||
mOtherBroadcastAction.setError(getString(R.string.text_should_not_be_empty));
|
||||
return;
|
||||
}
|
||||
}else {
|
||||
action = ACTIONS.get(buttonId);
|
||||
}
|
||||
IntentTask task = new IntentTask();
|
||||
task.setAction(action);
|
||||
task.setScriptPath(mScriptFile.getPath());
|
||||
TimedTaskManager.getInstance().addTask(task);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,12 +253,86 @@
|
||||
</com.github.aakira.expandablelayout.ExpandableRelativeLayout>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/run_on_boot_radio"
|
||||
android:id="@+id/run_on_broadcast"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:text="@string/text_run_on_boot"/>
|
||||
android:text="@string/text_run_on_broadcast"/>
|
||||
|
||||
<com.github.aakira.expandablelayout.ExpandableRelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:ael_expanded="false"
|
||||
app:ael_interpolator="fastOutSlowIn"
|
||||
app:ael_orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/broadcast_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/run_on_boot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:text="@string/text_run_on_boot"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/run_on_screen_on"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:text="@string/text_run_on_screen_on"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/run_on_screen_off"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:text="@string/text_run_on_screen_off"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/run_on_other_broadcast"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:text="@string/text_run_on_other_broadcast"/>
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="36dp"
|
||||
android:layout_marginTop="2dp">
|
||||
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/action"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/text_broadcast_action"
|
||||
android:text="@string/text_broadcast_action_prefix"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</com.github.aakira.expandablelayout.ExpandableRelativeLayout>
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@ -382,7 +382,7 @@
|
||||
<string name="text_use_alarm_clock">使用系统闹钟唤醒Auto.js</string>
|
||||
<string name="error_connect_to_remote">连接失败: %s</string>
|
||||
<string name="text_are_you_sure_to_delete">确定要删除%s吗</string>
|
||||
<string name="text_run_on_boot">开机时运行</string>
|
||||
<string name="text_run_on_broadcast">特定事件(广播)触发运行</string>
|
||||
<string name="text_search_java_class">搜索Java包/类</string>
|
||||
<string name="text_class_or_package_name">类/包名</string>
|
||||
<string name="text_view_docs">查看文档</string>
|
||||
@ -403,4 +403,10 @@
|
||||
<string name="foreground_notification_channel_name">前台服务通知</string>
|
||||
<string name="foreground_notification_title">Auto.js保持运行中</string>
|
||||
<string name="foreground_notification_text">点击进入主界面</string>
|
||||
<string name="text_run_on_boot">开机时运行</string>
|
||||
<string name="text_run_on_screen_on">亮屏时运行</string>
|
||||
<string name="text_run_on_screen_off">息屏时运行</string>
|
||||
<string name="text_run_on_other_broadcast">其他事件(广播)</string>
|
||||
<string name="text_broadcast_action">广播Action</string>
|
||||
<string name="text_broadcast_action_prefix">android.intent.action.</string>
|
||||
</resources>
|
||||
|
||||
11
common/src/main/java/com/stardust/util/BiMap.java
Normal file
11
common/src/main/java/com/stardust/util/BiMap.java
Normal file
@ -0,0 +1,11 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface BiMap<K, V> extends Map<K, V> {
|
||||
|
||||
K getKey(V value);
|
||||
|
||||
Set<V> valueSet();
|
||||
}
|
||||
206
common/src/main/java/com/stardust/util/BiMaps.java
Normal file
206
common/src/main/java/com/stardust/util/BiMaps.java
Normal file
@ -0,0 +1,206 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class BiMaps {
|
||||
|
||||
public static <K, V> BiMap<K, V> make(Map<K, V> keyToValue, Map<V, K> valueToKey) {
|
||||
return new BiMapImpl<>(keyToValue, valueToKey);
|
||||
}
|
||||
|
||||
public static <K, V> BiMapBuilder<K, V> newBuilder() {
|
||||
return new BiMapBuilder<>();
|
||||
}
|
||||
|
||||
public static class BiMapBuilder<K, V> {
|
||||
|
||||
private final BiMap<K, V> mBiMap = make(new HashMap<K, V>(), new HashMap<V, K>());
|
||||
|
||||
public BiMapBuilder<K, V> put(K key, V value) {
|
||||
mBiMap.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiMap<K, V> build() {
|
||||
return mBiMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class BiMapImpl<K, V> implements BiMap<K, V> {
|
||||
|
||||
private final Map<K, V> mKVMap;
|
||||
private final Map<V, K> mVKMap;
|
||||
|
||||
private BiMapImpl(Map<K, V> kvMap, Map<V, K> vkMap) {
|
||||
mKVMap = kvMap;
|
||||
mVKMap = vkMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return mKVMap.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return mKVMap.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return mKVMap.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return mVKMap.containsKey(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
return mKVMap.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
V put = mKVMap.put(key, value);
|
||||
mVKMap.put(value, key);
|
||||
return put;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
V remove = mKVMap.remove(key);
|
||||
if (remove != null) {
|
||||
mVKMap.remove(key);
|
||||
}
|
||||
return remove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(@NonNull Map<? extends K, ? extends V> m) {
|
||||
mKVMap.putAll(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
mKVMap.clear();
|
||||
mVKMap.clear();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return mKVMap.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public K getKey(V value) {
|
||||
return mVKMap.get(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<V> valueSet() {
|
||||
return mVKMap.keySet();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
return mKVMap.values();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return mKVMap.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return mKVMap.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mKVMap.hashCode();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public V getOrDefault(Object key, V defaultValue) {
|
||||
return mKVMap.getOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public void forEach(BiConsumer<? super K, ? super V> action) {
|
||||
mKVMap.forEach(action);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
|
||||
mKVMap.replaceAll(function);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public V putIfAbsent(K key, V value) {
|
||||
return mKVMap.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public boolean remove(Object key, Object value) {
|
||||
return mKVMap.remove(key, value);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public boolean replace(K key, V oldValue, V newValue) {
|
||||
return mKVMap.replace(key, oldValue, newValue);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public V replace(K key, V value) {
|
||||
return mKVMap.replace(key, value);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||
return mKVMap.computeIfAbsent(key, mappingFunction);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
return mKVMap.computeIfPresent(key, remappingFunction);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
return mKVMap.compute(key, remappingFunction);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
||||
return mKVMap.merge(key, value, remappingFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user