<未完成,待续>
获取未安装 apk (插件)的 Resource
因为没有安装,所以不能得到 context,所以我们需要未安装 apk 的 Resource,我们可以通过反射来获取,代码如下
/**
* @param apkPath
* @return 得到对应插件的Resource对象
*/
private Resources getPluginResources(String apkPath) {
try {
AssetManager assetManager = AssetManager.class.newInstance();
//反射调用方法addAssetPath(String path)
Method addAssetPath = assetManager.getClass().getMethod(ADDSSETPATH, String.class);
//将未安装的Apk文件的添加进AssetManager中,第二个参数是apk的路径
addAssetPath.invoke(assetManager, apkPath);
Resources superRes = this.getResources();
Resources mResources = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());
return mResources;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
用DexClassLoader加载apk资源文件替换背景
/**
* 加载apk获得内部资源,并且替换背景
* @param apkDir apk目录
* @param apkName apk名字,带.apk
* @throws Exception
*/
private void dynamicLoadApk(String apkPath, String apkPackageName) throws Exception {
//在应用安装目录下创建一个名为app_dex文件夹目录,如果已经存在则不创建,这个目录主要是最优化目录,用于缓存dex文件
File optimizedDirectoryFile = getDir(DEX, Context.MODE_PRIVATE);
//打印路径 理论上是/data/data/package/app_dex
Log.v(TAG, optimizedDirectoryFile.getPath().toString());
//构建DexClassLoader
DexClassLoader dexClassLoader = new DexClassLoader(apkPath, optimizedDirectoryFile.getPath(), null, ClassLoader.getSystemClassLoader());
//通过使用apk自己的类加载器,反射出R类中相应的内部类进而获取我们需要的资源id
Class<?> clazz = dexClassLoader.loadClass(apkPackageName + DRAWABLE);
//得到名为about_log的这张图片字段,这个图片是为安装apk里面的图片
Field field = clazz.getDeclaredField(IMAGE_ID);
//得到图片id
int resId = field.getInt(R.id.class);
//得到插件apk中的Resource
Resources mResources = getPluginResources(apkPath);
if (mResources != null) {
//通过插件apk中的Resource得到resId对应的资源
Drawable btnDrawable = mResources.getDrawable(resId);
mLayout.setBackgroundDrawable(btnDrawable);
} else {
Log.d(TAG, "mResources is null");
}
}
reference:
Android插件化开发之用DexClassLoader加载未安装的APK资源文件来实现app切换背景皮肤
网友评论