add: LICENSE, ui mode
This commit is contained in:
@@ -76,6 +76,7 @@
|
||||
<activity android:name=".AboutActivity"/>
|
||||
<activity android:name=".SettingsActivity"/>
|
||||
<activity android:name=".ErrorReportActivity"/>
|
||||
<activity android:name=".droid.script.ScriptExecuteActivity"/>
|
||||
|
||||
<service android:name=".AssistModeSwitchService"/>
|
||||
|
||||
|
||||
@@ -19,21 +19,11 @@ var launchApp = function(appName){
|
||||
droid.launchApp(appName);
|
||||
}
|
||||
|
||||
|
||||
var text = function(str){
|
||||
return droid.text(str);
|
||||
}
|
||||
|
||||
var bounds = function(left, top, right, bottom){
|
||||
return droid.bounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
|
||||
function performAction(action, args){
|
||||
if(args.length == 4){
|
||||
return action(bounds(args[0], args[1], args[2], args[3]));
|
||||
return action(droid.bounds(args[0], args[1], args[2], args[3]));
|
||||
}else{
|
||||
return action(text(args[0]));
|
||||
return action(droid.text(args[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,17 +39,9 @@ var longClick = function(a, b, c, d){
|
||||
}, arguments);
|
||||
}
|
||||
|
||||
var scrollAllUp = function(){
|
||||
droid.scrollAllUp();
|
||||
}
|
||||
|
||||
var scrollAllDown = function(){
|
||||
droid.scrollAllDown();
|
||||
}
|
||||
|
||||
var scrollUp = function(a, b, c, d){
|
||||
if(arguments.length == 0)
|
||||
return scrollAllUp();
|
||||
return droid.scrollAllUp();
|
||||
return performAction(function(target){
|
||||
return droid.scrollUp(target);
|
||||
}, arguments);
|
||||
@@ -67,7 +49,7 @@ var scrollUp = function(a, b, c, d){
|
||||
|
||||
var scrollDown = function(a, b, c, d){
|
||||
if(arguments.length == 0)
|
||||
return scrollAllDown();
|
||||
return droid.scrollAllDown();
|
||||
return performAction(function(target){
|
||||
return droid.scrollDown(target);
|
||||
}, arguments);
|
||||
@@ -95,10 +77,6 @@ var editable = function(i){
|
||||
return droid.editable(i);
|
||||
}
|
||||
|
||||
var setText = function(target, str){
|
||||
return droid.setText(target, str);
|
||||
}
|
||||
|
||||
var input = function(a, b){
|
||||
if(arguments.length == 1){
|
||||
return droid.setText(editable(-1), a);
|
||||
@@ -111,9 +89,11 @@ var sleep = function(millis){
|
||||
droid.sleep(millis);
|
||||
}
|
||||
|
||||
var isStopped = function(){
|
||||
return droid.isStopped();
|
||||
}
|
||||
|
||||
importClass("java.lang.Runnable");
|
||||
var notStopped = function(){
|
||||
return !isStopped();
|
||||
}
|
||||
|
||||
var ui = function(action){
|
||||
droid.ui(new Runnable(action));
|
||||
}
|
||||
22
app/src/main/assets/sample_force_qq_chat.js
Normal file
22
app/src/main/assets/sample_force_qq_chat.js
Normal file
@@ -0,0 +1,22 @@
|
||||
"ui";
|
||||
|
||||
importClass("android.widget.EditText");
|
||||
importClass("android.widget.Button");
|
||||
importClass("android.widget.LinearLayout");
|
||||
importClass("android.view.View.OnClickListener");
|
||||
importClass("android.content.Intent");
|
||||
importClass("android.net.Uri");
|
||||
|
||||
var qq = new EditText(activity);
|
||||
qq.setHint("请输入QQ号");
|
||||
var btnOk = new Button(activity);
|
||||
btnOk.setText("确定");
|
||||
var container = new LinearLayout(activity);
|
||||
container.addView(qq);
|
||||
container.addView(btnOk);
|
||||
activity.setContentView(container);
|
||||
|
||||
btnOk.setOnClickListener(new OnClickListener(function(view){
|
||||
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("mqqwpa://im/chat?chat_type=wpa&uin=" + qq.getText())));
|
||||
activity.finish();
|
||||
}));
|
||||
@@ -1,4 +0,0 @@
|
||||
toast("大姐姐好")
|
||||
for(var i = 0; i < 10; i++){
|
||||
toast("大姐姐今年有" + i + "块钱~");
|
||||
}
|
||||
13
app/src/main/assets/sample_qq_hongbao.js
Normal file
13
app/src/main/assets/sample_qq_hongbao.js
Normal file
@@ -0,0 +1,13 @@
|
||||
launch("com.tencent.mobileqq");
|
||||
toast("请打开一个聊天窗口");
|
||||
toast("出现红包时将会自动拆开并关闭");
|
||||
while(!isStopped()){
|
||||
if(click("点击拆开")){
|
||||
//拆开红包后尝试10次关闭红包页面
|
||||
for(var i = 0; i < 10; i++){
|
||||
sleep(300);
|
||||
if(click("关闭"))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,17 @@
|
||||
"ui";
|
||||
|
||||
importClass("com.afollestad.materialdialogs.MaterialDialog.Builder");
|
||||
importClass("com.afollestad.materialdialogs.MaterialDialog.InputCallback");
|
||||
importClass("android.content.DialogInterface.OnDismissListener");
|
||||
|
||||
new Builder(context)
|
||||
.title("请输入算式")
|
||||
.content("测试")
|
||||
new Builder(activity)
|
||||
.title("简单计算器")
|
||||
.input("请输入算式", "1+1", new InputCallback(function(dialog, input){
|
||||
eval("var ans = (" + input + ")");
|
||||
toast(ans);
|
||||
}))
|
||||
.positiveText("计算")
|
||||
.dismissListener(new OnDismissListener(function(dialog){
|
||||
activity.finish();
|
||||
}))
|
||||
.show();
|
||||
@@ -28,7 +28,12 @@ public class NotRemindAgainDialog extends MaterialDialog {
|
||||
private boolean mRemind;
|
||||
|
||||
public Builder(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public Builder(Context context, String key) {
|
||||
super(context);
|
||||
mKeyRemind = key;
|
||||
readRemindStatus();
|
||||
checkBoxPrompt(context.getString(R.string.text_do_not_remind_again), false, new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
@@ -52,12 +57,13 @@ public class NotRemindAgainDialog extends MaterialDialog {
|
||||
}
|
||||
|
||||
private void readRemindStatus() {
|
||||
generatePreferenceKey();
|
||||
generatePreferenceKeyIfNeeded();
|
||||
mRemind = PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean(mKeyRemind, true);
|
||||
}
|
||||
|
||||
private void generatePreferenceKey() {
|
||||
mKeyRemind = md5(TextUtils.join("", Thread.currentThread().getStackTrace()));
|
||||
private void generatePreferenceKeyIfNeeded() {
|
||||
if (mKeyRemind == null)
|
||||
mKeyRemind = md5(TextUtils.join("", Thread.currentThread().getStackTrace()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.stardust.scriptdroid;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.stardust.util.CrashHandler;
|
||||
@@ -14,6 +16,7 @@ public class App extends Application {
|
||||
|
||||
private static App instance;
|
||||
private static StateObserver stateObserver;
|
||||
private static Activity currentActivity;
|
||||
|
||||
public static App getApp() {
|
||||
return instance;
|
||||
@@ -26,8 +29,69 @@ public class App extends Application {
|
||||
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Thread.currentThread().setUncaughtExceptionHandler(new CrashHandler(ErrorReportActivity.class));
|
||||
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(ErrorReportActivity.class));
|
||||
instance = this;
|
||||
stateObserver = new StateObserver(PreferenceManager.getDefaultSharedPreferences(this));
|
||||
registerActivityLifecycleCallbacks(new SimpleActivityLifecycleCallbacks() {
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
currentActivity = activity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
currentActivity = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
currentActivity = activity;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public static Activity currentActivity() {
|
||||
return currentActivity;
|
||||
}
|
||||
|
||||
|
||||
private static class SimpleActivityLifecycleCallbacks implements ActivityLifecycleCallbacks {
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
|
||||
import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
|
||||
|
||||
@@ -15,10 +15,18 @@ import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIS
|
||||
*/
|
||||
public class AssistModeSwitchService extends Service {
|
||||
|
||||
|
||||
private static final String EXTRA_INTENT_VALID = "intentValid";
|
||||
private static final String EXTRA_ACTION = "action";
|
||||
|
||||
private static final int ACTION_TOGGLE_ASSIST_MODE = 1;
|
||||
private static final int ACTION_CANCEL_ASSIST_MODE_NOTIFICATION = 2;
|
||||
|
||||
|
||||
public static PendingIntent getStartIntent() {
|
||||
Intent intent = new Intent(App.getApp(), AssistModeSwitchService.class)
|
||||
.putExtra("intentValid", true)
|
||||
.putExtra("switch", "assistMode");
|
||||
.putExtra(EXTRA_INTENT_VALID, true)
|
||||
.putExtra(EXTRA_ACTION, ACTION_TOGGLE_ASSIST_MODE);
|
||||
return PendingIntent.getService(App.getApp(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
@@ -26,19 +34,23 @@ public class AssistModeSwitchService extends Service {
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
boolean intentValid = intent.getBooleanExtra("intentValid", false);
|
||||
if (intentValid) {
|
||||
String action = intent.getStringExtra("switch");
|
||||
if (action != null) {
|
||||
if (action.equals("assistMode")) {
|
||||
Assistant.setAssistModeEnable(!Assistant.isAssistModeEnable());
|
||||
} else {
|
||||
App.getStateObserver().setState(KEY_ASSIST_MODE_NOTIFICATION, false);
|
||||
}
|
||||
}
|
||||
performAction(intent.getIntExtra(EXTRA_ACTION, 0));
|
||||
}
|
||||
stopSelf();
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
private void performAction(int action) {
|
||||
switch (action) {
|
||||
case ACTION_TOGGLE_ASSIST_MODE:
|
||||
BoundsAssistant.setAssistModeEnable(!BoundsAssistant.isAssistModeEnable());
|
||||
break;
|
||||
case ACTION_CANCEL_ASSIST_MODE_NOTIFICATION:
|
||||
App.getStateObserver().setState(KEY_ASSIST_MODE_NOTIFICATION, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
@@ -47,8 +59,8 @@ public class AssistModeSwitchService extends Service {
|
||||
|
||||
public static PendingIntent getDeletePendingIntent() {
|
||||
Intent deleteIntent = new Intent(App.getApp(), AssistModeSwitchService.class)
|
||||
.putExtra("intentValid", true)
|
||||
.putExtra("switch", "assistModeNotification");
|
||||
.putExtra(EXTRA_INTENT_VALID, true)
|
||||
.putExtra(EXTRA_ACTION, ACTION_CANCEL_ASSIST_MODE_NOTIFICATION);
|
||||
return PendingIntent.getService(App.getApp(), 0, deleteIntent, PendingIntent.FLAG_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.jecelyin.editor.v2.ui.EditorDelegate;
|
||||
import com.jecelyin.editor.v2.view.EditorView;
|
||||
import com.jecelyin.editor.v2.view.menu.MenuDef;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.editor920.Editor920Activity;
|
||||
import com.stardust.scriptdroid.ui.AssistClipListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.EditSideMenuFragment;
|
||||
@@ -58,7 +57,6 @@ public class EditActivity extends Editor920Activity {
|
||||
|
||||
public void onCreate(Bundle b) {
|
||||
super.onCreate(b);
|
||||
DroidRuntime.setContext(this);
|
||||
handleIntent();
|
||||
setUpUI();
|
||||
setUpEditor();
|
||||
|
||||
@@ -6,6 +6,8 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
@@ -20,22 +22,29 @@ import java.util.TimerTask;
|
||||
|
||||
public class ErrorReportActivity extends BaseActivity {
|
||||
|
||||
private static final String TAG = "ErrorReportActivity";
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
try {
|
||||
super.onCreate(savedInstanceState);
|
||||
setUpUI();
|
||||
handleIntent();
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
Log.e(TAG, "", throwable);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIntent() {
|
||||
String message = getIntent().getStringExtra("message");
|
||||
final String errorDetail = getIntent().getStringExtra("error");
|
||||
//showErrorMessage(message, errorDetail);
|
||||
showErrorMessageByDialog(message, errorDetail);
|
||||
}
|
||||
|
||||
private void showErrorMessageByDialog(String message, final String errorDetail) {
|
||||
new MaterialDialog.Builder(this)
|
||||
.content(message)
|
||||
.title(R.string.text_crash)
|
||||
.content(R.string.crash_feedback)
|
||||
.positiveText(R.string.text_exit)
|
||||
.negativeText(R.string.text_copy_debug_info)
|
||||
.onPositive(new MaterialDialog.SingleButtonCallback() {
|
||||
@@ -55,6 +64,10 @@ public class ErrorReportActivity extends BaseActivity {
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showErrorMessage(String message, String errorDetail) {
|
||||
((TextView) findViewById(R.id.error)).setText(message + "\n" + errorDetail);
|
||||
}
|
||||
|
||||
private String getDeviceMessage() {
|
||||
return "Android: " + Build.VERSION.SDK_INT + "\n";
|
||||
}
|
||||
@@ -86,13 +99,13 @@ public class ErrorReportActivity extends BaseActivity {
|
||||
getSupportActionBar().setHomeButtonEnabled(false);
|
||||
}
|
||||
|
||||
private void exit() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
finishAffinity();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
exit();
|
||||
}
|
||||
|
||||
private void exit() {
|
||||
finishAffinity();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
|
||||
private void goToAccessibilityPermissionSettingIfDisabled() {
|
||||
if (!AccessibilityServiceUtils.isAccessibilityServiceEnabled(this, ActionPerformService.class)) {
|
||||
new NotRemindAgainDialog.Builder(this)
|
||||
new NotRemindAgainDialog.Builder(this, "goToAccessibilityPermissionSettingIfDisabled")
|
||||
.title(R.string.text_alert)
|
||||
.content(R.string.explain_accessibility_permission)
|
||||
.positiveText(R.string.text_go_to_setting)
|
||||
@@ -62,7 +62,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
.onPositive(new MaterialDialog.SingleButtonCallback() {
|
||||
@Override
|
||||
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
|
||||
AccessibilityServiceUtils.goToPermissionSetting(MainActivity.this);
|
||||
AccessibilityServiceUtils.goToAccessibilitySetting(MainActivity.this);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ public class NonUiInitializer {
|
||||
private static final Map<String, Integer> SAMPLES = new MapEntries<String, Integer>()
|
||||
.entry("sample_open_wechat_moment.js", R.string.text_sample_open_what_moment)
|
||||
.entry("sample_open_running_services.js", R.string.text_sample_open_running_services)
|
||||
.entry("sample_hello_big_sister.js", R.string.text_sample_hello_big_sister)
|
||||
.entry("sample_qq_hongbao.js", R.string.text_sample_qq_hongbao)
|
||||
.entry("sample_simple_calculator.js", R.string.text_sample_simple_calculator)
|
||||
.entry("sample_force_qq_chat.js", R.string.text_sample_for_qq_chat)
|
||||
.map();
|
||||
|
||||
private static NonUiInitializer instance = new NonUiInitializer();
|
||||
@@ -41,21 +43,25 @@ public class NonUiInitializer {
|
||||
}
|
||||
}
|
||||
|
||||
private void copySampleScriptFile() {
|
||||
public int copySampleScriptFile() {
|
||||
ScriptFileList list = SharedPrefScriptFileList.getInstance();
|
||||
int succeedCount = 0;
|
||||
int failCount = 0;
|
||||
for (Map.Entry<String, Integer> entry : SAMPLES.entrySet()) {
|
||||
String assetFile = entry.getKey();
|
||||
String name = getContext().getString(entry.getValue());
|
||||
String path = ScriptFile.DEFAULT_FOLDER + name + ".js";
|
||||
if (FileUtils.copyAsset(assetFile, path)) {
|
||||
list.add(new ScriptFile(name, path));
|
||||
succeedCount++;
|
||||
if (!list.containsPath(path)) {
|
||||
if (FileUtils.copyAsset(assetFile, path)) {
|
||||
list.add(new ScriptFile(name, path));
|
||||
} else {
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (succeedCount > 0) {
|
||||
if (failCount > 0) {
|
||||
Pref.def().edit().putBoolean(Pref.SAMPLE_SCRIPTS_COPIED, true).apply();
|
||||
}
|
||||
return failCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.stardust.scriptdroid;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
@@ -8,10 +9,28 @@ import android.preference.PreferenceManager;
|
||||
*/
|
||||
public class Pref {
|
||||
|
||||
private static final SharedPreferences DISPOSABLE_BOOLEAN = App.getApp().getSharedPreferences("DISPOSABLE_BOOLEAN", Context.MODE_PRIVATE);
|
||||
|
||||
public static final String SAMPLE_SCRIPTS_COPIED = "SAMPLE_SCRIPTS_COPIED";
|
||||
|
||||
|
||||
public static SharedPreferences def() {
|
||||
return PreferenceManager.getDefaultSharedPreferences(App.getApp());
|
||||
}
|
||||
|
||||
public static boolean isFirstEnableAssistMode() {
|
||||
return getDisposableBoolean("isFirstEnableAssistMode", true);
|
||||
}
|
||||
|
||||
private static boolean getDisposableBoolean(String key, boolean defaultValue) {
|
||||
boolean b = DISPOSABLE_BOOLEAN.getBoolean(key, defaultValue);
|
||||
if (b == defaultValue) {
|
||||
DISPOSABLE_BOOLEAN.edit().putBoolean(key, !defaultValue).apply();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static boolean isFirstGoToAccessibilitySetting() {
|
||||
return getDisposableBoolean("isFirstGoToAccessibilitySetting", true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.preference.PreferenceScreen;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.util.MapEntries;
|
||||
|
||||
@@ -61,6 +62,16 @@ public class SettingsActivity extends BaseActivity {
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
ACTION_MAP = new MapEntries<String, Runnable>()
|
||||
.entry(getString(R.string.text_re_import_samples), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int failCount = NonUiInitializer.getInstance().copySampleScriptFile();
|
||||
if (failCount <= 0) {
|
||||
Toast.makeText(getActivity(), R.string.text_re_import_succeed, Toast.LENGTH_SHORT).show();
|
||||
} else
|
||||
Toast.makeText(getActivity(), R.string.text_fail, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
})
|
||||
.entry(getString(R.string.text_about), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package com.stardust.scriptdroid.droid;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.droid.script.DuktapeJavaScriptEngine;
|
||||
import com.stardust.scriptdroid.droid.script.JavaScriptEngine;
|
||||
import com.stardust.scriptdroid.droid.script.ScriptExecuteActivity;
|
||||
import com.stardust.scriptdroid.file.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
@@ -16,12 +21,14 @@ import java.io.FileNotFoundException;
|
||||
|
||||
public class Droid {
|
||||
|
||||
public static final String UI = "\"ui\";";
|
||||
|
||||
public interface OnRunFinishedListener {
|
||||
void onRunFinished(Object result, Exception e);
|
||||
}
|
||||
|
||||
private static final DroidRuntime RUNTIME = DroidRuntime.getRuntime();
|
||||
private static final JavaScriptEngine JAVA_SCRIPT_ENGINE = new DuktapeJavaScriptEngine(RUNTIME);
|
||||
public static final JavaScriptEngine JAVA_SCRIPT_ENGINE = new DuktapeJavaScriptEngine(RUNTIME);
|
||||
private static final OnRunFinishedListener DEFAULT_LISTENER = new OnRunFinishedListener() {
|
||||
@Override
|
||||
public void onRunFinished(Object result, Exception e) {
|
||||
@@ -33,7 +40,6 @@ public class Droid {
|
||||
private static Droid instance = new Droid();
|
||||
|
||||
protected Droid() {
|
||||
|
||||
}
|
||||
|
||||
public static Droid getInstance() {
|
||||
@@ -59,8 +65,13 @@ public class Droid {
|
||||
}
|
||||
|
||||
public void runScript(final String script, OnRunFinishedListener listener, RunningConfig config) {
|
||||
listener = listener == null ? DEFAULT_LISTENER : listener;
|
||||
if (config.runInNewThread) {
|
||||
new Thread(new RunScriptRunnable(script, listener, config)).start();
|
||||
if (script.startsWith(UI)) {
|
||||
ScriptExecuteActivity.runScript(script, listener, config);
|
||||
} else {
|
||||
new Thread(new RunScriptRunnable(script, listener, config)).start();
|
||||
}
|
||||
} else {
|
||||
new RunScriptRunnable(script, listener, config).run();
|
||||
}
|
||||
@@ -72,11 +83,6 @@ public class Droid {
|
||||
return JAVA_SCRIPT_ENGINE.stopAll();
|
||||
}
|
||||
|
||||
|
||||
public void ensureNotStopped() {
|
||||
JAVA_SCRIPT_ENGINE.ensureNotStopped();
|
||||
}
|
||||
|
||||
private void checkFile(File file) {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("file = null");
|
||||
@@ -95,8 +101,8 @@ public class Droid {
|
||||
private final String mScript;
|
||||
private OnRunFinishedListener mOnRunFinishedListener;
|
||||
|
||||
public RunScriptRunnable(String script, OnRunFinishedListener listener, RunningConfig config) {
|
||||
mOnRunFinishedListener = listener == null ? DEFAULT_LISTENER : listener;
|
||||
RunScriptRunnable(String script, OnRunFinishedListener listener, RunningConfig config) {
|
||||
mOnRunFinishedListener = listener;
|
||||
mScript = script;
|
||||
}
|
||||
|
||||
@@ -108,5 +114,10 @@ public class Droid {
|
||||
mOnRunFinishedListener.onRunFinished(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
public RunScriptRunnable setActivity(Activity a) {
|
||||
JAVA_SCRIPT_ENGINE.set("activity", Activity.class, a);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package com.stardust.scriptdroid.droid.assist;
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public interface AssistClipList {
|
||||
public interface BoundsAssistClipList {
|
||||
|
||||
interface OnClipChangedListener {
|
||||
void onClipRemove(int position);
|
||||
@@ -6,29 +6,43 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public class Assistant {
|
||||
public class BoundsAssistant {
|
||||
public static final String KEY_ASSIST_MODE_ENABLE = "ASSIST_MODE_ENABLE";
|
||||
|
||||
|
||||
private static boolean assistModeEnable;
|
||||
private static AssistClipList assistClipList = SharedPrefAssistClipList.getInstance();
|
||||
private static BoundsAssistClipList boundsAssistClipList = SharedPrefBoundsAssistClipList.getInstance();
|
||||
|
||||
public static boolean isAssistModeEnable() {
|
||||
return assistModeEnable;
|
||||
}
|
||||
|
||||
public static void setAssistModeEnable(boolean assistModeEnable) {
|
||||
Assistant.assistModeEnable = assistModeEnable;
|
||||
if (assistModeEnable && Pref.isFirstEnableAssistMode()) {
|
||||
showAssistModeInfoDialog();
|
||||
}
|
||||
BoundsAssistant.assistModeEnable = assistModeEnable;
|
||||
App.getStateObserver().setState(KEY_ASSIST_MODE_ENABLE, assistModeEnable);
|
||||
}
|
||||
|
||||
private static void showAssistModeInfoDialog() {
|
||||
new MaterialDialog.Builder(App.currentActivity())
|
||||
.title(R.string.text_alert)
|
||||
.content(R.string.assist_mode_notice)
|
||||
.positiveText(R.string.ok)
|
||||
.show();
|
||||
}
|
||||
|
||||
public static void performAssistance(AccessibilityEvent event) {
|
||||
if (!assistModeEnable) {
|
||||
return;
|
||||
@@ -53,7 +67,7 @@ public class Assistant {
|
||||
|
||||
private static void saveAndAlertBounds(Rect rect) {
|
||||
String str = rect.toString().replace('-', ',').replace(" ", "").substring(4);
|
||||
assistClipList.add(str);
|
||||
boundsAssistClipList.add(str);
|
||||
Toast.makeText(App.getApp(), str, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@@ -15,24 +15,24 @@ import java.util.List;
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public class SharedPrefAssistClipList implements AssistClipList {
|
||||
public class SharedPrefBoundsAssistClipList implements BoundsAssistClipList {
|
||||
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
|
||||
private static SharedPrefAssistClipList instance = new SharedPrefAssistClipList(App.getApp());
|
||||
private static SharedPrefBoundsAssistClipList instance = new SharedPrefBoundsAssistClipList(App.getApp());
|
||||
private OnClipChangedListener mOnClipChangedListener;
|
||||
|
||||
public static SharedPrefAssistClipList getInstance() {
|
||||
public static SharedPrefBoundsAssistClipList getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static final int MAX_SIZE = 10;
|
||||
private static final String SHARED_PREF_NAME = "SharedPrefAssistClipList";
|
||||
private static final String SHARED_PREF_NAME = "SharedPrefBoundsAssistClipList";
|
||||
private SharedPreferences mSharedPreferences;
|
||||
private List<String> mAssistClipList = new LinkedList<>();
|
||||
|
||||
public SharedPrefAssistClipList(Context context) {
|
||||
public SharedPrefBoundsAssistClipList(Context context) {
|
||||
mSharedPreferences = context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
|
||||
readFromSharedPref();
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.stardust.scriptdroid.droid.runtime;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -12,7 +11,6 @@ import android.widget.Toast;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.Action;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionFactory;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
@@ -21,6 +19,8 @@ import com.stardust.scriptdroid.droid.runtime.api.IDroidRuntime;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
@@ -29,21 +29,15 @@ public class DroidRuntime implements IDroidRuntime {
|
||||
|
||||
private static final String TAG = "DroidRuntime";
|
||||
private static DroidRuntime runtime = new DroidRuntime();
|
||||
private static Context context;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private boolean mActionPerformResult;
|
||||
private boolean mActionPerformResultUpToDate;
|
||||
private Handler mUIHandler;
|
||||
|
||||
public static DroidRuntime getRuntime() {
|
||||
return runtime;
|
||||
}
|
||||
|
||||
public static void setContext(Context context) {
|
||||
DroidRuntime.context = context;
|
||||
}
|
||||
|
||||
protected DroidRuntime() {
|
||||
mUIHandler = new Handler(App.getApp().getMainLooper());
|
||||
}
|
||||
@@ -143,25 +137,20 @@ public class DroidRuntime implements IDroidRuntime {
|
||||
private boolean performAction(Action action) {
|
||||
if (ActionPerformService.getInstance() == null) {
|
||||
toast(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
throw new PermissionDeniedException(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
}
|
||||
ensureNotStopped();
|
||||
ActionPerformService.setAction(action);
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
mLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new PermissionDeniedException("已停止运行");
|
||||
ActionPerformService.setActions(ActionPerformService.NO_ACTION);
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_script_stopped), e);
|
||||
}
|
||||
}
|
||||
return mActionPerformResult;
|
||||
}
|
||||
|
||||
private void ensureNotStopped() {
|
||||
Droid.getInstance().ensureNotStopped();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void toast(final String text) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@@ -172,18 +161,48 @@ public class DroidRuntime implements IDroidRuntime {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
throw new ScriptStopException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStopped() {
|
||||
return Thread.currentThread().isInterrupted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
Thread.interrupted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialDialog.Builder dialog() {
|
||||
return new Builder();
|
||||
if (App.currentActivity() == null) {
|
||||
Toast.makeText(App.getApp(), R.string.text_cannot_create_dialog_when_app_invisible, Toast.LENGTH_SHORT).show();
|
||||
throw new ScriptStopException(App.getApp().getString(R.string.text_cannot_create_dialog_when_app_invisible));
|
||||
}
|
||||
return new MaterialDialog.Builder(App.currentActivity()) {
|
||||
|
||||
public MaterialDialog show() {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
superShow();
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
private void superShow() {
|
||||
super.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void notifyActionPerformed(boolean succeed) {
|
||||
@@ -193,16 +212,4 @@ public class DroidRuntime implements IDroidRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
public class Builder extends MaterialDialog.Builder {
|
||||
|
||||
public Builder() {
|
||||
super(DroidRuntime.context);
|
||||
}
|
||||
|
||||
public MaterialDialog show(final MaterialDialog.Builder dialog) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.stardust.scriptdroid.droid.runtime;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/29.
|
||||
*/
|
||||
public class PermissionDeniedException extends RuntimeException {
|
||||
public PermissionDeniedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.stardust.scriptdroid.droid.runtime;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/29.
|
||||
*/
|
||||
public class ScriptStopException extends RuntimeException {
|
||||
|
||||
|
||||
public ScriptStopException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ScriptStopException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ScriptStopException() {
|
||||
|
||||
}
|
||||
|
||||
public ScriptStopException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ActionPerformService extends AccessibilityService {
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
Log.v(TAG, "onAccessibilityEvent: state=" + state + " event=" + event);
|
||||
Assistant.performAssistance(event);
|
||||
BoundsAssistant.performAssistance(event);
|
||||
if (state == STATE_INACTIVE)
|
||||
return;
|
||||
AccessibilityNodeInfo root = getRootInActiveWindow();
|
||||
@@ -103,8 +103,12 @@ public class ActionPerformService extends AccessibilityService {
|
||||
}
|
||||
|
||||
public static void disable() {
|
||||
if (instance != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
instance.disableSelf();
|
||||
if (instance != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
instance.disableSelf();
|
||||
} else {
|
||||
AccessibilityServiceUtils.goToAccessibilitySetting(App.getApp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,5 +42,9 @@ public interface IDroidRuntime {
|
||||
|
||||
void sleep(long millis);
|
||||
|
||||
boolean isStopped();
|
||||
|
||||
void stop();
|
||||
|
||||
MaterialDialog.Builder dialog();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.stardust.scriptdroid.droid.script;
|
||||
import com.efurture.script.JSTransformer;
|
||||
import com.furture.react.DuktapeEngine;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.runtime.api.IDroidRuntime;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -34,7 +34,6 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
|
||||
public DuktapeJavaScriptEngine(IDroidRuntime runtime) {
|
||||
setRuntime(runtime);
|
||||
|
||||
}
|
||||
|
||||
private void setRuntime(IDroidRuntime runtime) {
|
||||
@@ -50,13 +49,15 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
try {
|
||||
result = duktapeEngine.execute(JSTransformer.parse(new StringReader(script)));
|
||||
} catch (IOException e) {
|
||||
remove(Thread.currentThread());
|
||||
removeAndStop(Thread.currentThread());
|
||||
throw e;
|
||||
}
|
||||
remove(Thread.currentThread());
|
||||
if (!script.startsWith(Droid.UI))
|
||||
removeAndDestroy(Thread.currentThread());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private void init(DuktapeEngine duktapeEngine) {
|
||||
duktapeEngine.put("context", App.getApp());
|
||||
duktapeEngine.execute(INIT_SCRIPT);
|
||||
@@ -66,13 +67,23 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
|
||||
}
|
||||
|
||||
private void remove(Thread thread) {
|
||||
public void removeAndStop(Thread thread) {
|
||||
synchronized (mThreadDuktapeEngineMap) {
|
||||
DuktapeEngine engine = mThreadDuktapeEngineMap.remove(thread);
|
||||
stop(engine, thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removeAndDestroy(Thread thread) {
|
||||
synchronized (mThreadDuktapeEngineMap) {
|
||||
DuktapeEngine engine = mThreadDuktapeEngineMap.remove(thread);
|
||||
if (engine != null)
|
||||
engine.destory();
|
||||
}
|
||||
}
|
||||
|
||||
private void stop(DuktapeEngine engine, Thread thread) {
|
||||
if (engine != null)
|
||||
engine.destory();
|
||||
@@ -107,10 +118,4 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensureNotStopped() {
|
||||
if (!mThreadDuktapeEngineMap.containsKey(Thread.currentThread())) {
|
||||
throw new RuntimeException(App.getApp().getString(R.string.text_script_stopped));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface JavaScriptEngine {
|
||||
|
||||
int stopAll();
|
||||
|
||||
void ensureNotStopped();
|
||||
void removeAndDestroy(Thread thread);
|
||||
|
||||
class Init {
|
||||
public static final String INIT_SCRIPT = readInitScript();
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.stardust.scriptdroid.droid.script;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.RunningConfig;
|
||||
|
||||
import static com.stardust.scriptdroid.droid.Droid.JAVA_SCRIPT_ENGINE;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/5.
|
||||
*/
|
||||
|
||||
public class ScriptExecuteActivity extends Activity {
|
||||
|
||||
private static String script;
|
||||
private static Droid.OnRunFinishedListener onRunFinishedListener;
|
||||
private static RunningConfig runningConfig;
|
||||
private Object mResult;
|
||||
|
||||
|
||||
public static void runScript(String script, Droid.OnRunFinishedListener listener, RunningConfig config) {
|
||||
ScriptExecuteActivity.script = script;
|
||||
ScriptExecuteActivity.onRunFinishedListener = listener;
|
||||
ScriptExecuteActivity.runningConfig = config;
|
||||
App.getApp().startActivity(new Intent(App.getApp(), ScriptExecuteActivity.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
runScript();
|
||||
}
|
||||
|
||||
private void runScript() {
|
||||
JAVA_SCRIPT_ENGINE.set("activity", Activity.class, this);
|
||||
try {
|
||||
mResult = JAVA_SCRIPT_ENGINE.execute(script);
|
||||
} catch (Exception e) {
|
||||
onRunFinishedListener.onRunFinished(null, e);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
onRunFinishedListener.onRunFinished(mResult, null);
|
||||
super.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
JAVA_SCRIPT_ENGINE.removeAndDestroy(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
@@ -25,4 +25,5 @@ public abstract class ScriptFileList {
|
||||
}
|
||||
|
||||
|
||||
public abstract boolean containsPath(String path);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,11 @@ public class SharedPrefScriptFileList extends ScriptFileList {
|
||||
return mScriptPath.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsPath(String path) {
|
||||
return mScriptPath.contains(path);
|
||||
}
|
||||
|
||||
protected void syncWithSharedPref() {
|
||||
SharedPreferences.Editor editor = mSharedPreferences.edit();
|
||||
editor.putString(SP_KEY_SCRIPT_NAME, GSON.toJson(mScriptName));
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.service.quicksettings.Tile;
|
||||
import android.service.quicksettings.TileService;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
@@ -15,12 +15,12 @@ import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
public class BoundsAssistEnableTileService extends TileService {
|
||||
|
||||
public void onClick() {
|
||||
Assistant.setAssistModeEnable(!Assistant.isAssistModeEnable());
|
||||
BoundsAssistant.setAssistModeEnable(!BoundsAssistant.isAssistModeEnable());
|
||||
updateTile();
|
||||
}
|
||||
|
||||
private void updateTile() {
|
||||
getQsTile().setState(Assistant.isAssistModeEnable() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
|
||||
getQsTile().setState(BoundsAssistant.isAssistModeEnable() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
|
||||
getQsTile().updateTile();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.assist.AssistClipList;
|
||||
import com.stardust.scriptdroid.droid.assist.SharedPrefAssistClipList;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistClipList;
|
||||
import com.stardust.scriptdroid.droid.assist.SharedPrefBoundsAssistClipList;
|
||||
import com.stardust.scriptdroid.widget.ExpandableRecyclerView;
|
||||
|
||||
/**
|
||||
@@ -25,7 +25,7 @@ public class AssistClipListRecyclerView extends ExpandableRecyclerView {
|
||||
void onClick(String clip, int position);
|
||||
}
|
||||
|
||||
private AssistClipList mAssistClipList = SharedPrefAssistClipList.getInstance();
|
||||
private BoundsAssistClipList mBoundsAssistClipList = SharedPrefBoundsAssistClipList.getInstance();
|
||||
private OnClipClickListener mOnClipClickListener;
|
||||
|
||||
public AssistClipListRecyclerView(Context context) {
|
||||
@@ -55,7 +55,7 @@ public class AssistClipListRecyclerView extends ExpandableRecyclerView {
|
||||
}
|
||||
}
|
||||
});
|
||||
mAssistClipList.setOnClipChangedListener(new AssistClipList.OnClipChangedListener() {
|
||||
mBoundsAssistClipList.setOnClipChangedListener(new BoundsAssistClipList.OnClipChangedListener() {
|
||||
@Override
|
||||
public void onClipRemove(int position) {
|
||||
getAdapter().notifyItemRemoved(position);
|
||||
@@ -82,7 +82,7 @@ public class AssistClipListRecyclerView extends ExpandableRecyclerView {
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
//防止因mAssistClipList持有OnClipChangedListener引用从而导致这个RecyclerView及其Context被引用,内存泄漏
|
||||
mAssistClipList.setOnClipChangedListener(null);
|
||||
mBoundsAssistClipList.setOnClipChangedListener(null);
|
||||
}
|
||||
|
||||
private class Adapter extends ExpandableRecyclerView.DefaultTitleAdapter {
|
||||
@@ -100,12 +100,12 @@ public class AssistClipListRecyclerView extends ExpandableRecyclerView {
|
||||
@Override
|
||||
protected void onBindChildViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
ChildViewHolder viewHolder = (ChildViewHolder) holder;
|
||||
viewHolder.mTextView.setText(mAssistClipList.get(position));
|
||||
viewHolder.mTextView.setText(mBoundsAssistClipList.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildItemCount() {
|
||||
return mAssistClipList.size();
|
||||
return mBoundsAssistClipList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,7 @@ import android.support.v4.app.NotificationCompat;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.AssistModeSwitchService;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.util.StateObserver;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public class AssistModeSwitchNotification {
|
||||
}
|
||||
}
|
||||
});
|
||||
App.getStateObserver().register(Assistant.KEY_ASSIST_MODE_ENABLE, new StateObserver.OnBooleanStateChangedListener() {
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_ASSIST_MODE_ENABLE, new StateObserver.OnBooleanStateChangedListener() {
|
||||
@Override
|
||||
public void onStateChanged(Boolean newState) {
|
||||
if (enable) {
|
||||
@@ -78,7 +78,7 @@ public class AssistModeSwitchNotification {
|
||||
.setAutoCancel(false)
|
||||
.setSmallIcon(R.drawable.ic_robot_head)
|
||||
.setDeleteIntent(AssistModeSwitchService.getDeletePendingIntent())
|
||||
.setContentText(Assistant.isAssistModeEnable() ?
|
||||
.setContentText(BoundsAssistant.isAssistModeEnable() ?
|
||||
App.getApp().getString(R.string.text_assist_mode_enabled) :
|
||||
App.getApp().getString(R.string.text_assist_mode_disabled))
|
||||
.setContentIntent(AssistModeSwitchService.getStartIntent())
|
||||
|
||||
@@ -12,7 +12,7 @@ import android.view.ViewGroup;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.DocumentActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
|
||||
@@ -70,14 +70,14 @@ public class EditSideMenuFragment extends com.stardust.app.Fragment {
|
||||
}
|
||||
|
||||
private void syncSwitchState() {
|
||||
mAssistServiceSwitch.setChecked(Assistant.isAssistModeEnable());
|
||||
mAssistServiceSwitch.setChecked(BoundsAssistant.isAssistModeEnable());
|
||||
mAssistServiceNotificationSwitch.setChecked(AssistModeSwitchNotification.isEnable());
|
||||
}
|
||||
|
||||
private void setUpSwitchCompat() {
|
||||
mAssistServiceSwitch = $(R.id.sw_assist_service);
|
||||
mAssistServiceNotificationSwitch = $(R.id.sw_assist_service_notification);
|
||||
App.getStateObserver().register(Assistant.KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, mAssistServiceNotificationSwitch);
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public class EditSideMenuFragment extends com.stardust.app.Fragment {
|
||||
|
||||
@ViewBinding.Check(R.id.sw_assist_service)
|
||||
private void setAssistServiceEnable(boolean enable) {
|
||||
Assistant.setAssistModeEnable(enable);
|
||||
BoundsAssistant.setAssistModeEnable(enable);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.assist_service)
|
||||
|
||||
@@ -15,7 +15,10 @@ import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.file.FileUtils;
|
||||
import com.stardust.scriptdroid.widget.ExpandableRecyclerView;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -91,7 +94,7 @@ public class FunctionListRecyclerView extends ExpandableRecyclerView {
|
||||
|
||||
Adapter() {
|
||||
setIcon(R.drawable.ic_function_mathematical_green);
|
||||
setTitle(R.string.text_function);
|
||||
setTitle(R.string.text_common_function);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -136,6 +139,12 @@ public class FunctionListRecyclerView extends ExpandableRecyclerView {
|
||||
String[] str = f.split(" ");
|
||||
FUNCTION_LIST.add(new Function(str[0], str[1]));
|
||||
}
|
||||
|
||||
final Comparator cmp = Collator.getInstance();
|
||||
Collections.sort(FUNCTION_LIST, new Comparator<Function>() {
|
||||
@Override
|
||||
public int compare(Function f1, Function f2) {
|
||||
return cmp.compare(f1.description, f2.description);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.DocumentActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.scriptdroid.droid.assist.BoundsAssistant;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
@@ -60,7 +60,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
mAutoOperateServiceSwitch.setChecked(ActionPerformService.isEnable());
|
||||
}
|
||||
}, 450);
|
||||
mAssistServiceSwitch.setChecked(Assistant.isAssistModeEnable());
|
||||
mAssistServiceSwitch.setChecked(BoundsAssistant.isAssistModeEnable());
|
||||
mAssistServiceNotificationSwitch.setChecked(AssistModeSwitchNotification.isEnable());
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
mAutoOperateServiceSwitch = $(R.id.sw_auto_operate_service);
|
||||
mAssistServiceSwitch = $(R.id.sw_assist_service);
|
||||
mAssistServiceNotificationSwitch = $(R.id.sw_assist_service_notification);
|
||||
App.getStateObserver().register(Assistant.KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(BoundsAssistant.KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, mAssistServiceNotificationSwitch);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
@ViewBinding.Check(R.id.sw_auto_operate_service)
|
||||
private void setAutoOperateServiceEnable(boolean enable) {
|
||||
if (enable && !ActionPerformService.isEnable()) {
|
||||
AccessibilityServiceUtils.goToPermissionSetting(getContext());
|
||||
AccessibilityServiceUtils.goToAccessibilitySetting(getContext());
|
||||
} else if (!enable && ActionPerformService.isEnable()) {
|
||||
ActionPerformService.disable();
|
||||
}
|
||||
@@ -93,7 +93,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
|
||||
@ViewBinding.Check(R.id.sw_assist_service)
|
||||
private void setAssistServiceEnable(boolean enable) {
|
||||
Assistant.setAssistModeEnable(enable);
|
||||
BoundsAssistant.setAssistModeEnable(enable);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.assist_service)
|
||||
|
||||
@@ -80,11 +80,15 @@ public class ExpandableRecyclerView extends RecyclerView {
|
||||
}
|
||||
|
||||
public void expand() {
|
||||
if (mExpanded)
|
||||
return;
|
||||
mExpanded = true;
|
||||
((Adapter) getAdapter()).notifyExpanded();
|
||||
}
|
||||
|
||||
public void collapse() {
|
||||
if (!mExpanded)
|
||||
return;
|
||||
mExpanded = false;
|
||||
((Adapter) getAdapter()).notifyCollapsed();
|
||||
}
|
||||
@@ -95,17 +99,11 @@ public class ExpandableRecyclerView extends RecyclerView {
|
||||
|
||||
public void notifyExpanded() {
|
||||
notifyItemChanged(0);
|
||||
int n = getItemCount();
|
||||
for (int i = 1; i < n; i++) {
|
||||
notifyItemInserted(i);
|
||||
}
|
||||
notifyItemRangeInserted(1, getChildItemCount());
|
||||
}
|
||||
|
||||
public void notifyCollapsed() {
|
||||
int n = getChildItemCount();
|
||||
for (int i = 0; i < n; i++) {
|
||||
notifyItemRemoved(1);
|
||||
}
|
||||
notifyItemRangeRemoved(1, getChildItemCount());
|
||||
notifyItemChanged(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@ public class CrashHandler implements UncaughtExceptionHandler {
|
||||
|
||||
public void uncaughtException(Thread thread, Throwable ex) {
|
||||
try {
|
||||
Log.e("CrashHandler", "Uncaught Exception!!!");
|
||||
ex.printStackTrace();
|
||||
Log.e(TAG, "Uncaught Exception", ex);
|
||||
String t = App.getApp().getString(R.string.sorry_for_crash) + ex.toString();
|
||||
Intent intent = new Intent(App.getApp(), this.mErrorReportClass);
|
||||
intent.putExtra("message", t);
|
||||
|
||||
@@ -4,10 +4,10 @@ import android.content.SharedPreferences;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/3.
|
||||
@@ -70,7 +70,10 @@ public class StateObserver {
|
||||
if (initialState != null)
|
||||
listener.initState(initialState);
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
getListenerListOrCreateIfNotExists(key).add(listener);
|
||||
List<OnStateChangedListener> listeners = getListenerListOrCreateIfNotExists(key);
|
||||
synchronized (listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,19 +84,25 @@ public class StateObserver {
|
||||
if (listeners == null) {
|
||||
return;
|
||||
}
|
||||
listeners.remove(stateChangedListener);
|
||||
synchronized (listeners) {
|
||||
listeners.remove(stateChangedListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void setState(String key, T state) {
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null || listeners.isEmpty()) {
|
||||
if (listeners == null)
|
||||
return;
|
||||
}
|
||||
if (listeners.get(0) instanceof OnBooleanStateChangedListener) {
|
||||
mSharedPreferences.edit().putBoolean(key, (Boolean) state).apply();
|
||||
notifyBooleanStateChanged(listeners, (Boolean) state);
|
||||
synchronized (listeners) {
|
||||
if (listeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (listeners.get(0) instanceof OnBooleanStateChangedListener) {
|
||||
mSharedPreferences.edit().putBoolean(key, (Boolean) state).apply();
|
||||
notifyBooleanStateChanged(listeners, (Boolean) state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +124,7 @@ public class StateObserver {
|
||||
private List<OnStateChangedListener> getListenerListOrCreateIfNotExists(String key) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null) {
|
||||
listeners = new Vector<>();
|
||||
listeners = new ArrayList<>();
|
||||
mKeyStateListenersMap.put(key, listeners);
|
||||
}
|
||||
return listeners;
|
||||
|
||||
@@ -40,8 +40,10 @@ public class ViewBinder {
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
try {
|
||||
method.invoke(o, isChecked);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,6 +5,10 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
@@ -12,7 +16,10 @@ import android.text.TextUtils;
|
||||
|
||||
public class AccessibilityServiceUtils {
|
||||
|
||||
public static void goToPermissionSetting(Context context) {
|
||||
public static void goToAccessibilitySetting(Context context) {
|
||||
if (Pref.isFirstGoToAccessibilitySetting()) {
|
||||
Toast.makeText(context, context.getString(R.string.text_please_choose) + context.getString(R.string.app_name), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
context.startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
@@ -20,4 +21,13 @@
|
||||
</android.support.v7.widget.Toolbar>
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
android:scrollbars="vertical"
|
||||
android:textColor="@android:color/secondary_text_light"
|
||||
android:textSize="16sp"
|
||||
tools:text="错误"/>
|
||||
</LinearLayout>
|
||||
@@ -40,7 +40,7 @@
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_service_green"/>
|
||||
android:src="@drawable/ic_robot_head_green"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_service_green"/>
|
||||
android:src="@drawable/ic_robot_head_green"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -4,21 +4,31 @@
|
||||
###二、自动操作函数
|
||||
**自动操作的函数都需要开启"自动操作服务"才能执行,否则执行到相应函数时脚本会停止运行。**
|
||||
* `click(text)` 点击文本text所在的区域,并返回是否点击成功。当前界面没有出现该文本或者该文本所在区域不可点击时返回false。例如`click("发现")`,是点击"发现"。如果要点击"发现"直至点击成功可以用`while(!click("发现"))`。
|
||||
> 文本所在区域指的是,从文本处向上寻找,直至发现一个可点击的部件为止。
|
||||
* `click(left, top, bottom, right)` 点击与长方形范围严格匹配的区域,并返回是否点击成功。其中left为长方形左边与屏幕左边的像素距离,top为上边与屏幕上边的像素距离,right为右边与**屏幕左边**的像素距离, bottom为下边与**屏幕下边**的距离。区域严格匹配,至于要确定要点击的区域在屏幕上的左边位置,可以在侧拉菜单开启"脚本辅助"(或者安卓7.0以上在通知栏点击"修改"添加脚本辅助快捷设定图标),之后每次点击或长按事件都会提示这次点击或长按的区域并自动保存,可以在编辑器中插入。
|
||||
> 文本所在区域指的是,从文本处向其父视图寻找,直至发现一个可点击的部件为止。
|
||||
* `click(left, top, bottom, right)`
|
||||
> 有些按钮或者部件是图标而不是文字(例如发送朋友圈的照相机图标以及QQ下方的消息、联系人、动态图标),这时不能通过`click(text)`来点击,只能通过描述图标所在的区域来点击。left, bottom, top, right描述的就是点击的区域。至于要定位点击的区域,可以在侧拉菜单开启"点击区域辅助"(或者安卓7.0以上在通知栏点击"修改"添加点击区域辅助快捷设定图标),之后每次点击或长按都会提示这次点击或长按的区域并自动保存,可以在编辑器的右侧拉菜单中插入。
|
||||
|
||||
点击与长方形范围严格匹配的区域,并返回是否点击成功。其中left为长方形左边与屏幕左边的像素距离,top为上边与屏幕上边的像素距离,right为右边与**屏幕左边**的像素距离, bottom为下边与**屏幕上边**的距离。区域严格匹配。
|
||||
> 以下的longClick、select、scrollUp、scrollDown的参数均与click类似,不再赘述。
|
||||
* `longClick` 长按
|
||||
* `select` 选择
|
||||
* `scrollUp` 上滑。不加参数时会寻找"最大"的可滑动的控件下滑,例如微信消息列表等。
|
||||
* `scrollUp` 上滑。不加参数时会寻找"最大"的可滑动的控件上滑,例如微信消息列表等。
|
||||
* `scrollDown` 下滑。不加参数时与scrollUp类似。
|
||||
* `input(string)` 把所有输入框的文本都置为string。
|
||||
* `input(text)` 把所有输入框的文本都置为text。例如input("测试")。
|
||||
* `input(i, text)` 把第i个输入框的文本设为text。i从0开始。
|
||||
###三、其他函数
|
||||
* `sleep(n)` 暂停执行n**毫秒**时间。
|
||||
* `toast(string)` 显示提示文本。
|
||||
* `toast(text)` 显示提示文本。
|
||||
* `launch(packageName)` 运行包名为packageName的应用。例如launch("com.tencent.mm")是运行微信,应用包名可以通过一些工具获取;获取通过函数launchApp代替
|
||||
* `launch(packageName, className)` 运行包名为packageName,类名(Activity)为className的应用。
|
||||
* `launchApp(appName)` 运存应用名称为appName的应用。例如launchApp("QQ")。不同应用名称可能相同,这时只运行其中某一个应用。
|
||||
###四、在脚本中调用安卓
|
||||
* `notStopped` 若当前脚本处于运行状态时返回`true`, 否则返回`false`。对于某些循环, 例如`while(true)`,请用`while(notStopped())`代替,以免死循环造成的脚本无法正常停止。
|
||||
* `isStoppd` 若当前脚本处于停止状态时返回`true`, 否则返回`false`。
|
||||
###四、全局变量
|
||||
* `context` ApplicationContext,参见安卓[android.content.Context](https://developer.android.com/reference/android/content/Context.html)
|
||||
> 这里的context由于是ApplicationContext,是不可见的,不能用于dialog和其他UI相关。如果要显示弹窗或者视图,请启动UI模式(代码的第一行为`"ui";`既可)并使用activity代替。
|
||||
* `activity` UI模式下会启动一个Activity来运行脚本,并在UI线程下运行。可通过该变量来获取该activity。
|
||||
###五、在脚本中调用Java
|
||||
使用importClass来引入要使用的库,例如:
|
||||
```javascript
|
||||
importClass("android.view.View.OnClickListener")
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
click 点击
|
||||
longClick 长按
|
||||
scrollUp 上滑
|
||||
scrollDown 下滑
|
||||
toast 提示
|
||||
launch 运行
|
||||
launchApp 运行应用
|
||||
select 选择
|
||||
input 输入
|
||||
sleep 暂停运行
|
||||
sleep 暂停运行
|
||||
notStopped 非暂停
|
||||
@@ -30,5 +30,11 @@
|
||||
<copyright>Copyright (c) 2015 zzhoujay</copyright>
|
||||
<license>MIT License</license>
|
||||
</notice>
|
||||
<notice>
|
||||
<name>Alipay ZeroSdk</name>
|
||||
<copyright>Copyright 2016 Fung Go (fython)</copyright>
|
||||
<url>https://github.com/fython/AlipayZeroSdk</url>
|
||||
<license>Apache Software License 2.0</license>
|
||||
</notice>
|
||||
|
||||
</notices>
|
||||
@@ -51,17 +51,16 @@
|
||||
<string name="text_email">邮箱</string>
|
||||
<string name="my_github">https://github.com/hyb1996/NoRootScriptDroid</string>
|
||||
<string name="share_app">[免Root脚本机器人]下载地址:https://github.com/hyb1996/NoRootScriptDroid/releases</string>
|
||||
<string name="text_assist_service">点击定位辅助服务</string>
|
||||
<string name="text_assist_serivce_notification">通知栏显示点击定位开关</string>
|
||||
<string name="text_assist_service_notification">通知栏显示点击定位开关</string>
|
||||
<string name="text_assist_service">点击区域辅助服务</string>
|
||||
<string name="text_assist_service_notification">通知栏点击区域辅助开关</string>
|
||||
<string name="text_others">其他</string>
|
||||
<string name="text_assist_mode_enabled">点击定位辅助服务已开启(点击关闭)</string>
|
||||
<string name="text_assist_mode_disabled">点击定位辅助服务已关闭(点击开启)</string>
|
||||
<string name="text_assist_mode_enabled">点击区域辅助服务已开启(点击关闭)</string>
|
||||
<string name="text_assist_mode_disabled">点击区域辅助服务已关闭(点击开启)</string>
|
||||
<string name="text_error_report">错误报告</string>
|
||||
<string name="text_sample_hello_big_sister">大姐姐好</string>
|
||||
<string name="text_sample_qq_hongbao">示例:QQ自动抢红包</string>
|
||||
<string name="text_press_again_to_exit">再按一次退出程序</string>
|
||||
<string name="text_function">函数</string>
|
||||
<string name="sorry_for_crash">\"很抱歉,程序遇到未知错误,即将停止运行\\n错误代码:\"</string>
|
||||
<string name="text_common_function">常用函数</string>
|
||||
<string name="sorry_for_crash">很抱歉(ಥ _ ಥ)程序遇到未知错误,即将停止运行\n错误代码:</string>
|
||||
<string name="text_no_running_script">没有正在运行的脚本</string>
|
||||
<string name="text_already_stop_n_scripts">已停止%d个正在运行的脚本</string>
|
||||
<string name="text_start_running">开始运行</string>
|
||||
@@ -85,4 +84,13 @@
|
||||
<string name="text_choose_email_app">请选择邮件应用</string>
|
||||
<string name="text_assist_clip">点击定位剪贴板</string>
|
||||
<string name="text_script_stopped">脚本已停止</string>
|
||||
<string name="assist_mode_notice">\"点击区域辅助服务\"是在要点击的区域不是文本时使用的,参见\"语法与API\"。\"点击区域辅助服务\"只有在\"自动操作服务\"开启时才有效。</string>
|
||||
<string name="text_please_choose">请选择</string>
|
||||
<string name="text_crash">崩溃了o(≧口≦)o</string>
|
||||
<string name="crash_feedback">点击\"退出\"退出程序(ಥ _ ಥ)或者复制调试信息反馈给开发者(≧∇≦)ノ</string>
|
||||
<string name="text_cannot_create_dialog_when_app_invisible">无法在后台显示弹框,脚本已停止运行</string>
|
||||
<string name="text_sample_for_qq_chat">示例:QQ强制聊天</string>
|
||||
<string name="text_re_import_samples">重新导入示例脚本文件</string>
|
||||
<string name="text_re_import_succeed">导入成功,重新打开应用生效</string>
|
||||
<string name="text_fail">失败</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/text_others">
|
||||
|
||||
<Preference
|
||||
android:title="@string/text_re_import_samples"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/text_about">
|
||||
|
||||
|
||||
Reference in New Issue
Block a user