import android.app.AppComponentFactory; import android.content.pm.ApplicationInfo; import android.util.Log; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipFile; import dalvik.system.InMemoryDexClassLoader; public class InMemoryDexClassLoaderFactory extends AppComponentFactory { private static ClassLoader classLoader; private static void readDexes(ZipFile apkFile, List dexFiles) throws IOException { int secondary = 2; for (var dexFile = apkFile.getEntry("classes.dex"); dexFile != null; dexFile = apkFile.getEntry("classes" + secondary + ".dex"), secondary++) { var in = apkFile.getInputStream(dexFile); var byteBuffer = ByteBuffer.allocate(in.available()); byteBuffer.mark(); Channels.newChannel(in).read(byteBuffer); byteBuffer.reset(); dexFiles.add(byteBuffer); } } @Override public ClassLoader instantiateClassLoader(ClassLoader cl, ApplicationInfo aInfo) { if (classLoader != null) return classLoader; var buffers = new ArrayList(); try (var zipFile = new ZipFile(aInfo.sourceDir)) { readDexes(zipFile, buffers); } catch (IOException e) { Log.e(App.TAG, "Can not load " + aInfo.sourceDir, e); return cl; } var dexfiles = new ByteBuffer[buffers.size()]; buffers.toArray(dexfiles); classLoader = new InMemoryDexClassLoader(dexfiles, aInfo.nativeLibraryDir, cl.getParent()); return classLoader; } }