add dialogs, fix code completion

This commit is contained in:
hyb1996
2017-05-08 15:22:01 +08:00
parent 472bd46b87
commit 0349c113ca
40 changed files with 958 additions and 158 deletions

View File

@@ -1 +1,82 @@
__importClass__(com.stardust.scriptdroid.autojs.Shell);
__importClass__(com.stardust.scriptdroid.autojs.api.Shell);
var dialogs = {};
dialogs.rawInput = function(title, prefill){
prefill = prefill || "";
return __runtime__.dialogs.rawInput(title, prefill);
};
dialogs.input = function(title, prefill){
return eval(rawInput(title, prefill));
}
dialogs.prompt = dialogs.rawInput;
dialogs.alert = function(title, prefill){
prefill = prefill || "";
return __runtime__.dialogs.alert(title, prefill);
}
dialogs.confirm = function(title, prefill){
prefill = prefill || "";
return __runtime__.dialogs.confirm(title, prefill);
}
dialogs.select = function(title, items){
return __runtime__.dialogs.select(title, [].slice.call(arguments, 1));
}
dialogs.singleChoice = function(title, index, items){
return __runtime__.dialogs.singleChoice(title, index, [].slice.call(arguments, 2));
}
dialogs.multiChoice = function(title, index, items){
var javaArray = __runtime__.dialogs.multiChoice(title, index, [].slice.call(arguments, 2));
var jsArray = {};
for each(i in javaArray){
jsArray.push(i);
}
return jsArray;
}
var rawInput = function(title, prefill){
return dialogs.rawInput(title, prefill);
}
var input = function(title, prefill){
return dialogs.input(title, prefill);
}
var alert = function(title, prefill){
dialogs.alert(title, prefill);
}
var confirm = function(title, prefill){
return dialogs.confirm(title, prefill);
}
var prompt = function(title, prefill){
return dialogs.prompt(title, prefill);
}
/*
dialogs.rawInput = function(title, prefill){
prefill = prefill || "";
return __runtime__.dialogs.rawInput(title, prefill);
}
dialogs.input = function(title, prefill){
return eval(rawInput(title, prefill));
}
dialogs.alert = function(title, content){
__runtime__.dialogs.alert(title, content);
}
dialogs.select = function(title, content){
__runtime__.dialogs.alert(title, content);
}
*/

View File

@@ -0,0 +1,62 @@
[ "toast",
"app",
"launchPackage",
"launch",
"launchApp",
"getPackageName",
"openAppSetting",
"sleep",
"isStopped",
"notStopped",
"stop",
"console",
"log",
"print",
"err",
"openConsole",
"clearConsole",
"shell",
"currentPackage",
"currentActivity",
"back",
"home",
"powerDialog",
"notifications",
"quickSettings",
"recents",
"splitScreen",
"click",
"longClick",
"scrollDown",
"scrollUp",
"input",
"setClip",
"SetScreenMetrics",
"Tap",
"Swipe",
"Screencap",
"KeyCode",
"Home",
"Back",
"Power",
"Up",
"Down",
"Left",
"Right",
"OK",
"VolumeUp",
"VolumeDown",
"Menu",
"Camera",
"Text",
"selector",
"open",
"newInjectableWebClient",
"newInjectableWebView",
"dialogs",
"rawInput",
"input",
"alert",
"confirm",
"prompt"
]

View File

@@ -0,0 +1,31 @@
var i = dialogs.select("请选择工具", "获取应用包名", "打开应用详情页", "卸载应用");
if(i == -1){
alert("没有选择任何工具!");
}
switch(i){
case 0:
//获取应用包名
appName = rawInput("请输入应用名称", "QQ");
packageName = getPackageName(appName);
toast(packageName);
setClip(packageName);
toast("已复制到剪贴板");
break;
case 1:
//打开应用详情页
appName = rawInput("请输入应用名称", "微信");
openAppSetting(getPackageName(appName));
break;
case 2:
//卸载应用
appName = rawInput("请输入应用名称");
packageName = getPackageName(appName);
if(packageName == ""){
toast("应用不存在");
}else if(confirm("确定卸载应用" + packageName + "吗?")){
app.uninstall(packageName);
}
break;
}

View File

@@ -0,0 +1,2 @@
var appName = rawInput("请输入应用名称");
launchApp(appName);

View File

@@ -0,0 +1,22 @@
var num1 = input("请输入第一个数字");
var op = dialogs.singleChoice("请选择运算", 0, "加", "减", "乘", "除", "幂");
var num2 = input("请输入第二个数字");
var result = 0;
switch(op){
case 0:
result = num1 + num2;
break;
case 1:
result = num1 - num2;
break;
case 2:
result = num1 * num2;
break;
case 3:
result = num1 / num2;
break;
case 4:
result = Math.pow(num1, num2);
break;
}
alert("运算结果", result);

View File

@@ -0,0 +1,20 @@
SetScreenMetrics(1080, 1920);
launchApp("QQ");
//点击动态图标
Tap(891, 1851);
//点击好友动态
Tap(192, 453);
//点击头像
Tap(155, 638);
//点击留言
Tap(747, 775);
while(true){
//点击箭头图标
Tap(1029, 433);
//点击删除
Tap(530, 820);
//点击确定
Tap(331, 1122);
}

View File

@@ -31,7 +31,6 @@ public class App extends MultiDexApplication {
private static final String TAG = "App";
private static WeakReference<App> instance;
private static WeakReference<Activity> currentActivity;
public static App getApp() {
return instance.get();
@@ -89,27 +88,23 @@ public class App extends MultiDexApplication {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
super.onActivityCreated(activity, savedInstanceState);
AutoJs.getInstance().getAppUtils().setCurrentActivity(activity);
}
@Override
public void onActivityPaused(Activity activity) {
currentActivity = null;
AutoJs.getInstance().getAppUtils().setCurrentActivity(null);
}
@Override
public void onActivityResumed(Activity activity) {
ScreenMetrics.initIfNeeded(activity);
currentActivity = new WeakReference<>(activity);
AutoJs.getInstance().getAppUtils().setCurrentActivity(activity);
}
});
}
@Keep
public static Activity currentActivity() {
return currentActivity.get();
}
public static String getResString(int id) {
return getApp().getString(id);
}

View File

@@ -8,7 +8,10 @@ import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.ScriptEngineServiceBuilder;
import com.stardust.autojs.engine.NodeJsJavaScriptEngineManager;
import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.runtime.*;
import com.stardust.autojs.runtime.AccessibilityBridge;
import com.stardust.autojs.runtime.ScriptStopException;
import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.autojs.runtime.api.AppUtils;
import com.stardust.automator.AccessibilityEventCommandHost;
import com.stardust.automator.simple_action.SimpleActionPerformHost;
import com.stardust.pio.PFile;
@@ -16,9 +19,9 @@ import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.api.Shell;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.ui.console.StardustConsole;
import com.stardust.util.AssetsCache;
import com.stardust.util.Supplier;
import com.stardust.util.UiHandler;
import com.stardust.view.accessibility.AccessibilityInfoProvider;
@@ -56,10 +59,12 @@ public class AutoJs implements AccessibilityBridge {
private final ScriptEngineService mScriptEngineService;
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
private final UiHandler mUiHandler;
private final AppUtils mAppUtils;
private AutoJs(final Context context) {
mUiHandler = new UiHandler(context);
mAppUtils = new AppUtils(context);
mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager());
ScriptEngineManager manager = createScriptEngineManager(context);
mScriptEngineService = new ScriptEngineServiceBuilder()
@@ -70,7 +75,17 @@ public class AutoJs implements AccessibilityBridge {
@Override
public ScriptRuntime get() {
return new ScriptRuntime(mUiHandler, new StardustConsole(mUiHandler), AutoJs.this);
return new ScriptRuntime.Builder()
.setAppUtils(mAppUtils)
.setConsole(new StardustConsole(mUiHandler))
.setAccessibilityBridge(AutoJs.this)
.setUiHandler(mUiHandler)
.setShellSupplier(new Supplier<AbstractShell>() {
@Override
public AbstractShell get() {
return new Shell(true);
}
}).build();
}
})
.build();
@@ -100,6 +115,10 @@ public class AutoJs implements AccessibilityBridge {
return mAccessibilityActionRecorder;
}
public AppUtils getAppUtils() {
return mAppUtils;
}
public UiHandler getUiHandler() {
return mUiHandler;
}

View File

@@ -0,0 +1,71 @@
package com.stardust.scriptdroid.autojs;
import com.stardust.autojs.runtime.AccessibilityBridge;
import com.stardust.autojs.runtime.ScriptVariable;
import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.autojs.runtime.api.AppUtils;
import com.stardust.autojs.runtime.api.Console;
import com.stardust.scriptdroid.autojs.api.Dialogs;
import com.stardust.util.Supplier;
import com.stardust.util.UiHandler;
/**
* Created by Stardust on 2017/5/8.
*/
public class ScriptRuntime extends com.stardust.autojs.runtime.ScriptRuntime {
public static class Builder {
private AppUtils mAppUtils;
private UiHandler mUiHandler;
private Console mConsole;
private AccessibilityBridge mAccessibilityBridge;
private Supplier<AbstractShell> mShellSupplier;
public Builder() {
}
public Builder setAppUtils(AppUtils appUtils) {
mAppUtils = appUtils;
return this;
}
public Builder setUiHandler(UiHandler uiHandler) {
mUiHandler = uiHandler;
return this;
}
public Builder setConsole(Console console) {
mConsole = console;
return this;
}
public Builder setAccessibilityBridge(AccessibilityBridge accessibilityBridge) {
mAccessibilityBridge = accessibilityBridge;
return this;
}
public Builder setShellSupplier(Supplier<AbstractShell> shellSupplier) {
mShellSupplier = shellSupplier;
return this;
}
public ScriptRuntime build() {
return new ScriptRuntime(mAppUtils, mUiHandler, mConsole, mAccessibilityBridge, mShellSupplier);
}
}
@ScriptVariable
public Dialogs dialogs;
public ScriptRuntime(AppUtils appUtils, UiHandler uiHandler, Console console, AccessibilityBridge accessibilityBridge, Supplier<AbstractShell> shellSupplier) {
super(appUtils, uiHandler, console, accessibilityBridge, shellSupplier);
dialogs = new Dialogs(appUtils, uiHandler);
}
}

View File

@@ -0,0 +1,135 @@
package com.stardust.scriptdroid.autojs.api;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.WindowManager;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.util.UiHandler;
/**
* Created by Stardust on 2017/5/8.
*/
public class BlockedMaterialDialog extends MaterialDialog {
protected BlockedMaterialDialog(MaterialDialog.Builder builder) {
super(builder);
}
@Override
public void show() {
if (!(getContext() instanceof Activity)) {
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
super.show();
}
public static class Builder extends MaterialDialog.Builder {
private UiHandler mUiHandler;
public Builder(Context context, UiHandler uiHandler) {
super(context);
mUiHandler = uiHandler;
}
public MaterialDialog.Builder input(@Nullable CharSequence hint, @Nullable CharSequence prefill, boolean allowEmptyInput, final VolatileBox<String> result) {
dismissListener(result);
super.input(hint, prefill, allowEmptyInput, new MaterialDialog.InputCallback() {
@Override
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
result.set(input.toString());
synchronized (result) {
result.notify();
}
}
});
return this;
}
public Builder confirm(final VolatileBox<Boolean> result) {
onAny(new SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
if (which == DialogAction.POSITIVE) {
result.setAndNotify(true);
} else {
result.setAndNotify(false);
}
}
});
return this;
}
public MaterialDialog.Builder itemsCallback(final VolatileBox<Integer> result) {
dismissListener(result);
super.itemsCallback(new ListCallback() {
@Override
public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) {
result.setAndNotify(position);
}
});
return this;
}
public MaterialDialog.Builder itemsCallbackMultiChoice(@Nullable Integer[] selectedIndices, final VolatileBox<Integer[]> result) {
dismissListener(result);
super.itemsCallbackMultiChoice(selectedIndices, new ListCallbackMultiChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, Integer[] which, CharSequence[] text) {
result.setAndNotify(which);
return true;
}
});
return this;
}
public MaterialDialog.Builder itemsCallbackSingleChoice(int selectedIndex, final VolatileBox<Integer> result) {
dismissListener(result);
super.itemsCallbackSingleChoice(selectedIndex, new ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
result.setAndNotify(which);
return true;
}
});
return this;
}
public Builder dismissListener(final VolatileBox<?> result) {
super.dismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
synchronized (result) {
result.notify();
}
}
});
return this;
}
@Override
public MaterialDialog show() {
mUiHandler.post(new Runnable() {
@Override
public void run() {
Builder.super.show();
}
});
return null;
}
@Override
public MaterialDialog build() {
return new BlockedMaterialDialog(this);
}
}
}

View File

@@ -0,0 +1,123 @@
package com.stardust.scriptdroid.autojs.api;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.DialogInterface;
import android.text.TextUtils;
import android.view.ContextThemeWrapper;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.autojs.runtime.ScriptInterface;
import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.autojs.runtime.api.AppUtils;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.util.ArrayUtils;
import com.stardust.util.UiHandler;
/**
* Created by Stardust on 2017/5/8.
*/
public class Dialogs {
private AppUtils mAppUtils;
private UiHandler mUiHandler;
private ContextWrapper mContextWrapper;
public Dialogs(AppUtils appUtils, UiHandler uiHandler) {
mAppUtils = appUtils;
mUiHandler = uiHandler;
}
@ScriptInterface
public String rawInput(String title, String prefill) {
VolatileBox<String> result = new VolatileBox<>(null);
dialogBuilder()
.input(null, prefill, true, result)
.title(title)
.show();
return result.blockedGet();
}
@ScriptInterface
public void alert(String title, String content) {
VolatileBox<Void> lock = new VolatileBox<>();
MaterialDialog.Builder builder = dialogBuilder()
.dismissListener(lock)
.title(title)
.positiveText(R.string.ok);
if (!TextUtils.isEmpty(content)) {
builder.content(content);
}
builder.show();
lock.blockedGet();
}
@ScriptInterface
public boolean confirm(String title, String content) {
VolatileBox<Boolean> result = new VolatileBox<>(false);
MaterialDialog.Builder builder = dialogBuilder()
.dismissListener(result)
.confirm(result)
.title(title)
.positiveText(R.string.ok)
.negativeText(R.string.cancel);
if (!TextUtils.isEmpty(content)) {
builder.content(content);
}
builder.show();
return result.blockedGet();
}
private Context getContext() {
if (mContextWrapper == null) {
mContextWrapper = new ContextThemeWrapper(mUiHandler.getContext(), R.style.AppTheme);
}
return mContextWrapper;
}
@ScriptInterface
public int select(String title, String... items) {
VolatileBox<Integer> result = new VolatileBox<>(-1);
dialogBuilder()
.itemsCallback(result)
.title(title)
.items((CharSequence[]) items)
.show();
return result.blockedGet();
}
@ScriptInterface
public int singleChoice(String title, int selectedIndex, String... items) {
VolatileBox<Integer> result = new VolatileBox<>(-1);
dialogBuilder()
.itemsCallbackSingleChoice(selectedIndex, result)
.title(title)
.positiveText(R.string.ok)
.items((CharSequence[]) items)
.show();
return result.blockedGet();
}
@ScriptInterface
public int[] multiChoice(String title, int[] indices, String... items) {
VolatileBox<Integer[]> result = new VolatileBox<>(new Integer[0]);
dialogBuilder()
.itemsCallbackMultiChoice(ArrayUtils.box(indices), result)
.title(title)
.positiveText(R.string.ok)
.items((CharSequence[]) items)
.show();
return ArrayUtils.unbox(result.blockedGet());
}
private BlockedMaterialDialog.Builder dialogBuilder() {
Context context = mAppUtils.getCurrentActivity();
if (context == null) {
context = getContext();
}
return new BlockedMaterialDialog.Builder(context, mUiHandler);
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.autojs;
package com.stardust.scriptdroid.autojs.api;
import android.content.Context;
import android.os.Handler;
@@ -10,6 +10,7 @@ import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.lang.ThreadCompat;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.autojs.AutoJs;
import java.io.BufferedReader;
import java.io.IOException;

View File

@@ -0,0 +1,47 @@
package com.stardust.scriptdroid.autojs.api;
import com.stardust.autojs.runtime.ScriptInterruptedException;
/**
* Created by Stardust on 2017/5/8.
*/
public class VolatileBox<T> {
private volatile T mValue;
public VolatileBox() {
}
public VolatileBox(T value) {
set(value);
}
public T get() {
return mValue;
}
public void set(T value) {
mValue = value;
}
public void setAndNotify(T value) {
mValue = value;
synchronized (this) {
notify();
}
}
public T blockedGet() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
throw new ScriptInterruptedException();
}
}
return mValue;
}
}

View File

@@ -1,24 +1,8 @@
package com.stardust.scriptdroid.record.inputevent;
import android.preference.PreferenceManager;
import android.util.Log;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.autojs.Shell;
import com.stardust.scriptdroid.autojs.api.Shell;
import com.stardust.scriptdroid.record.Recorder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import jackpal.androidterm.ShellTermSession;
import jackpal.androidterm.emulatorview.TermSession;
import jackpal.androidterm.util.TermSettings;
/**
* Created by Stardust on 2017/3/6.
*/

View File

@@ -23,7 +23,7 @@ public class InputEventToSendEventJsConverter extends InputEventConverter {
public InputEventToSendEventJsConverter() {
mCode.append("var sh = new Shell(true);\n")
.append("sh.SetScreenScale(").append(getScreenWidth()).append(", ")
.append("sh.SetScreenMetrics(").append(getScreenWidth()).append(", ")
.append(getScreenHeight()).append(");\n");
}

View File

@@ -1,12 +1,19 @@
package com.stardust.scriptdroid.ui.edit.completion;
import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import com.google.gson.Gson;
import com.stardust.pio.PFile;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.jecelyin.editor.v2.core.widget.TextView;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -106,7 +113,7 @@ public class CodeCompletion implements TextWatcher {
mFunctions = functions;
}
private String[] mFunctions = {"toast", "launchPackage", "launch", "launchApp", "click", "longClick", "scrollUp", "scrollDown", "select", "focus", "paste", "input", "sleep", "isStopped", "notStopped", "printf", "err", "openConsole", "clearConsole", "shell", "getTexts", "getPackageName", "getActivityName", "setClip", "addAccessibilityDelegate"};
private String[] mFunctions = new String[0];
private boolean searchCodeCompletion(String str) {
Collection<CodeCompletionItem> c = searchWordCompletion(str);
@@ -148,8 +155,7 @@ public class CodeCompletion implements TextWatcher {
return searchCodeCompletion(str, KEYWORDS);
}
private static final String[] DEFAULT_CODE_COMPLETIONS = new String[]{"=", "(", ")", ";", "{", "}", "\"", "!", "[", "]", "\\", ".", ", "};
private static final String[] DEFAULT_CODE_COMPLETIONS = new String[]{"=", "(", ")", ";", "{", "}", "\"", "!", "[", "]", "\\", ">", "<", ".", ", "};
private static final List<CodeCompletionItem> DEFAULT_CODE_COMPLETION_LIST = new ArrayList<>();
static {

View File

@@ -14,10 +14,14 @@ import android.widget.TextView;
import android.widget.Toast;
import android.workground.WrapContentLinearLayoutManager;
import com.google.gson.Gson;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -79,7 +83,7 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
private void init() {
setAdapter(new CodeCompletionAdapter());
setLayoutManager(new WrapContentLinearLayoutManager(getContext(), HORIZONTAL, false));
mCodeCompletion.setFunctions(AutoJs.getInstance().getScriptEngineService().getGlobalFunctions());
mCodeCompletion.setFunctions(readFunctions(getContext(), "js/functions.json"));
}
public void setEditTextBridge(EditTextBridge editTextBridge) {
@@ -124,4 +128,14 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
itemView.setOnLongClickListener(mOnCodeCompletionItemLongClickListener);
}
}
private static String[] readFunctions(Context context, String path) {
Gson gson = new Gson();
try {
return gson.fromJson(new InputStreamReader(context.getAssets().open(path)), String[].class);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}