diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4f04e01f3..6b77a97cb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -241,6 +241,8 @@ dependencies /* Unclassified */ { // ICU4J implementation("com.ibm.icu:icu4j:77.1") + + implementation("com.android.tools:r8:8.13.17") } dependencies /* MIME */ { diff --git a/app/src/main/java/org/autojs/autojs/rhino/AndroidClassLoader.kt b/app/src/main/java/org/autojs/autojs/rhino/AndroidClassLoader.kt index b9e2c95d5..7926f4d0c 100644 --- a/app/src/main/java/org/autojs/autojs/rhino/AndroidClassLoader.kt +++ b/app/src/main/java/org/autojs/autojs/rhino/AndroidClassLoader.kt @@ -3,6 +3,10 @@ package org.autojs.autojs.rhino import android.os.Build import android.util.Log import com.android.dx.command.dexer.Main +import com.android.tools.r8.CompilationMode +import com.android.tools.r8.D8 +import com.android.tools.r8.D8Command +import com.android.tools.r8.OutputMode import dalvik.system.DexClassLoader import net.lingala.zip4j.ZipFile import net.lingala.zip4j.exception.ZipException @@ -84,8 +88,18 @@ class AndroidClassLoader(private val parent: ClassLoader, private val cacheDir: } } - @Throws(IOException::class) fun loadJar(file: File): DexClassLoader { + try { + val dexFile = jarToDex(file, cacheDir) + return loadDex(dexFile) + } catch (e: Exception) { + Log.e(TAG, "loadJar: failed to load jar ${file.path}", e) + return loadJar1(file) + } + } + + @Throws(IOException::class) + fun loadJar1(file: File): DexClassLoader { val path = file.path Log.d(TAG, "loadJar: jar = $path") if (!file.exists() || !file.canRead()) { @@ -215,6 +229,39 @@ class AndroidClassLoader(private val parent: ClassLoader, private val cacheDir: private fun generateDexFileName(jar: File) = md5("${jar.path}_${jar.lastModified()}") + private fun jarToDex(jar: File, cacheDir: File): File { + val dexName = generateDexFileName(jar) + val dexFile = File(cacheDir, "$dexName.dex") + if (dexFile.exists()) { + return dexFile + } + val tmpOut = File(cacheDir, "${dexName}_tmp").apply { mkdirs() } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val cmd = D8Command.builder() + .addProgramFiles(jar.toPath()) + .setOutput(tmpOut.toPath(), OutputMode.DexIndexed) + .setMode(CompilationMode.RELEASE) + .build() + D8.run(cmd) + } else { + val args = arrayOf( + "--output", tmpOut.absolutePath, + "--release", + jar.absolutePath + ) + D8.main(args) + } + val classesDex = File(tmpOut, "classes.dex") + if (classesDex.exists().not()) { + throw IOException("R8 did not produce classes.dex") + } + if (classesDex.renameTo(dexFile).not()) { + dexFile.outputStream().use { out -> classesDex.inputStream().use { it.copyTo(out) } } + } + tmpOut.deleteRecursively() + return dexFile + } + companion object { private val TAG = AndroidClassLoader::class.java.simpleName diff --git a/app/src/main/java/org/autojs/autojs/ui/error/ErrorDialogActivity.java b/app/src/main/java/org/autojs/autojs/ui/error/ErrorDialogActivity.java index 13a68b5b7..14f9f3b80 100644 --- a/app/src/main/java/org/autojs/autojs/ui/error/ErrorDialogActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/error/ErrorDialogActivity.java @@ -20,8 +20,8 @@ public class ErrorDialogActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); + super.onCreate(savedInstanceState); // Get extras from intent Intent intent = getIntent();