Android插件化基础之加载未安装的apk资源


邮箱:[email protected]


这里废话一句,我没有将太多的原理和分析,我这里就写了核心的代码.
知其然而后知其所以然这是我认为更好理解的方式

下面说一下如何加载没有安装apk的资源文件

问题出来了我们就要去思考怎么去解决,首先加载资源我们需要什么
Context.getResource().getXxx();
从这里我们就看到了思路,首先我们我们应该清楚一点,应为apk没有安装,所以肯定不会存在Context这个东西,那么我们就要找到另一个东西Resource.这就是我们的突破口.

怎么拿到Resource呢?

这就是我们突破口了

经过查看源码我们发现Resources是可以new的,并且我们找到了一个已经废弃的方法(可以用就可以暂时这么解决),那我们来看一下源码

@Deprecated
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
    this(null);
    mResourcesImpl = new ResourcesImpl(assets, metrics, config, new DisplayAdjustments());
}

关于参数我来简单说一下

  1. 先说后面两个,这两个参数都是关于们我们手机平台配置的,我们直接使用当前的设置就是可以的,直接用当前的Resource来获取就可以
  2. 再来说一下第一个参数,第一个参数指的并不是当前AssetManager的实例,而是我们需要访问资源的apk的AssetManager的实例.并且我们需要将资源apk的位置通过addAssetPath(assetManager,path)将我们要加载apk位置设置进去

先来解决第一个参数AssetManager的实例化,点击去看源码,我们发现没有办法new出来,那怎么办?

AssetManager assetManager = AssetManager.class.newInstance();

这样子我们可以拿到一个实例对象,但是这还没有结束,我们还需要设置一些参数,但是方法是私有的我们只能使用反射来进行设置

Method addAssetPath = assetManager.getClass().getMethod("addAssetPath",String.class);
addAssetPath.invoke(assetManager,path);

在上面我们已经拿到了我们需要的参数和实例化对象,之后我们就可以继续我们的操作了

Resources superRes = this.getResources();
Resources mRes = new Resources(assetManager,superRes.getDisplayMetrics(),superRes.getConfiguration());

在这个之后我们就需要将apk的给解析出来,并且拿到他的资源的字节码文件

//解析apk
File dexFile = getDir("dex", Context.MODE_PRIVATE);
DexClassLoader dexClassLoader = new DexClassLoader(apk.getPath(),dexFile.getPath(),null,ClassLoader.getSystemClassLoader());
Class<?> clazz = dexClassLoader.loadClass(info[1] + ".R$drawable");
Field about = clazz.getDeclaredField("ic_launcher");
int anInt = about.getInt(R.id.class);
//设置相应的资源
Drawable drawable = mRes.getDrawable(anInt);
src.setImageDrawable(drawable);

代码里面的apk就是下载之后的File,如何下载之类的我这里就不说了,想简单点的可以使用assets来做

完成上面的步骤就可以运行看看了,看到效果之后再去研究原理我觉得会更加容易一些

这里说一下ClassLoader,Android有两种PathClassLoader和DexClassLoader前者是用来接在已经安装的apk资源的,而后者则是用来加载没有安装的apk的

https://www.ibm.com/developerworks/cn/java/j-lo-classloader/java类加载器的解析,这里可以做一下了解

经过上述为数不多的代码就可以加载出来没有安装的apk的资源文件.
当然上面的代码就是一个初步的学习

有什么问题可以直接提问,一起研究和探讨

猜你喜欢

转载自blog.csdn.net/xiangnicao/article/details/71703445