最近这个版本需要降低APK的大小, 所以很多功能需要从主APK中移除到插件中,除了相关工程的代码,还有Assets、Libs、Resources都需要移动到插件中,而在插件拆分的过程中也遇到了很多问题,需要记录一下。
通常我们通过来获取字符串:
getResources().getString(R.string.about);
传入的R.string.about
是一个int
类型的值,是AAPT打包时为每个资源文件分配的唯一的ID。在Resources
类中,所有获取资源名称、资源包名、资源ID等等的方式都是通过AssetsManager
对象来获取的。
而从官网中,我们也能知道完整的资源名包含三个部分,而ID对应的也是这三部分:
通过这三个信息结合,就能唯一标志一个资源了。
在AAPT打包的过程中会将res中除了raw和assets之外的资源(如layout、string、drawable等等)打成二进制文件,并且生成R.java
以及resources.arsc
这两个文件。
R.java
中存放着各个Type对应的id:
public static int Base_Widget_AppCompat_ImageButton = 0x7f16008b;
其中: 前两位代表包:0x7f 后两位代表类型:16 最后四位代表id:008B
而在resources.arsc
中,则保存着这APK的包名,以及资源的映射表。通过Android Studio中可以打开这个文件:
Resources.arsc
在AAPT打包的时候,默认的包都是0x7f,而且Type都是固定的。
一般通过Resource.getIdentifier
来获取资源名称对应的ID。
/**
* Retrieve the resource identifier for the given resource name.
*/
/*package*/ native final int getResourceIdentifier(String name,
String defType,
String defPackage);
如果包名错误,类型错误的话,则无法找到资源,会返回id为0
。通过Name,Type,DefaultPakcage组成的资源字符串为:
// package/type:name
com.pakcage.test/string:resource_name
在AssetManager中查找资源Id的过程:
AssetsPath
路径resources.arsc
资源表,匹配资源表中的包名在标准的Gradle打包中,R.java是不会被修改成常量的,对于资源的引用还是会保持R.string.about
,而不会使用常量的0x7f
来替换。
插件资源路径,也就是插件APK的路径
当使用插件,并且资源外置在插件APK中的时候,需要完成以下事情:
AssetManager
中,以便AssetsManager
可以找到资源路径解决方案有多种: