Cargar el archivo DEX dinámicamente en Android 5.0
Antes de Android 5.0 podía cargar archivos de DEX dinámicamente usando DexClassLoader y llamando el método de loadClass()
pero con la última versión de Androide obtengo un ClassNotFoundException
.
Esto es lo que estoy haciendo:
-
Generar archivo DEX.
../android-sdk/android-sdk-linux_86/build-tools/21.1.1/dx --dex --output=bin/output.dex bin/output.jar
-
Cree un DexClassLoader.
DexClassLoader cl = new DexClassLoader( dexFile.getAbsolutePath(), odexFile.getAbsolutePath(), null, mContext.getClassLoader());
-
Llame a
cl.loadClass("myMethod");
Soy consciente de que ART utiliza dex2oat para generar un archivo ELF que es el cargado por ART pero en el paso 2 estoy generando un archivo ODEX así que no soy lo que hay que hacer en ART para cargar un archivo DEX en tiempo de ejecución, yo ?
One Solution collect form web for “Cargar el archivo DEX dinámicamente en Android 5.0”
Actualizar
Esto funciona tanto en Dalvik como en ART: new DexClassLoader(jarredDex.getAbsolutePath(), context.getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), null, context.getClassLoader());
Donde jarredDex
es un archivo jar con classes.dex
. Jar se puede obtener ejecutando dx --dex --output=filename.jar your/classes/dir
.
Respuesta original
He tomado un ejemplo de código de este artículo . Pero ART utiliza PathClassLoader
lugar de PathClassLoader
de Dalvik. Este código se prueba en el emulador con Android 6 y en Xiaomi con Android 5.1 y funciona bien:
// Before the secondary dex file can be processed by the DexClassLoader, // it has to be first copied from asset resource to a storage location. File dexInternalStoragePath = new File(getDir("dex", Context.MODE_PRIVATE), SECONDARY_DEX_NAME); try (BufferedInputStream bis = new BufferedInputStream(getAssets().open(SECONDARY_DEX_NAME)); OutputStream dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath))) { byte[] buf = new byte[BUF_SIZE]; int len; while((len = bis.read(buf, 0, BUF_SIZE)) > 0) { dexWriter.write(buf, 0, len); } } catch (IOException e) { throw new RuntimeException(e); } try { PathClassLoader loader = new PathClassLoader(dexInternalStoragePath.getAbsolutePath(), getClassLoader()); Class<?> toasterClass = loader.loadClass("my.package.ToasterImpl"); Toaster toaster = (Toaster) toasterClass.newInstance(); toaster.show(this, "Success!"); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); }