您的位置:首页 > 移动开发 > Android开发

Android动态加载—Res文件

2016-04-05 21:33 369 查看

简介

动态加载res文件,就是将资源文件打包进一个统一的apk,而在我们的app安装后通过后台下载,然后再写到我们的应用中,将这个含有资源的apk,可以称为插件apk,而我们的app,可以称为宿主apk,在宿主中加载插件中的资源文件的方法。

介绍

下载

加载

获取资源文件

对于下载可以参考上一篇so文件的下载,没什么要说的,加载是从你的sdcard目录下复制到你的应用目录下例如:data/data/包名/app_dex目录下面,代码参考so文件的复制。

将apk复制到指定的目录后,就是获取其里面的资源了,而获取一个应用的资源,我么首先要知道这个资源对应的id是多少,而对于插件来说,它里面的资源id我们是不知道的,但是资源的name确实我们开发者定的,所有我们可以通过资源的name来获取id,方法是系统API : Resources.getIdentifier()

public int getIdentifier(String name, String defType, String defPackage) {
if (name == null) {
throw new NullPointerException("name is null");
}
try {
return Integer.parseInt(name);
} catch (Exception e) {
// Ignore
}
return mAssets.getResourceIdentifier(name, defType, defPackage);
}


好了,拿到了资源id,我们就可以应用到我们需要的地方了。但是,在运行的时候你会发现获取的id是0,这是因为你用的Resources是宿主的resources,在宿主里面并没有找到你name所对应的id。所以,我们还需要创建一个插件所拥有的resources,让app拥有两个resources对象,当加载插件资源的时候用插件的resources

protected void loadResources(File tmpDir) {
try {
File[] currentFiles=tmpDir.listFiles();
String path;
if (currentFiles == null || currentFiles.length == 0) {
path = DuduUtil.resApkPath;
} else {
path = currentFiles[0].getAbsolutePath();
}
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod(
"addAssetPath", String.class);//通过methodName和参数的数据类型得到要执行的Method。
addAssetPath.invoke(assetManager, path);//assetManager对象中带有参数path的addAssetPath方法。返回值是Object,也既是该方法的返回值
mAssetManager = assetManager;
} catch (Exception e) {
e.printStackTrace();
}
Resources superRes = super.getResources();
mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),
superRes.getConfiguration());
}


解释一下反射的两个方法的意思:

getMethod

public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
return getMethod(name, parameterTypes, true);
}


@param name

* the requested method’s name.

* @param parameterTypes

* the parameter types of the requested method.

* {@code (Class[]) null} is equivalent to the empty array.

Method字面理解方法的意思,getMethod参数的意思,name:方法的名字;parameterTypes方法参数的类型,获取assetManager对象里面名字为addAssetPath,参数类似为String的方法,即:

public final int addAssetPath(String path) {
synchronized (this) {
int res = addAssetPathNative(path);
makeStringBlocks(mStringBlocks);
return res;
}
}


invoke

@param receiver
the object on which to call this method (or null for static methods)
@param args
the arguments to the method
public native Object invoke(Object receiver, Object... args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;


invoke字面理解:调用。receiver调用反射处理的method,参数是args

至此,插件apk的resources已经拿到,然后再通过name拿到id,但是拿到id之后并不能直接使用,因为我们之前直接setxxx(id)的时候,实在方法里面转换成了相应的资源,所以,还需要我们把插件的资源转换成向对应的资源

demo:https://github.com/fayou147/DyLoadResDemo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: