diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index b9831b27..99f3a510 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/build.gradle b/app/build.gradle index 328eb710..7e978328 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { applicationId "org.autojs.autojs" minSdkVersion versions.mini targetSdkVersion versions.target - versionCode 423 - versionName "4.0.3 Alpha4" + versionCode versions.appVersionCode + versionName versions.appVersionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true ndk { 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 4538c348..0548a4bb 100644 --- a/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java +++ b/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java @@ -3,7 +3,8 @@ package com.stardust.autojs.rhino; import android.util.Log; import com.android.dx.command.dexer.Main; -import com.android.dx.dex.file.DexFile; +import com.stardust.pio.PFiles; +import com.stardust.util.MD5; import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.exception.ZipException; @@ -16,6 +17,7 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; @@ -42,7 +44,11 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa public AndroidClassLoader(ClassLoader parent, File dir) { this.parent = parent; mCacheDir = dir; - dir.mkdirs(); + if (dir.exists()) { + PFiles.deleteFilesOfDir(dir); + } else { + dir.mkdirs(); + } } /** @@ -53,13 +59,13 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa Log.d(LOG_TAG, "defineClass: name = " + name + " data.length = " + data.length); File classFile = null; try { - classFile = generateTempClassFile(name, false); + classFile = generateTempFile(name, false); final ZipFile zipFile = new ZipFile(classFile); final ZipParameters parameters = new ZipParameters(); parameters.setFileNameInZip(name.replace('.', '/') + ".class"); parameters.setSourceExternalStream(true); zipFile.addStream(new ByteArrayInputStream(data), parameters); - return dexJar(classFile).loadClass(name); + return dexJar(classFile, null).loadClass(name); } catch (IOException | ZipException | ClassNotFoundException e) { throw new FatalLoadingException(e); } finally { @@ -69,7 +75,7 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa } } - private File generateTempClassFile(String name, boolean create) throws IOException { + private File generateTempFile(String name, boolean create) throws IOException { File file = new File(mCacheDir, name.hashCode() + System.currentTimeMillis() + ".jar"); if (create) { if (!file.exists()) { @@ -83,8 +89,16 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa public void loadJar(File jar) throws IOException { Log.d(LOG_TAG, "loadJar: jar = " + jar); + if (!jar.exists() || !jar.canRead()) { + throw new FileNotFoundException("File does not exist or readable: " + jar.getPath()); + } + File dexFile = new File(mCacheDir, generateDexFileName(jar)); + if (dexFile.exists()) { + loadDex(dexFile); + return; + } try { - final File classFile = generateTempClassFile(jar.getPath(), false); + final File classFile = generateTempFile(jar.getPath(), false); final ZipFile zipFile = new ZipFile(classFile); final ZipFile jarFile = new ZipFile(jar); //noinspection unchecked @@ -96,12 +110,22 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa zipFile.addStream(jarFile.getInputStream(header), parameters); } } - dexJar(classFile); + dexJar(classFile, dexFile); + classFile.delete(); } catch (ZipException e) { throw new IOException(e); } } + private String generateDexFileName(File jar) { + String message = jar.getPath() + "_" + jar.lastModified(); + try { + return MD5.md5(message); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + public DexClassLoader loadDex(File file) throws FileNotFoundException { Log.d(LOG_TAG, "loadDex: file = " + file); if (!file.exists()) { @@ -112,15 +136,20 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa return loader; } - private DexClassLoader dexJar(File classFile) throws IOException { + private DexClassLoader dexJar(File classFile, File dexFile) throws IOException { final Main.Arguments arguments = new Main.Arguments(); arguments.fileNames = new String[]{classFile.getPath()}; - File dexFile = generateTempClassFile("dex-" + classFile.getPath(), true); + boolean isTmpDex = dexFile == null; + if (isTmpDex) { + dexFile = generateTempFile("dex-" + classFile.getPath(), true); + } arguments.outName = dexFile.getPath(); arguments.jarOutput = true; Main.run(arguments); DexClassLoader loader = loadDex(dexFile); - dexFile.delete(); + if (isTmpDex) { + dexFile.delete(); + } return loader; } diff --git a/build.gradle b/build.gradle index 98210af6..ae5f3c13 100644 --- a/build.gradle +++ b/build.gradle @@ -28,9 +28,11 @@ task clean(type: Delete) { ext { versions = [ - target: 28, - mini: 17, - compile: 28, - buildTool: '28.0.3' + appVersionCode: 423, + appVersionName: '4.0.3 Alpha4', + target : 28, + mini : 17, + compile : 28, + buildTool : '28.0.3' ] } diff --git a/common/src/main/java/com/stardust/pio/PFiles.java b/common/src/main/java/com/stardust/pio/PFiles.java index 5f2dfc2b..b304b98a 100644 --- a/common/src/main/java/com/stardust/pio/PFiles.java +++ b/common/src/main/java/com/stardust/pio/PFiles.java @@ -395,6 +395,19 @@ public class PFiles { return file.delete(); } + public static boolean deleteFilesOfDir(File dir) { + if (!dir.isDirectory()) + throw new IllegalArgumentException("not a directory: " + dir); + File[] children = dir.listFiles(); + if (children != null) { + for (File child : children) { + if (!deleteRecursively(child)) + return false; + } + } + return true; + } + public static boolean remove(String path) { return new File(path).delete(); } diff --git a/common/src/main/java/com/stardust/util/MD5.java b/common/src/main/java/com/stardust/util/MD5.java new file mode 100644 index 00000000..824a37b7 --- /dev/null +++ b/common/src/main/java/com/stardust/util/MD5.java @@ -0,0 +1,26 @@ +package com.stardust.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class MD5 { + + public static byte[] md5Bytes(String message) throws NoSuchAlgorithmException { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(message.getBytes()); + return md5.digest(); + } + + public static String md5(String message) throws NoSuchAlgorithmException { + byte[] bytes = md5Bytes(message); + StringBuilder hexString = new StringBuilder(32); + for (byte b : bytes) { + String hex = Integer.toHexString(0xFF & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} diff --git a/inrt/build.gradle b/inrt/build.gradle index a4f6d49f..98285bbc 100644 --- a/inrt/build.gradle +++ b/inrt/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.stardust.auojs.inrt" minSdkVersion versions.mini targetSdkVersion versions.target - versionCode 210 - versionName "4.0.2 Alpha5" + versionCode versions.appVersionCode - 200 + versionName versions.appVersionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ndk { abiFilters 'armeabi-v7a' diff --git a/inrt/src/main/AndroidManifest.xml b/inrt/src/main/AndroidManifest.xml index 1f081ede..76116e60 100644 --- a/inrt/src/main/AndroidManifest.xml +++ b/inrt/src/main/AndroidManifest.xml @@ -26,7 +26,8 @@ android:label="inrt" android:supportsRtl="true" android:theme="@style/AppTheme" - tools:replace="android:label, android:allowBackup"> + tools:replace="android:label, android:allowBackup" + tools:ignore="GoogleAppIndexingWarning">