diff --git a/autojs/src/main/assets/jvm-npm.js b/autojs/src/main/assets/jvm-npm.js index 25de71e6..4f7c81ef 100644 --- a/autojs/src/main/assets/jvm-npm.js +++ b/autojs/src/main/assets/jvm-npm.js @@ -78,6 +78,9 @@ module = (typeof module === 'undefined') ? {} : module; if(builtInModules.indexOf(normalizePath) >= 0 && !files.exists(normalizePath)){ return NativeRequire.require(normalizePath); } + if(id === "events"){ + return events; + } if(id.startsWith("http://") || id.startsWith("https://")){ return NativeRequire.require(id); } @@ -252,6 +255,9 @@ module = (typeof module === 'undefined') ? {} : module; } function normalizeName (fileName, ext) { + if(fileName.endsWith('.json')){ + return fileName; + } var extension = ext || '.js'; if (fileName.endsWith(extension)) { return fileName; diff --git a/autojs/src/main/assets/modules/__images__.js b/autojs/src/main/assets/modules/__images__.js index f5228245..e11814cc 100644 --- a/autojs/src/main/assets/modules/__images__.js +++ b/autojs/src/main/assets/modules/__images__.js @@ -169,7 +169,23 @@ module.exports = function(__runtime__, scope){ format = format || "png"; quality = quality == undefined ? 100 : quality; return rtImages.toBytes(img, format, quality); - } + } + + images.readPixels = function(path){ + var img = images.read(path); + var bitmap = img.getBitmap(); + var w = bitmap.getWidth(); + var h = bitmap.getHeight(); + var pixels = util.java.array("int", w * h); + bitmap.getPixels(pixels, 0, w, 0, 0, w, h); + img.recycle(); + return { + data: pixels, + width: w, + height: h + }; + } + function getColorDetector(color, algorithm, threshold){ switch(algorithm){ diff --git a/autojs/src/main/assets/modules/__java_util__.js b/autojs/src/main/assets/modules/__java_util__.js index 3a97e5d4..9fe8feba 100644 --- a/autojs/src/main/assets/modules/__java_util__.js +++ b/autojs/src/main/assets/modules/__java_util__.js @@ -4,6 +4,32 @@ J.instanceOf = function(obj, clazz){ return java.lang.Class.forName(clazz).isAssignableFrom(obj.getClass()); } +function typeToClass(type) { + if (typeof(type) != 'string') { + return type; + } + var types = { + "int": "Integer", + "long": "Long", + "string": "String", + "double": "Double", + "char": "Character", + "byte": "Byte", + "float": "Float" + }; + if (types[type]) { + return Packages["java.lang." + types[type]].TYPE; + } + return Packages[type]; +} +function array(type) { + var clazz = typeToClass(type); + var args = arguments; + args[0] = clazz; + return java.lang.reflect.Array.newInstance.apply(null, args); +} + +J.array = array; module.exports = J; \ No newline at end of file diff --git a/autojs/src/main/assets/modules/__ui__.js b/autojs/src/main/assets/modules/__ui__.js index 91ad4f18..d5b6e446 100644 --- a/autojs/src/main/assets/modules/__ui__.js +++ b/autojs/src/main/assets/modules/__ui__.js @@ -3,7 +3,7 @@ module.exports = function (runtime, global) { require("object-observe-lite.min")(); require("array-observe.min")(); - var J = require("__java_util__"); + var J = util.java; var ui = {}; diff --git a/autojs/src/main/assets/modules/__util__.js b/autojs/src/main/assets/modules/__util__.js index 59b8083b..ec6d0115 100644 --- a/autojs/src/main/assets/modules/__util__.js +++ b/autojs/src/main/assets/modules/__util__.js @@ -20,6 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. var formatRegExp = /%[sdj%]/g; +exports.java = require("__java_util__"); exports.format = function(f) { if (!isString(f)) { var objects = []; diff --git a/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java b/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java index 163927c8..0fec757b 100644 --- a/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java +++ b/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import dalvik.system.DexClassLoader; import dalvik.system.DexFile; /** @@ -25,10 +26,11 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa private final ClassLoader parent; - private List dx; + private List dx; private final File dexFile; private final File odexOatFile; private final File classFile; + private final File mCacheDir; /** * Create a new instance with the given parent classloader and cache dierctory @@ -38,6 +40,7 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa */ public AndroidClassLoader(ClassLoader parent, File dir) { this.parent = parent; + mCacheDir = dir; dx = new ArrayList<>(); dexFile = new File(dir, "dex-" + hashCode() + ".jar"); odexOatFile = new File(dir, "odex_oat-" + hashCode() + ".tmp"); @@ -56,8 +59,8 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa parameters.setFileNameInZip(name.replace('.', '/') + ".class"); parameters.setSourceExternalStream(true); zipFile.addStream(new ByteArrayInputStream(data), parameters); - return dexJar().loadClass(name, parent); - } catch (IOException | ZipException e) { + return dexJar().loadClass(name); + } catch (IOException | ZipException | ClassNotFoundException e) { throw new FatalLoadingException(e); } finally { dexFile.delete(); @@ -87,7 +90,13 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa } } - private DexFile dexJar() throws IOException { + public DexClassLoader loadDex(File file) throws IOException { + DexClassLoader loader = new DexClassLoader(file.getPath(), mCacheDir.getPath(), null, parent); + dx.add(loader); + return loader; + } + + private DexClassLoader dexJar() throws IOException { if (!classFile.exists()) { classFile.createNewFile(); } @@ -96,9 +105,7 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa arguments.outName = dexFile.getPath(); arguments.jarOutput = true; Main.run(arguments); - DexFile dex = DexFile.loadDex(dexFile.getPath(), odexOatFile.getPath(), 0); - dx.add(dex); - return dex; + return loadDex(dexFile); } /** @@ -124,8 +131,8 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa throws ClassNotFoundException { Class loadedClass = findLoadedClass(name); if (loadedClass == null) { - for (DexFile dex : dx) { - loadedClass = dex.loadClass(name, parent); + for (DexClassLoader dex : dx) { + loadedClass = dex.loadClass(name); if (loadedClass != null) { break; } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java index b90069d5..d8ef9979 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java @@ -332,6 +332,14 @@ public class ScriptRuntime { } } + public void loadDex(String path){ + try { + ((AndroidClassLoader) ContextFactory.getGlobal().getApplicationClassLoader()).loadDex(new File(path)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void exit() { mThread.interrupt(); if (Looper.myLooper() != Looper.getMainLooper()) {