diff --git a/.idea/modules.xml b/.idea/modules.xml index 4fac18b4..7e950955 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,8 +2,8 @@ + - diff --git a/autojs/src/main/assets/javascript_engine_init.js b/autojs/src/main/assets/javascript_engine_init.js index fda1ad45..e1da05c3 100644 --- a/autojs/src/main/assets/javascript_engine_init.js +++ b/autojs/src/main/assets/javascript_engine_init.js @@ -14,13 +14,32 @@ var loadJar = function(path){ __runtime__.loadJar(path); } -__runtime__.bridges.setFunctionCaller(function(func, target, args){ - var arr = []; - var len = args.length; - for(var i = 0; i < len; i++){ - arr.push(args[i]); - } - return func.apply(target, arr); +__runtime__.bridges.setBridges({ + call: function(func, target, args){ + var arr = []; + var len = args.length; + for(var i = 0; i < len; i++){ + arr.push(args[i]); + } + return func.apply(target, arr); + }, + toArray: function(o){ + var arr = []; + for(var i = 0; i < o.size(); i++){ + arr.push(o.get(i)); + } + for(var key in o){ + if(arr[key]) + continue; + var v = o[key]; + if(typeof(v) == 'function'){ + arr[key] = v.bind(o); + }else{ + arr[key] = v; + } + } + return arr; + } }); var __that__ = this; diff --git a/autojs/src/main/java/com/stardust/autojs/core/accessibility/UiCollection.java b/autojs/src/main/java/com/stardust/autojs/core/accessibility/UiCollection.java new file mode 100644 index 00000000..dfb9c93f --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/accessibility/UiCollection.java @@ -0,0 +1,196 @@ +package com.stardust.autojs.core.accessibility; + +import android.support.annotation.Nullable; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; +import android.view.accessibility.AccessibilityNodeInfo; + +import com.stardust.automator.ActionArgument; +import com.stardust.automator.UiGlobalSelector; +import com.stardust.automator.UiObject; +import com.stardust.automator.UiObjectCollection; +import com.stardust.util.ArrayUtils; +import com.stardust.util.Consumer; +import com.stardust.util.Func1; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.NativeArray; +import org.mozilla.javascript.NativeJavaObject; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; +import org.mozilla.javascript.ast.Scope; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by Stardust on 2017/10/31. + */ + +public class UiCollection extends NativeJavaObject { + + private UiObjectCollection mUiObjectCollection; + + public UiCollection(UiObjectCollection c, Scriptable scope) { + super(scope, c, UiObjectCollection.class); + mUiObjectCollection = c; + } + + public boolean performAction(int action) { + return mUiObjectCollection.performAction(action); + } + + public boolean performAction(int action, ActionArgument... arguments) { + return mUiObjectCollection.performAction(action, arguments); + } + + public boolean click() { + return mUiObjectCollection.click(); + } + + public boolean longClick() { + return mUiObjectCollection.longClick(); + } + + public boolean accessibilityFocus() { + return mUiObjectCollection.accessibilityFocus(); + } + + public boolean clearAccessibilityFocus() { + return mUiObjectCollection.clearAccessibilityFocus(); + } + + public boolean focus() { + return mUiObjectCollection.focus(); + } + + public boolean clearFocus() { + return mUiObjectCollection.clearFocus(); + } + + public boolean copy() { + return mUiObjectCollection.copy(); + } + + public boolean paste() { + return mUiObjectCollection.paste(); + } + + public boolean select() { + return mUiObjectCollection.select(); + } + + public boolean cut() { + return mUiObjectCollection.cut(); + } + + public boolean collapse() { + return mUiObjectCollection.collapse(); + } + + + public boolean expand() { + return mUiObjectCollection.expand(); + } + + public boolean dismiss() { + return mUiObjectCollection.dismiss(); + } + + public boolean show() { + return mUiObjectCollection.show(); + } + + public boolean scrollForward() { + return mUiObjectCollection.scrollForward(); + } + + public boolean scrollBackward() { + return mUiObjectCollection.scrollBackward(); + } + + public boolean scrollUp() { + return mUiObjectCollection.scrollUp(); + } + + public boolean scrollDown() { + return mUiObjectCollection.scrollDown(); + } + + public boolean scrollLeft() { + return mUiObjectCollection.scrollLeft(); + } + + public boolean scrollRight() { + return mUiObjectCollection.scrollRight(); + } + + public boolean contextClick() { + return mUiObjectCollection.contextClick(); + } + + public boolean setSelection(int s, int e) { + return mUiObjectCollection.setSelection(s, e); + } + + public boolean setText(CharSequence text) { + return mUiObjectCollection.setText(text); + } + + public boolean setProgress(float value) { + return mUiObjectCollection.setProgress(value); + } + + public boolean scrollTo(int row, int column) { + return mUiObjectCollection.scrollTo(row, column); + } + + public UiCollection each(Consumer consumer) { + mUiObjectCollection.each(consumer); + return this; + } + + public UiCollection find(UiGlobalSelector selector) { + return new UiCollection(mUiObjectCollection.find(selector), getParentScope()); + } + + @Nullable + public UiObject findOne(UiGlobalSelector selector) { + return mUiObjectCollection.findOne(selector); + } + + public boolean empty() { + return mUiObjectCollection.empty(); + } + + public boolean nonEmpty() { + return mUiObjectCollection.nonEmpty(); + } + + + @Override + public boolean has(int index, Scriptable start) { + return index > 0 && index < mUiObjectCollection.size(); + } + + @Override + public Object get(int index, Scriptable start) { + return mUiObjectCollection.get(index); + } + + @Override + public Object get(String name, Scriptable start) { + if ("length".equals(name)) { + return mUiObjectCollection.size(); + } + return super.get(name, start); + } + + @Override + public boolean has(String name, Scriptable start) { + if ("length".equals(name)) { + return true; + } + return super.has(name, start); + } +} + diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java index c2762975..ef2e786a 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java @@ -3,19 +3,25 @@ package com.stardust.autojs.engine; import android.util.Log; import com.stardust.autojs.BuildConfig; +import com.stardust.autojs.core.accessibility.UiCollection; import com.stardust.autojs.rhino.AndroidContextFactory; import com.stardust.autojs.rhino.RhinoAndroidHelper; import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.StringScriptSource; +import com.stardust.automator.UiObjectCollection; import com.stardust.pio.PFiles; import com.stardust.pio.UncheckedIOException; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.ImporterTopLevel; +import org.mozilla.javascript.NativeArray; +import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; +import org.mozilla.javascript.TopLevel; +import org.mozilla.javascript.WrapFactory; import org.mozilla.javascript.commonjs.module.RequireBuilder; import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider; import org.mozilla.javascript.tools.debugger.Dim; @@ -23,9 +29,12 @@ import org.mozilla.javascript.tools.debugger.Dim; import java.io.File; import java.io.IOException; import java.io.Reader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.ArrayList; import java.util.List; +import java.util.Locale; /** * Created by Stardust on 2017/4/2. @@ -33,7 +42,13 @@ import java.util.List; public class RhinoJavaScriptEngine extends JavaScriptEngine { + public interface TypeWrapper { + + Object wrap(Context cx, Scriptable scope, Object obj, Class staticType); + } + private static final String LOG_TAG = "RhinoJavaScriptEngine"; + private static Constructor nativeStringConstructor; private static int contextCount = 0; private static StringScriptSource sInitScript; @@ -124,6 +139,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { .setSandboxed(true) .createRequire(context, scope) .install(scope); + } public Context getContext() { @@ -148,9 +164,36 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { contextCount++; context.setOptimizationLevel(-1); context.setLanguageVersion(Context.VERSION_ES6); + context.setLocale(Locale.getDefault()); + context.setWrapFactory(new WrapFactory()); return context; } + private Object createNativeString(Object obj) { + if (nativeStringConstructor == null) + return obj; + try { + return nativeStringConstructor.newInstance(obj.toString()); + } catch (Exception e) { + e.printStackTrace(); + return obj; + } + } + + private class WrapFactory extends org.mozilla.javascript.WrapFactory { + @Override + public Object wrap(Context cx, Scriptable scope, Object obj, Class staticType) { + if (staticType == String.class) { + return createNativeString(obj); + } + if (staticType == UiObjectCollection.class ) { + return getRuntime().bridges.toArray(obj); + + } + return super.wrap(cx, scope, obj, staticType); + } + } + private static class InterruptibleAndroidContextFactory extends AndroidContextFactory { public InterruptibleAndroidContextFactory(File cacheDirectory) { @@ -172,4 +215,14 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { } } + + static { + try { + Class c = Class.forName("org.mozilla.javascript.NativeString"); + nativeStringConstructor = c.getDeclaredConstructor(CharSequence.class); + nativeStringConstructor.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java index 404497bb..0678079e 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java @@ -1,28 +1,41 @@ package com.stardust.autojs.runtime; +import com.stardust.autojs.core.accessibility.UiCollection; + /** * Created by Stardust on 2017/7/21. */ public class ScriptBridges { - - public interface FunctionCaller { + public interface Bridges { Object[] NO_ARGUMENTS = new Object[0]; Object call(Object func, Object target, Object[] arg); + + Object toArray(Object o); } - private FunctionCaller mFunctionCaller; + private Bridges mBridges; - public void setFunctionCaller(FunctionCaller functionCaller) { - mFunctionCaller = functionCaller; + public void setBridges(Bridges bridges) { + mBridges = bridges; } public Object callFunction(Object func, Object target, Object[] args) { - if (mFunctionCaller == null) - throw new IllegalStateException("no function caller"); - return mFunctionCaller.call(func, target, args); + checkBridges(); + return mBridges.call(func, target, args); + } + + private void checkBridges() { + if (mBridges == null) + throw new IllegalStateException("no bridges set"); + } + + + public Object toArray(Object c) { + checkBridges(); + return mBridges.toArray(c); } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/AppUtils.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/AppUtils.java index aceebcd4..0627b50e 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/AppUtils.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/AppUtils.java @@ -47,7 +47,10 @@ public class AppUtils { @ScriptInterface public boolean launchApp(String appName) { - return launchPackage(getPackageName(appName)); + String pkg = getPackageName(appName); + if(pkg == null) + return false; + return launchPackage(pkg); } @ScriptInterface diff --git a/automator/src/main/java/com/stardust/automator/UiObjectCollection.java b/automator/src/main/java/com/stardust/automator/UiObjectCollection.java index 4f89a4e0..3f00bb64 100644 --- a/automator/src/main/java/com/stardust/automator/UiObjectCollection.java +++ b/automator/src/main/java/com/stardust/automator/UiObjectCollection.java @@ -53,6 +53,10 @@ public class UiObjectCollection { mNodes = list; } + public UiObject[] toArray(){ + return mNodes.toArray(new UiObject[mNodes.size()]); + } + public boolean performAction(int action) { boolean fail = false; for (UiObject node : mNodes) { @@ -204,15 +208,6 @@ public class UiObjectCollection { return this; } - public UiObjectCollection filter(Func1 func1) { - List list = new ArrayList<>(); - for (UiObject uiObject : mNodes) { - if (func1.call(uiObject)) - list.add(uiObject); - } - return of(list); - } - public UiObjectCollection find(UiGlobalSelector selector) { List list = new ArrayList<>(); for (UiObject object : mNodes) { diff --git a/common/src/main/java/com/stardust/util/ArrayUtils.java b/common/src/main/java/com/stardust/util/ArrayUtils.java index 2e48c01e..2c13f0d3 100644 --- a/common/src/main/java/com/stardust/util/ArrayUtils.java +++ b/common/src/main/java/com/stardust/util/ArrayUtils.java @@ -1,5 +1,6 @@ package com.stardust.util; +import java.lang.reflect.Array; import java.util.List; /** @@ -34,4 +35,12 @@ public class ArrayUtils { } return str; } + + @SuppressWarnings("unchecked") + public static T[] merge(T[] a1, T[] a2) { + T[] a = (T[]) Array.newInstance(a1.getClass().getComponentType(), a1.length + a2.length); + System.arraycopy(a1, 0, a, 0, a1.length); + System.arraycopy(a2, 0, a, a1.length, a2.length); + return a; + } }