插件化方案
2020-05-20 本文已影响0人
拿拿guardian
一、将插件化内容打包成apk,放在宿主APP的assert目录下。
二、app启动时,动态加载插件apk的内容:
- 将插件apk复制到/data/user/0/packagename/app_apk 目录下
- 用DexClassLoader从插件apk的提取dex文件,保存在/data/user/0/packagename/app_dex目录
private DexClassLoader createDexClassLoader(String pluginName) {
boolean saved = savePluginApkToStorage(pluginName);
if(!saved) {
return null;
}
DTLog.d(TAG, "createDexClassLoader pluginName = " + pluginName);
DexClassLoader classLoader = null;
try {
String apkPath = this.getPlguinApkDirectory() + pluginName;
File dexOutputDir = DTApplication.getInstance().getDir("dex", 0);
String dexOutputDirPath = dexOutputDir.getAbsolutePath();
Log.d(TAG, " apkPath = " + apkPath + " dexOutputPath = " + dexOutputDirPath);
ApplicationInfo ai = DTApplication.getInstance().getApplicationInfo();
String nativeLibraryDir = null;
if (Build.VERSION.SDK_INT > 8) {
nativeLibraryDir = ai.nativeLibraryDir;
} else {
nativeLibraryDir = "/data/data/" + ai.packageName + "/lib/";
}
DTLog.d(TAG, " native library path = " + nativeLibraryDir);
ClassLoader cl = DTApplication.getInstance().getClassLoader();
DTLog.d(TAG, " get parent class loader = " + cl.getParent());
classLoader = new DexClassLoader(apkPath, dexOutputDirPath, nativeLibraryDir,
cl);
Log.d(TAG, "after new class loader classLoader = " + classLoader.toString());
}catch(Throwable e) {
//Assert.assertTrue("LoadPluginApk e=" + ExceptionUtils.getStackTrace(e), false);
//DTLog.e(TAG, "loadPluginApk exception = " + ExceptionUtils.getStackTrace(e));
}
DTLog.d(TAG, "End load apk");
return classLoader;
}
三、将步骤二中生成的DexClassLoader实例保存下来,代码运行时用到插件apk的内容时,直接用保存下来的DexClassLoader实例去加载相关class文件:
public Object newInstance(String className) {
if(mDexClassLoader == null) {
return null;
}
try {
Class<?> clazz = mDexClassLoader.loadClass(className);
Object instance = clazz.newInstance();
return instance;
} catch (Exception e) {
DTLog.e(TAG, "newInstance className = " + className + " failed" + " exception = " + e.getMessage());
}
return null;
}