# Conflicts:
#	.idea/caches/build_file_checksums.ser
This commit is contained in:
hyb1996
2018-10-11 10:10:40 +08:00
87 changed files with 1825 additions and 752 deletions

View File

@@ -1,5 +1,7 @@
package org.autojs.autojs;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -10,29 +12,26 @@ 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 org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.autojs.key.GlobalKeyObserver;
import org.autojs.autojs.network.GlideApp;
import org.autojs.autojs.storage.database.IntentTaskDatabase;
import org.autojs.autojs.storage.database.TimedTaskDatabase;
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 org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.autojs.key.GlobalKeyObserver;
import org.autojs.autojs.external.receiver.DynamicBroadcastReceivers;
import org.autojs.autojs.network.GlideApp;
import org.autojs.autojs.timing.IntentTask;
import org.autojs.autojs.timing.TimedTaskManager;
import org.autojs.autojs.timing.TimedTaskScheduler;
import org.autojs.autojs.tool.CrashHandler;
import org.autojs.autojs.ui.error.ErrorReportActivity;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**
* Created by Stardust on 2017/1/27.
@@ -44,6 +43,7 @@ public class App extends MultiDexApplication {
private static final String BUGLY_APP_ID = "19b3607b53";
private static WeakReference<App> instance;
private DynamicBroadcastReceivers mDynamicBroadcastReceivers;
public static App getApp() {
return instance.get();
@@ -58,6 +58,10 @@ public class App extends MultiDexApplication {
init();
}
public DynamicBroadcastReceivers getDynamicBroadcastReceivers() {
return mDynamicBroadcastReceivers;
}
private void setUpStaticsTool() {
if (BuildConfig.DEBUG)
return;
@@ -67,6 +71,11 @@ public class App extends MultiDexApplication {
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
}
private void setUpDebugEnvironment() {
CrashHandler crashHandler = new CrashHandler(ErrorReportActivity.class);
@@ -77,17 +86,16 @@ public class App extends MultiDexApplication {
crashHandler.setBuglyHandler(Thread.getDefaultUncaughtExceptionHandler());
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
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);
@@ -96,6 +104,18 @@ public class App extends MultiDexApplication {
}
setupDrawableImageLoader();
TimedTaskScheduler.checkTasksRepeatedlyIfNeeded(this);
initDynamicBroadcastReceivers();
}
@SuppressLint("CheckResult")
private void initDynamicBroadcastReceivers() {
mDynamicBroadcastReceivers = new DynamicBroadcastReceivers(this);
TimedTaskManager.getInstance().getAllIntentTasks()
.filter(task -> task.getAction() != null)
.map(IntentTask::getAction)
.collectInto(new ArrayList<String>(), ArrayList::add)
.subscribe(list -> mDynamicBroadcastReceivers.register(list),
Throwable::printStackTrace);
}
private void setupDrawableImageLoader() {

View File

@@ -201,4 +201,8 @@ public class Pref {
getString(R.string.default_value_script_dir_path));
return new File(Environment.getExternalStorageDirectory(), dir).getPath();
}
public static boolean isForegroundServiceEnabled() {
return def().getBoolean(getString(R.string.key_foreground_servie), false);
}
}

View File

@@ -50,6 +50,7 @@ public class AutoJsApkBuilder extends ApkBuilder {
public static AppConfig fromProjectConfig(String projectDir, ProjectConfig projectConfig) {
return new AppConfig()
.setAppName(projectConfig.getName())
.setPackageName(projectConfig.getPackageName())
.ignoreDir(new File(projectDir, projectConfig.getBuildDir()))
.setVersionCode(projectConfig.getVersionCode())
.setVersionName(projectConfig.getVersionName())

View File

@@ -0,0 +1,88 @@
package org.autojs.autojs.external.foreground;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import com.stardust.app.GlobalAppContext;
import org.autojs.autojs.R;
import org.autojs.autojs.ui.main.MainActivity_;
public class ForegroundService extends Service {
private static final int NOTIFICATION_ID = 1;
private static final String CHANEL_ID = ForegroundService.class.getName() + ".foreground";
public static void start(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context, ForegroundService.class));
} else {
context.startService(new Intent(context, ForegroundService.class));
}
}
public static void stop(Context context){
context.stopService(new Intent(context, ForegroundService.class));
}
@Override
public void onCreate() {
super.onCreate();
startForeground();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void startForeground() {
startForeground(NOTIFICATION_ID, buildNotification());
}
private Notification buildNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel();
}
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, MainActivity_.intent(this).get(), 0);
return new NotificationCompat.Builder(this, CHANEL_ID)
.setContentTitle(getString(R.string.foreground_notification_title))
.setContentText(getString(R.string.foreground_notification_text))
.setSmallIcon(R.drawable.autojs_material)
.setWhen(System.currentTimeMillis())
.setContentIntent(contentIntent)
.setChannelId(CHANEL_ID)
.build();
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannel() {
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
CharSequence name = getString(R.string.foreground_notification_channel_name);
String description = getString(R.string.foreground_notification_channel_name);
NotificationChannel channel = new NotificationChannel(CHANEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(description);
channel.enableLights(false);
manager.createNotificationChannel(channel);
}
@Override
public void onDestroy() {
stopForeground(true);
super.onDestroy();
}
}

View File

@@ -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: intent = " + intent + ", this = " + this);
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();
}
}
}

View File

@@ -0,0 +1,78 @@
package org.autojs.autojs.external.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.os.Build;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
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_PACKAGES_SUSPENDED;
import static android.content.Intent.ACTION_PACKAGES_UNSUSPENDED;
import static android.content.Intent.ACTION_SCREEN_OFF;
import static android.content.Intent.ACTION_SCREEN_ON;
import static android.content.Intent.ACTION_TIME_TICK;
public class DynamicBroadcastReceivers {
private static final List<String> DEFAULT_ACTIONS = new ArrayList<>(Arrays.asList(
ACTION_TIME_TICK,
ACTION_SCREEN_OFF,
ACTION_SCREEN_ON,
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 final Set<String> mActions = new LinkedHashSet<>();
private final List<BroadcastReceiver> mReceivers = new ArrayList<>();
private final Context mContext;
public DynamicBroadcastReceivers(Context context) {
mContext = context;
register(DEFAULT_ACTIONS);
}
public void register(String action) {
register(Collections.singletonList(action));
}
public void register(List<String> actions) {
IntentFilter filter = new IntentFilter();
for (String action : actions) {
if (!StaticBroadcastReceiver.ACTIONS.contains(action)
&& !mActions.contains(action)) {
mActions.add(action);
filter.addAction(action);
}
}
if (filter.countActions() == 0) {
return;
}
BaseBroadcastReceiver receiver = new BaseBroadcastReceiver();
mContext.registerReceiver(receiver, filter);
}
public void unregisterAll() {
for (BroadcastReceiver receiver : mReceivers) {
mContext.unregisterReceiver(receiver);
}
mReceivers.clear();
}
}

View 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"
));
}

View File

@@ -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,8 @@ 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_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)
@@ -63,4 +65,9 @@ public class TaskerScriptEditActivity extends BaseActivity {
TaskerScriptEditActivity.super.finish();
}
@Override
protected void onDestroy() {
mEditorView.destroy();
super.onDestroy();
}
}

View File

@@ -161,4 +161,7 @@ public class AutoCompletion {
}
public void shutdown(){
mExecutorService.shutdownNow();
}
}

View File

@@ -30,6 +30,10 @@ public class Explorer {
this(explorerProvider, cacheSize, EventBus.getDefault());
}
public ExplorerProvider getProvider() {
return mExplorerProvider;
}
public void notifyChildrenChanged(ExplorerPage page) {
clearCache(page);
mEventBus.post(new ExplorerChangeEvent(page, CHILDREN_CHANGE, null));

View File

@@ -4,16 +4,16 @@ import com.stardust.pio.PFile;
import java.io.File;
public class ExplorerSamleItem extends ExplorerFileItem {
public ExplorerSamleItem(PFile file, ExplorerPage parent) {
public class ExplorerSampleItem extends ExplorerFileItem {
public ExplorerSampleItem(PFile file, ExplorerPage parent) {
super(file, parent);
}
public ExplorerSamleItem(String path, ExplorerPage parent) {
public ExplorerSampleItem(String path, ExplorerPage parent) {
super(path, parent);
}
public ExplorerSamleItem(File file, ExplorerPage parent) {
public ExplorerSampleItem(File file, ExplorerPage parent) {
super(file, parent);
}

View File

@@ -8,6 +8,7 @@ import com.stardust.pio.PFile;
import com.stardust.pio.PFiles;
import org.autojs.autojs.Pref;
import org.autojs.autojs.model.sample.SampleFile;
import java.io.File;
import java.io.FileFilter;
@@ -52,7 +53,7 @@ public class WorkspaceFileProvider extends ExplorerFileProvider {
}
} else {
if (file.getPath().startsWith(mSampleDir.getPath())) {
p.addChild(new ExplorerSamleItem(file, p));
p.addChild(new ExplorerSampleItem(file, p));
} else {
p.addChild(new ExplorerFileItem(file, p));
}
@@ -98,6 +99,10 @@ public class WorkspaceFileProvider extends ExplorerFileProvider {
});
}
public static void resetSample(SampleFile sampleFile){
}
@Override
protected ExplorerDirPage createExplorerPage(String path, ExplorerPage parent) {
ExplorerDirPage page = super.createExplorerPage(path, parent);

View File

@@ -12,10 +12,9 @@ import android.util.Pair;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.stardust.util.MapEntries;
import com.stardust.util.MapBuilder;
import org.autojs.autojs.BuildConfig;
import org.autojs.autojs.tool.EmptyObservers;
import java.io.IOException;
import java.net.SocketTimeoutException;
@@ -24,7 +23,6 @@ import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import okhttp3.OkHttpClient;
import okhttp3.Request;
@@ -171,12 +169,12 @@ public class DevPluginService {
@WorkerThread
private void sayHelloToServer(JsonWebSocket socket) throws IOException {
writeMap(socket, TYPE_HELLO, new MapEntries<String, Object>()
.entry("device_name", Build.BRAND + " " + Build.MODEL)
.entry("client_version", CLIENT_VERSION)
.entry("app_version", BuildConfig.VERSION_NAME)
.entry("app_version_code", BuildConfig.VERSION_CODE)
.map());
writeMap(socket, TYPE_HELLO, new MapBuilder<String, Object>()
.put("device_name", Build.BRAND + " " + Build.MODEL)
.put("client_version", CLIENT_VERSION)
.put("app_version", BuildConfig.VERSION_NAME)
.put("app_version_code", BuildConfig.VERSION_CODE)
.build());
mHandshakeTimeoutHandler.postDelayed(() -> {
if (mSocket != socket && !socket.isClosed()) {
onHandshakeTimeout(socket);

View File

@@ -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));
}
}

View File

@@ -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;
}
}
}

View File

@@ -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) {
}
}
}

View File

@@ -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;
}

View File

@@ -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) {
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -1,29 +1,22 @@
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 android.text.TextUtils;
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.App;
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;
/**
* Created by Stardust on 2017/11/27.
@@ -31,12 +24,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 +36,132 @@ 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(i -> {
if(!TextUtils.isEmpty(intentTask.getAction())){
App.getApp().getDynamicBroadcastReceivers()
.register(intentTask.getAction());
}
}, 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);
}
@SuppressLint("CheckResult")
public void updateTask(IntentTask task) {
mIntentTaskDatabase.update(task)
.subscribe(i -> {
if(i > 0 && !TextUtils.isEmpty(task.getAction())){
App.getApp().getDynamicBroadcastReceivers()
.register(task.getAction());
}
}, Throwable::printStackTrace);
}
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();
}
public IntentTask getIntentTask(long intentTaskId) {
return mIntentTaskDatabase.queryById(intentTaskId);
}
public Flowable<IntentTask> getAllIntentTasks() {
return mIntentTaskDatabase.queryAllAsFlowable();
}
}

View File

@@ -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;
}

View File

@@ -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;
@@ -122,7 +123,11 @@ public class ScriptOperations {
}
private void notifyFileCreated(ScriptFile directory, ScriptFile scriptFile) {
mExplorer.notifyItemCreated(new ExplorerFileItem(scriptFile, mExplorerPage));
if (scriptFile.isDirectory()) {
mExplorer.notifyItemCreated(new ExplorerDirPage(scriptFile, mExplorerPage));
} else {
mExplorer.notifyItemCreated(new ExplorerFileItem(scriptFile, mExplorerPage));
}
}
public void newFile() {
@@ -315,9 +320,11 @@ 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)
.dir(Pref.getScriptDirPath())
.chooseDir()
.singleChoice()
.map(saveDir -> new File(saveDir, fileName).getPath())

View File

@@ -74,23 +74,12 @@ public class DocsFragment extends ViewPagerFragment implements BackPressedHandle
}
@Override
public void onResume() {
super.onResume();
((BackPressedHandler.HostActivity) getActivity())
.getBackPressedObserver()
.registerHandlerAtFront(this);
}
@Override
public void onPause() {
super.onPause();
Bundle savedWebViewState = new Bundle();
mWebView.saveState(savedWebViewState);
getArguments().putBundle("savedWebViewState", savedWebViewState);
((BackPressedHandler.HostActivity) getActivity())
.getBackPressedObserver()
.unregisterHandler(this);
}
@Override

View File

@@ -180,6 +180,7 @@ EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHo
@Override
protected void onDestroy() {
mEditorView.destroy();
super.onDestroy();
}

View File

@@ -392,7 +392,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
}
ScriptExecution execution = Scripts.runWithBroadcastSender(mFile);
if(execution == null){
if (execution == null) {
return null;
}
mScriptExecutionId = execution.getId();
@@ -671,4 +671,9 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
super.onRestoreInstanceState(superData);
setMenuItemStatus(R.id.run, mScriptExecutionId == ScriptExecution.NO_ID);
}
public void destroy() {
mEditor.destroy();
mAutoCompletion.shutdown();
}
}

View File

@@ -373,6 +373,11 @@ public class CodeEditor extends HVScrollView {
mCodeEditText.removeAllBreakpoints();
}
public void destroy(){
mJavaScriptHighlighter.shutdown();
mJsBeautifier.shutdown();
}
@Override
protected void onDraw(Canvas canvas) {
int codeWidth = getWidth() - getPaddingLeft() - getPaddingRight();

View File

@@ -2,10 +2,12 @@ package org.autojs.autojs.ui.edit.editor;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.TimingLogger;
import com.stardust.autojs.rhino.TokenStream;
import com.stardust.pio.UncheckedIOException;
import org.autojs.autojs.ui.edit.theme.Theme;
import org.autojs.autojs.ui.widget.SimpleTextWatcher;
@@ -46,7 +48,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
@Override
public String toString() {
return super.toString() + "{count = " + mCount + ", length = " + mText.length() + "}";
return super.toString() + "{count = " + mCount + ", length = " + mText.length() + "}";
}
public int getCharCount() {
@@ -60,16 +62,18 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
private Theme mTheme;
private CodeEditText mCodeEditText;
private ThreadPoolExecutor mExecutorService = new ThreadPoolExecutor(3, 6,
private ThreadPoolExecutor mExecutorService = new ThreadPoolExecutor(3, 6,
2L, TimeUnit.MINUTES, new LinkedBlockingQueue<>());
private AtomicInteger mRunningHighlighterId = new AtomicInteger();
private TimingLogger mLogger = new TimingLogger(CodeEditText.LOG_TAG, "highlight");
private final TextWatcher mTextWatcher;
public JavaScriptHighlighter(Theme theme, CodeEditText codeEditText) {
mExecutorService.allowCoreThreadTimeOut(true);
mTheme = theme;
mCodeEditText = codeEditText;
codeEditText.addTextChangedListener(new SimpleTextWatcher(this));
mTextWatcher = new SimpleTextWatcher(this);
codeEditText.addTextChangedListener(mTextWatcher);
}
@Override
@@ -112,5 +116,9 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
mCodeEditText.updateHighlightTokens(highlightTokens);
}
public void shutdown() {
mCodeEditText.removeTextChangedListener(mTextWatcher);
mExecutorService.shutdownNow();
}
}

View File

@@ -1,290 +0,0 @@
package org.autojs.autojs.ui.edit.editor;
/*
* Copyright 2016. SHENQINCI(沈钦赐)<946736079@qq.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.support.annotation.NonNull;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import java.util.Stack;
/**
* 撤销和恢复撤销
* Created by 沈钦赐 on 16/6/23.
*/
public class TextViewRedoUndoer {
//操作序号(一次编辑可能对应多个操作,如替换文字,就是删除+插入)
int index;
//撤销栈
Stack<Action> history = new Stack<>();
//恢复栈
Stack<Action> historyBack = new Stack<>();
private Editable editable;
private EditText editText;
//自动操作标志,防止重复回调,导致无限撤销
private boolean flag = false;
private int mInitialHistoryStackSize;
private boolean mEnabled = true;
public TextViewRedoUndoer(@NonNull EditText editText) {
this.editable = editText.getText();
this.editText = editText;
editText.addTextChangedListener(new Watcher());
}
protected void onEditableChanged(Editable s) {
}
protected void onTextChanged(Editable s) {
if (history.size() < mInitialHistoryStackSize) {
mInitialHistoryStackSize = 0;
}
}
/**
* 清理记录
* Clear history.
*/
public final void clearHistory() {
history.clear();
historyBack.clear();
mInitialHistoryStackSize = 0;
}
public boolean canUndo() {
return !history.empty();
}
/**
* 撤销
* Undo.
*/
public final void undo() {
if (history.empty()) return;
//锁定操作
flag = true;
Action action = history.pop();
historyBack.push(action);
if (action.isAdd) {
//撤销添加
editable.delete(action.startCursor, action.startCursor + action.actionTarget.length());
editText.setSelection(action.startCursor, action.startCursor);
} else {
//插销删除
editable.insert(action.startCursor, action.actionTarget);
if (action.endCursor == action.startCursor) {
editText.setSelection(action.startCursor + action.actionTarget.length());
} else {
editText.setSelection(action.startCursor, action.endCursor);
}
}
//释放操作
flag = false;
//判断是否是下一个动作是否和本动作是同一个操作,直到不同为止
if (!history.empty() && history.peek().index == action.index) {
undo();
}
}
public boolean canRedo() {
return !historyBack.empty();
}
/**
* 恢复
* Redo.
*/
public final void redo() {
if (historyBack.empty()) return;
flag = true;
Action action = historyBack.pop();
history.push(action);
if (action.isAdd) {
//恢复添加
editable.insert(action.startCursor, action.actionTarget);
if (action.endCursor == action.startCursor) {
editText.setSelection(action.startCursor + action.actionTarget.length());
} else {
editText.setSelection(action.startCursor, action.endCursor);
}
} else {
//恢复删除
editable.delete(action.startCursor, action.startCursor + action.actionTarget.length());
editText.setSelection(action.startCursor, action.startCursor);
}
flag = false;
//判断是否是下一个动作是否和本动作是同一个操作
if (!historyBack.empty() && historyBack.peek().index == action.index)
redo();
}
/**
* 首次设置文本
* Set default text.
*/
public final void setDefaultText(CharSequence text) {
clearHistory();
flag = true;
editable.replace(0, editable.length(), text);
flag = false;
}
public boolean isTextChanged() {
return history.size() != mInitialHistoryStackSize;
}
public void markTextAsUnchanged() {
mInitialHistoryStackSize = history.size();
}
public void setEnabled(boolean enabled) {
mEnabled = enabled;
}
public boolean isEnabled() {
return mEnabled;
}
private class Watcher implements TextWatcher {
/**
* Before text changed.
*
* @param s the s
* @param start the start 起始光标
* @param count the endCursor 选择数量
* @param after the after 替换增加的文字数
*/
@Override
public final void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (!editText.isEnabled() || !mEnabled) {
return;
}
if (flag) return;
int end = start + count;
if (end > start && end <= s.length()) {
CharSequence charSequence = s.subSequence(start, end);
//删除了文字
if (charSequence.length() > 0) {
Action action = new Action(charSequence, start, false);
if (count > 1) {
//如果一次超过一个字符,说名用户选择了,然后替换或者删除操作
action.setSelectCount(count);
} else if (count == 1 && count == after) {
//一个字符替换
action.setSelectCount(count);
}
//还有一种情况:选择一个字符,然后删除(暂时没有考虑这种情况)
history.push(action);
historyBack.clear();
action.setIndex(++index);
}
}
}
/**
* On text changed.
*
* @param s the s
* @param start the start 起始光标
* @param before the before 选择数量
* @param count the endCursor 添加的数量
*/
@Override
public final void onTextChanged(CharSequence s, int start, int before, int count) {
if (!editText.isEnabled() || !mEnabled) {
return;
}
if (flag) return;
int end = start + count;
if (end > start) {
CharSequence charSequence = s.subSequence(start, end);
//添加文字
if (charSequence.length() > 0) {
Action action = new Action(charSequence, start, true);
history.push(action);
historyBack.clear();
if (before > 0) {
//文字替换(先删除再增加),删除和增加是同一个操作,所以不需要增加序号
action.setIndex(index);
} else {
action.setIndex(++index);
}
}
}
}
@Override
public final void afterTextChanged(Editable s) {
if (!editText.isEnabled() || !mEnabled) {
return;
}
if (flag) return;
if (s != editable) {
editable = s;
onEditableChanged(s);
}
TextViewRedoUndoer.this.onTextChanged(s);
}
}
private class Action {
/**
* 改变字符.
*/
CharSequence actionTarget;
/**
* 光标位置.
*/
int startCursor;
int endCursor;
/**
* 标志增加操作.
*/
boolean isAdd;
/**
* 操作序号.
*/
int index;
public Action(CharSequence actionTag, int startCursor, boolean add) {
this.actionTarget = actionTag;
this.startCursor = startCursor;
this.endCursor = startCursor;
this.isAdd = add;
}
public void setSelectCount(int count) {
this.endCursor = endCursor + count;
}
public void setIndex(int index) {
this.index = index;
}
}
}

View File

@@ -9,6 +9,7 @@ import java.util.LinkedList;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Handler;
import android.text.Editable;
import android.text.Selection;
import android.text.TextWatcher;
@@ -46,6 +47,10 @@ public class TextViewUndoRedo {
private int mInitialHistoryStackSize;
private Handler mHandler = new Handler();
private int mTextChangeId = 0;
private boolean mTextChanging = false;
// =================================================================== //
/**
@@ -404,7 +409,6 @@ public class TextViewUndoRedo {
if (mIsUndoOrRedo || !mEnabled) {
return;
}
mBeforeChange = s.subSequence(start, start + count);
}
@@ -415,7 +419,10 @@ public class TextViewUndoRedo {
}
mAfterChange = s.subSequence(start, start + count);
mTextChangeId++;
mEditHistory.add(new EditItem(start, mBeforeChange, mAfterChange));
int textChangeId = mTextChangeId;
//TODO 增加连续输入文字当成一次撤销的功能
}
public void afterTextChanged(Editable s) {

View File

@@ -4,9 +4,6 @@ import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.CardView;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -14,7 +11,6 @@ import com.stardust.autojs.project.ProjectConfig;
import com.stardust.autojs.project.ProjectLauncher;
import com.stardust.pio.PFile;
import org.androidannotations.annotations.Click;
import org.autojs.autojs.R;
import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.model.explorer.ExplorerChangeEvent;
@@ -59,15 +55,19 @@ public class ExplorerProjectToolbar extends CardView {
setOnClickListener(view -> edit());
}
public void setProject(PFile dir, ProjectConfig config) {
public void setProject(PFile dir) {
mProjectConfig = ProjectConfig.fromProjectDir(dir.getPath());
if(mProjectConfig == null){
setVisibility(GONE);
return;
}
mDirectory = dir;
mProjectConfig = config;
mProjectName.setText(config.getName());
mProjectName.setText(mProjectConfig.getName());
}
public void refresh() {
if (mDirectory != null) {
setProject(mDirectory, ProjectConfig.fromProjectDir(mDirectory.getPath()));
setProject(mDirectory);
}
}

View File

@@ -27,7 +27,11 @@ import org.autojs.autojs.model.explorer.ExplorerFileItem;
import org.autojs.autojs.model.explorer.ExplorerItem;
import org.autojs.autojs.model.explorer.ExplorerPage;
import org.autojs.autojs.model.explorer.ExplorerProjectPage;
import org.autojs.autojs.model.explorer.ExplorerSampleItem;
import org.autojs.autojs.model.explorer.ExplorerSamplePage;
import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.model.explorer.WorkspaceFileProvider;
import org.autojs.autojs.model.sample.SampleFile;
import org.autojs.autojs.model.script.ScriptFile;
import org.autojs.autojs.model.script.Scripts;
import org.autojs.autojs.ui.project.BuildActivity;
@@ -111,7 +115,7 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
mCurrentPageState = currentPageState;
if (mCurrentPageState.page instanceof ExplorerProjectPage) {
mProjectToolbar.setVisibility(VISIBLE);
mProjectToolbar.setProject(currentPageState.page.toScriptFile(), ((ExplorerProjectPage) currentPageState.page).getProjectConfig());
mProjectToolbar.setProject(currentPageState.page.toScriptFile());
} else {
mProjectToolbar.setVisibility(GONE);
}
@@ -306,6 +310,8 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
case R.id.action_sort_by_size:
sort(ExplorerItemList.SORT_TYPE_SIZE, mDirSortMenuShowing);
break;
case R.id.reset:
// WorkspaceFileProvider.resetSample(mSelectedItem.toScriptFile());
default:
return false;
}
@@ -487,6 +493,9 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
}
if (!mExplorerItem.canRename()) {
menu.removeItem(R.id.rename);
}
if(mExplorerItem instanceof ExplorerSampleItem){
}
popupMenu.setOnMenuItemClickListener(ExplorerView.this);
popupMenu.show();

View File

@@ -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;
}

View File

@@ -115,7 +115,7 @@ public class CircularMenu implements Recorder.OnStateChangedListener, LayoutInsp
@Override
public View inflateActionView(FloatyService service, CircularMenuWindow window) {
View actionView = View.inflate(service, R.layout.circular_action_view, null);
mActionViewIcon = (RoundedImageView) actionView.findViewById(R.id.icon);
mActionViewIcon = actionView.findViewById(R.id.icon);
return actionView;
}

View File

@@ -1,11 +1,8 @@
package org.autojs.autojs.ui.floating;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.util.Log;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.WindowManager;
@@ -15,9 +12,13 @@ import com.stardust.enhancedfloaty.FloatyWindow;
import com.stardust.enhancedfloaty.WindowBridge;
import com.stardust.floatingcircularactionmenu.CircularActionMenu;
import com.stardust.floatingcircularactionmenu.gesture.BounceDragGesture;
import com.stardust.util.ScreenMetrics;
public class CircularMenuWindow implements FloatyWindow {
private static final String KEY_POSITION_X = CircularMenuWindow.class.getName() + ".position.x";
private static final String KEY_POSITION_Y = CircularMenuWindow.class.getName() + ".position.y";
protected CircularMenuFloaty mFloaty;
protected WindowManager mWindowManager;
protected CircularActionMenu mCircularActionMenu;
@@ -66,6 +67,9 @@ public class CircularMenuWindow implements FloatyWindow {
}
private void setInitialState() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
int y = preferences.getInt(KEY_POSITION_Y, ScreenMetrics.getDeviceScreenHeight() / 2);
mActionViewWindowBridge.updatePosition(mActionViewWindowBridge.getX(), y);
keepToSide();
}
@@ -190,6 +194,11 @@ public class CircularMenuWindow implements FloatyWindow {
}
public void close() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
preferences.edit()
.putInt(KEY_POSITION_X, mActionViewWindowBridge.getX())
.putInt(KEY_POSITION_Y, mActionViewWindowBridge.getY())
.apply();
mOrientationEventListener.disable();
this.mWindowManager.removeView(this.mCircularActionMenu);
this.mWindowManager.removeView(this.mCircularActionView);

View File

@@ -37,6 +37,7 @@ import org.autojs.autojs.BuildConfig;
import org.autojs.autojs.Pref;
import org.autojs.autojs.R;
import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.external.foreground.ForegroundService;
import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.tool.AccessibilityServiceTool;
import org.autojs.autojs.ui.BaseActivity;
@@ -208,6 +209,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
public void exitCompletely() {
finish();
FloatyWindowManger.hideCircularMenu();
ForegroundService.stop(this);
stopService(new Intent(this, FloatyService.class));
AutoJs.getInstance().getScriptEngineService().stopAll();
}
@@ -264,6 +266,12 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
@Override
public void onBackPressed() {
Fragment fragment = mPagerAdapter.getStoredFragment(mViewPager.getCurrentItem());
if (fragment instanceof BackPressedHandler) {
if (((BackPressedHandler) fragment).onBackPressed(this)) {
return;
}
}
if (!mBackPressObserver.onBackPressed(this)) {
super.onBackPressed();
}

View File

@@ -3,14 +3,17 @@ package org.autojs.autojs.ui.main;
import android.support.annotation.CallSuper;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.View;
import com.stardust.util.BackPressedHandler;
/**
* Created by Stardust on 2017/8/22.
*/
public abstract class ViewPagerFragment extends Fragment {
public abstract class ViewPagerFragment extends Fragment implements BackPressedHandler {
protected static final int ROTATION_GONE = -1;

View File

@@ -72,23 +72,12 @@ public class CommunityFragment extends ViewPagerFragment implements BackPressedH
}
}
@Override
public void onResume() {
super.onResume();
((BackPressedHandler.HostActivity) getActivity())
.getBackPressedObserver()
.registerHandlerAtFront(this);
}
@Override
public void onPause() {
super.onPause();
Bundle savedWebViewState = new Bundle();
mWebView.saveState(savedWebViewState);
getArguments().putBundle("savedWebViewState", savedWebViewState);
((BackPressedHandler.HostActivity) getActivity())
.getBackPressedObserver()
.unregisterHandler(this);
}
@Override

View File

@@ -1,5 +1,6 @@
package org.autojs.autojs.ui.main.drawer;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -22,6 +23,7 @@ import com.stardust.notification.NotificationListenerService;
import org.autojs.autojs.Pref;
import org.autojs.autojs.R;
import org.autojs.autojs.external.foreground.ForegroundService;
import org.autojs.autojs.network.GlideApp;
import org.autojs.autojs.network.UserService;
import org.autojs.autojs.tool.EmptyObservers;
@@ -107,6 +109,8 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
};
private DrawerMenuItem mNotificationPermissionItem = new DrawerMenuItem(R.drawable.ic_ali_notification, R.string.text_notification_permission, 0, this::goToNotificationServiceSettings);
private DrawerMenuItem mForegroundServiceItem = new DrawerMenuItem(R.drawable.ic_service_green, R.string.text_foreground_service, R.string.key_foreground_servie, this::toggleForegroundService);
private DrawerMenuItem mFloatingWindowItem = new DrawerMenuItem(R.drawable.ic_robot_64, R.string.text_floating_window, 0, this::showOrDismissFloatingWindow);
private DrawerMenuItem mCheckForUpdatesItem = new DrawerMenuItem(R.drawable.ic_check_for_updates, R.string.text_check_for_updates, this::checkForUpdates);
@@ -142,6 +146,10 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
setChecked(mFloatingWindowItem, true);
}
setChecked(mConnectionItem, DevPluginService.getInstance().isConnected());
if(Pref.isForegroundServiceEnabled()){
ForegroundService.start(GlobalAppContext.get());
setChecked(mForegroundServiceItem, true);
}
}
private void initMenuItems() {
@@ -150,6 +158,7 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
mAccessibilityServiceItem,
mStableModeItem,
mNotificationPermissionItem,
mForegroundServiceItem,
new DrawerMenuGroup(R.string.text_script_record),
mFloatingWindowItem,
@@ -165,6 +174,7 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
}
@SuppressLint("CheckResult")
@Click(R.id.avatar)
void loginOrShowUserInfo() {
UserService.getInstance()
@@ -251,6 +261,17 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
}
}
private void toggleForegroundService(DrawerMenuItemViewHolder holder) {
boolean checked = holder.getSwitchCompat().isChecked();
if(checked){
ForegroundService.start(GlobalAppContext.get());
}else {
ForegroundService.stop(GlobalAppContext.get());
}
}
private void inputRemoteHost() {
String host = Pref.getServerAddressOrDefault(WifiTool.getRouterIp(getActivity()));
new MaterialDialog.Builder(getActivity())

View File

@@ -62,7 +62,6 @@ public class MarketFragment extends ViewPagerFragment implements BackPressedHand
@Override
public boolean onBackPressed(Activity activity) {
return false;
}

View File

@@ -5,7 +5,9 @@ import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.RecyclerView;
import com.stardust.app.GlobalAppContext;
import com.stardust.util.BackPressedHandler;
import com.stardust.util.IntentUtil;
@@ -26,6 +28,7 @@ import org.autojs.autojs.ui.main.ViewPagerFragment;
import org.autojs.autojs.ui.project.ProjectConfigActivity;
import org.autojs.autojs.ui.project.ProjectConfigActivity_;
import org.autojs.autojs.ui.viewmodel.ExplorerItemList;
import org.autojs.autojs.ui.widget.ExpandableRecyclerView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -35,7 +38,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
* Created by Stardust on 2017/3/13.
*/
@EFragment(R.layout.fragment_my_script_list)
public class MyScriptListFragment extends ViewPagerFragment implements BackPressedHandler, FloatingActionMenu.OnFloatingActionButtonClickListener {
public class MyScriptListFragment extends ViewPagerFragment implements FloatingActionMenu.OnFloatingActionButtonClickListener {
private static final String TAG = "MyScriptListFragment";
@@ -63,27 +66,11 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress
if (item.isEditable()) {
Scripts.edit(item.toScriptFile());
} else {
IntentUtil.viewFile(getContext(), item.getPath());
IntentUtil.viewFile(GlobalAppContext.get(), item.getPath());
}
});
}
@Override
public void onResume() {
super.onResume();
((BackPressedHandler.HostActivity) getActivity())
.getBackPressedObserver()
.registerHandlerAtFront(this);
}
@Override
public void onPause() {
super.onPause();
((BackPressedHandler.HostActivity) getActivity())
.getBackPressedObserver()
.unregisterHandler(this);
}
@Override
protected void onFabClick(FloatingActionButton fab) {
initFloatingActionMenuIfNeeded(fab);
@@ -98,7 +85,7 @@ public class MyScriptListFragment extends ViewPagerFragment implements BackPress
private void initFloatingActionMenuIfNeeded(final FloatingActionButton fab) {
if (mFloatingActionMenu != null)
return;
mFloatingActionMenu = ((FloatingActionMenu) getActivity().findViewById(R.id.floating_action_menu));
mFloatingActionMenu = getActivity().findViewById(R.id.floating_action_menu);
mFloatingActionMenu.getState()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SimpleObserver<Boolean>() {

View File

@@ -1,24 +1,33 @@
package org.autojs.autojs.ui.main.task;
import android.content.Intent;
import com.stardust.app.GlobalAppContext;
import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.script.AutoFileSource;
import com.stardust.autojs.script.JavaScriptSource;
import com.stardust.pio.PFiles;
import com.stardust.util.MapBuilder;
import org.autojs.autojs.R;
import org.autojs.autojs.timing.IntentTask;
import org.autojs.autojs.timing.TimedTask;
import org.autojs.autojs.timing.TimedTaskManager;
import org.joda.time.format.DateTimeFormat;
import java.util.Map;
import static org.autojs.autojs.ui.timing.TimedTaskSettingActivity.ACTION_DESC_MAP;
/**
* Created by Stardust on 2017/11/28.
*/
public abstract class Task {
public abstract String getName();
public abstract String getDesc();
@@ -29,11 +38,26 @@ 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,24 +66,47 @@ 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;
Integer desc = ACTION_DESC_MAP.get(mIntentTask.getAction());
if(desc != null){
return GlobalAppContext.getString(desc);
}
return mIntentTask.getAction();
}
}
@Override
public void cancel() {
TimedTaskManager.getInstance().removeTask(mTimedTask);
if (mTimedTask != null) {
TimedTaskManager.getInstance().removeTask(mTimedTask);
} else {
TimedTaskManager.getInstance().removeTask(mIntentTask);
}
}
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 +116,16 @@ public abstract class Task {
public void setTimedTask(TimedTask timedTask) {
mTimedTask = timedTask;
}
public void setIntentTask(IntentTask intentTask) {
mIntentTask = intentTask;
}
public long getId() {
if(mTimedTask != null)
return mTimedTask.getId();
return mIntentTask.getId();
}
}
public static class RunningTask extends Task {

View File

@@ -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,56 @@ 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;
}
}

View File

@@ -13,30 +13,28 @@ 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 org.autojs.autojs.ui.timing.TimedTaskSettingActivity_;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
import java.util.ArrayList;
import java.util.List;
@@ -60,7 +58,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 +133,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 +152,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();
}
}
@@ -249,8 +249,11 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView {
void onItemClick(View view) {
if (mTask instanceof Task.PendingTask) {
Task.PendingTask task = (Task.PendingTask) mTask;
String extra = task.getTimedTask() == null ? TimedTaskSettingActivity.EXTRA_INTENT_TASK_ID
: TimedTaskSettingActivity.EXTRA_TASK_ID;
TimedTaskSettingActivity_.intent(getContext())
.extra(TaskReceiver.EXTRA_TASK_ID, ((Task.PendingTask) mTask).getTimedTask().getId())
.extra(extra, task.getId())
.start();
}
}
@@ -263,8 +266,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();

View File

@@ -1,5 +1,6 @@
package org.autojs.autojs.ui.main.task;
import android.app.Activity;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.widget.SwipeRefreshLayout;
@@ -70,4 +71,8 @@ public class TaskManagerFragment extends ViewPagerFragment {
AutoJs.getInstance().getScriptEngineService().stopAll();
}
@Override
public boolean onBackPressed(Activity activity) {
return false;
}
}

View File

@@ -39,6 +39,7 @@ import org.autojs.autojs.ui.shortcut.ShortcutIconSelectActivity_;
import java.io.File;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Locale;
import java.util.concurrent.Callable;
@@ -116,7 +117,6 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
if (version < ApkBuilderPluginHelper.getSuitablePluginVersion()) {
showPluginDownloadDialog(R.string.apk_builder_plugin_version_too_low, false);
}
}
private void showPluginDownloadDialog(int msgRes, boolean finishIfCanceled) {

View File

@@ -12,6 +12,7 @@ import android.widget.ImageView;
import android.widget.Toast;
import com.stardust.autojs.project.ProjectConfig;
import com.stardust.autojs.runtime.api.Dialogs;
import com.stardust.pio.PFiles;
import org.androidannotations.annotations.AfterViews;
@@ -24,6 +25,7 @@ import org.autojs.autojs.model.explorer.ExplorerFileItem;
import org.autojs.autojs.model.explorer.ExplorerItem;
import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.model.project.ProjectTemplate;
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
import org.autojs.autojs.ui.BaseActivity;
import org.autojs.autojs.ui.widget.SimpleTextWatcher;
@@ -89,11 +91,21 @@ public class ProjectConfigActivity extends BaseActivity {
}
mDirectory = new File(dir);
mProjectConfig = ProjectConfig.fromProjectDir(dir);
if (mProjectConfig == null) {
new ThemeColorMaterialDialogBuilder(this)
.title(R.string.text_invalid_project)
.positiveText(R.string.ok)
.dismissListener(dialogInterface -> finish())
.show();
}
}
}
@AfterViews
void setupViews() {
if (mProjectConfig == null) {
return;
}
setToolbarAsBack(mNewProject ? getString(R.string.text_new_project) : mProjectConfig.getName());
if (mNewProject) {
mAppName.addTextChangedListener(new SimpleTextWatcher(s ->

View File

@@ -12,7 +12,7 @@ import android.view.View;
import com.stardust.theme.app.ColorSelectActivity;
import com.stardust.theme.preference.ThemeColorPreferenceFragment;
import com.stardust.theme.util.ListBuilder;
import com.stardust.util.MapEntries;
import com.stardust.util.MapBuilder;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
@@ -100,14 +100,14 @@ public class SettingsActivity extends BaseActivity {
@Override
public void onStart() {
super.onStart();
ACTION_MAP = new MapEntries<String, Runnable>()
.entry(getString(R.string.text_theme_color), () -> selectThemeColor(getActivity()))
.entry(getString(R.string.text_check_for_updates), () -> new UpdateCheckDialog(getActivity())
ACTION_MAP = new MapBuilder<String, Runnable>()
.put(getString(R.string.text_theme_color), () -> selectThemeColor(getActivity()))
.put(getString(R.string.text_check_for_updates), () -> new UpdateCheckDialog(getActivity())
.show())
.entry(getString(R.string.text_issue_report), () -> startActivity(new Intent(getActivity(), IssueReporterActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
.entry(getString(R.string.text_about_me_and_repo), () -> startActivity(new Intent(getActivity(), AboutActivity_.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
.entry(getString(R.string.text_licenses), () -> showLicenseDialog())
.map();
.put(getString(R.string.text_issue_report), () -> startActivity(new Intent(getActivity(), IssueReporterActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
.put(getString(R.string.text_about_me_and_repo), () -> startActivity(new Intent(getActivity(), AboutActivity_.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
.put(getString(R.string.text_licenses), () -> showLicenseDialog())
.build();
}
@Override

View File

@@ -51,7 +51,7 @@ public class SplashActivity extends BaseActivity {
mNotStartMainActivity = getIntent().getBooleanExtra(NOT_START_MAIN_ACTIVITY, false);
boolean forceShowAd = getIntent().getBooleanExtra(FORCE_SHOW_AD, false);
setContentView(R.layout.activity_splash);
mFullScreenAdView = (FullScreenAdView) findViewById(R.id.full_screen_view);
mFullScreenAdView = findViewById(R.id.full_screen_view);
if (!forceShowAd && !Pref.shouldShowAd()) {
mFullScreenAdView.setVisibility(View.INVISIBLE);
mHandler.postDelayed(this::enterNextActivity, 1500);

View File

@@ -3,6 +3,8 @@ package org.autojs.autojs.ui.timing;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.graphics.ColorFilter;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -18,6 +20,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 +30,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.MapBuilder;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.CheckedChange;
@@ -49,6 +55,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.
@@ -56,12 +63,51 @@ import java.util.List;
@EActivity(R.layout.activity_timed_task_setting)
public class TimedTaskSettingActivity extends BaseActivity {
public static final String EXTRA_INTENT_TASK_ID = "intent_task_id";
public static final String EXTRA_TASK_ID = TaskReceiver.EXTRA_TASK_ID;
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";
public static final Map<String, Integer> ACTION_DESC_MAP = new MapBuilder<String, Integer>()
.put(Intent.ACTION_BOOT_COMPLETED, R.string.text_run_on_boot)
.put(Intent.ACTION_SCREEN_OFF, R.string.text_run_on_screen_off)
.put(Intent.ACTION_SCREEN_ON, R.string.text_run_on_screen_on)
.put(Intent.ACTION_USER_PRESENT, R.string.text_run_on_screen_unlock)
.put(Intent.ACTION_BATTERY_CHANGED, R.string.text_run_on_battery_change)
.put(Intent.ACTION_POWER_CONNECTED, R.string.text_run_on_power_connect)
.put(Intent.ACTION_POWER_DISCONNECTED, R.string.text_run_on_power_disconnect)
.put(ConnectivityManager.CONNECTIVITY_ACTION, R.string.text_run_on_conn_change)
.put(Intent.ACTION_PACKAGE_ADDED, R.string.text_run_on_package_install)
.put(Intent.ACTION_PACKAGE_REMOVED, R.string.text_run_on_package_uninstall)
.put(Intent.ACTION_PACKAGE_REPLACED, R.string.text_run_on_package_update)
.put(Intent.ACTION_HEADSET_PLUG, R.string.text_run_on_headset_plug)
.put(Intent.ACTION_CONFIGURATION_CHANGED, R.string.text_run_on_config_change)
.put(Intent.ACTION_TIME_TICK, R.string.text_run_on_time_tick)
.build();
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)
.put(R.id.run_on_screen_unlock, Intent.ACTION_USER_PRESENT)
.put(R.id.run_on_battery_change, Intent.ACTION_BATTERY_CHANGED)
.put(R.id.run_on_power_connect, Intent.ACTION_POWER_CONNECTED)
.put(R.id.run_on_power_disconnect, Intent.ACTION_POWER_DISCONNECTED)
.put(R.id.run_on_conn_change, ConnectivityManager.CONNECTIVITY_ACTION)
.put(R.id.run_on_package_install, Intent.ACTION_PACKAGE_ADDED)
.put(R.id.run_on_package_uninstall, Intent.ACTION_PACKAGE_REMOVED)
.put(R.id.run_on_package_update, Intent.ACTION_PACKAGE_REPLACED)
.put(R.id.run_on_headset_plug, Intent.ACTION_HEADSET_PLUG)
.put(R.id.run_on_config_change, Intent.ACTION_CONFIGURATION_CHANGED)
.put(R.id.run_on_time_tick, Intent.ACTION_TIME_TICK)
.build();
@ViewById(R.id.toolbar)
Toolbar mToolbar;
@@ -77,9 +123,17 @@ 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 mRunOnBroadcastRadio;
@ViewById(R.id.run_on_other_broadcast)
RadioButton mRunOnOtherBroadcast;
@ViewById(R.id.action)
EditText mOtherBroadcastAction;
@ViewById(R.id.broadcast_group)
RadioGroup mBroadcastGroup;
@ViewById(R.id.disposable_task_time)
TextView mDisposableTaskTime;
@@ -98,25 +152,33 @@ public class TimedTaskSettingActivity extends BaseActivity {
private List<CheckBox> mDayOfWeekCheckBoxes = new ArrayList<>();
private ScriptFile mScriptFile;
private TimedTask mTimedTask;
private IntentTask mIntentTask;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int taskId = getIntent().getIntExtra(TaskReceiver.EXTRA_TASK_ID, -1);
long taskId = getIntent().getLongExtra(EXTRA_TASK_ID, -1);
if (taskId != -1) {
mTimedTask = TimedTaskManager.getInstance().getTimedTask(taskId);
if (mTimedTask != null) {
mScriptFile = new ScriptFile(mTimedTask.getScriptPath());
}
} else {
String path = getIntent().getStringExtra(ScriptIntents.EXTRA_KEY_PATH);
if (TextUtils.isEmpty(path)) {
finish();
long intentTaskId = getIntent().getLongExtra(EXTRA_INTENT_TASK_ID, -1);
if (intentTaskId != -1) {
mIntentTask = TimedTaskManager.getInstance().getIntentTask(intentTaskId);
if (mIntentTask != null) {
mScriptFile = new ScriptFile(mIntentTask.getScriptPath());
}
} else {
String path = getIntent().getStringExtra(ScriptIntents.EXTRA_KEY_PATH);
if (TextUtils.isEmpty(path)) {
finish();
}
mScriptFile = new ScriptFile(path);
}
mScriptFile = new ScriptFile(path);
}
}
@@ -128,7 +190,7 @@ public class TimedTaskSettingActivity extends BaseActivity {
mToolbar.setSubtitle(mScriptFile.getName());
}
findDayOfWeekCheckBoxes(mWeeklyTaskContainer);
setUpTime();
setUpTaskSettings();
}
private void findDayOfWeekCheckBoxes(ViewGroup parent) {
@@ -145,13 +207,32 @@ public class TimedTaskSettingActivity extends BaseActivity {
}
private void setUpTime() {
private void setUpTaskSettings() {
mDisposableTaskDate.setText(DATE_FORMATTER.print(LocalDate.now()));
mDisposableTaskTime.setText(TIME_FORMATTER.print(LocalTime.now()));
if (mTimedTask == null) {
mDailyTaskRadio.setChecked(true);
if (mTimedTask != null) {
setupTime();
return;
}
if (mIntentTask != null) {
setupAction();
return;
}
mDailyTaskRadio.setChecked(true);
}
private void setupAction() {
mRunOnBroadcastRadio.setChecked(true);
Integer buttonId = ACTIONS.getKey(mIntentTask.getAction());
if (buttonId == null) {
mRunOnOtherBroadcast.setChecked(true);
mOtherBroadcastAction.setText(mIntentTask.getAction());
} else {
((RadioButton) findViewById(buttonId)).setChecked(true);
}
}
private void setupTime() {
if (mTimedTask.isDisposable()) {
mDisposableTaskRadio.setChecked(true);
mDisposableTaskTime.setText(TIME_FORMATTER.print(mTimedTask.getMillis()));
@@ -171,11 +252,10 @@ public class TimedTaskSettingActivity extends BaseActivity {
mDayOfWeekCheckBoxes.get(i).setChecked(mTimedTask.hasDayOfWeek(i + 1));
}
}
}
@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()) {
@@ -269,10 +349,8 @@ public class TimedTaskSettingActivity extends BaseActivity {
startActivityForResult(new Intent().setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
.setData(Uri.parse("package:" + getPackageName())), REQUEST_CODE_IGNORE_BATTERY);
} else {
createOrUpdateTimedTask();
createOrUpdateTask();
}
return true;
}
return super.onOptionsItemSelected(item);
@@ -282,18 +360,14 @@ public class TimedTaskSettingActivity extends BaseActivity {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_IGNORE_BATTERY) {
Log.d(LOG_TAG, "result code = " + requestCode);
createOrUpdateTimedTask();
createOrUpdateTask();
}
super.onActivityResult(requestCode, resultCode, data);
}
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();
private void createOrUpdateTask() {
if (mRunOnBroadcastRadio.isChecked()) {
createOrUpdateIntentTask();
return;
}
TimedTask task = createTimedTask();
@@ -301,6 +375,9 @@ public class TimedTaskSettingActivity extends BaseActivity {
return;
if (mTimedTask == null) {
TimedTaskManager.getInstance().addTask(task);
if (mIntentTask != null) {
TimedTaskManager.getInstance().removeTask(mIntentTask);
}
Toast.makeText(this, R.string.text_already_create, Toast.LENGTH_SHORT).show();
} else {
task.setId(mTimedTask.getId());
@@ -308,4 +385,38 @@ public class TimedTaskSettingActivity extends BaseActivity {
}
finish();
}
private void createOrUpdateIntentTask() {
int buttonId = mBroadcastGroup.getCheckedRadioButtonId();
if (buttonId == -1) {
Toast.makeText(this, R.string.error_empty_selection, Toast.LENGTH_SHORT).show();
return;
}
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());
if (mIntentTask != null) {
task.setId(mIntentTask.getId());
TimedTaskManager.getInstance().updateTask(task);
Toast.makeText(this, R.string.text_already_create, Toast.LENGTH_SHORT).show();
} else {
TimedTaskManager.getInstance().addTask(task);
if (mTimedTask != null) {
TimedTaskManager.getInstance().removeTask(mTimedTask);
}
}
finish();
}
}

View File

@@ -58,7 +58,7 @@ public class BubblePopupMenu extends PopupWindow {
} else {
params.leftMargin = 0;
}
if (y + height > screenHeight) {
if (y > screenHeight / 2) {
getContentView().setRotation(180);
mRecyclerView.setRotation(180);
params.leftMargin = -params.leftMargin;