前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android的打包过程与资源分配

Android的打包过程与资源分配

作者头像
None_Ling
发布2018-12-21 09:56:02
9880
发布2018-12-21 09:56:02
举报
文章被收录于专栏:Android相关

背景

最近这个版本需要降低APK的大小, 所以很多功能需要从主APK中移除到插件中,除了相关工程的代码,还有Assets、Libs、Resources都需要移动到插件中,而在插件拆分的过程中也遇到了很多问题,需要记录一下。

资源标志

通常我们通过来获取字符串:

代码语言:javascript
复制
getResources().getString(R.string.about);

传入的R.string.about是一个int类型的值,是AAPT打包时为每个资源文件分配的唯一的ID。在Resources类中,所有获取资源名称、资源包名、资源ID等等的方式都是通过AssetsManager对象来获取的。

而从官网中,我们也能知道完整的资源名包含三个部分,而ID对应的也是这三部分:

  • Package:App或者插件Apk的包名
  • Type:Dimen、Style、Attr、String、Anim等等
  • Name:资源名称

通过这三个信息结合,就能唯一标志一个资源了。

AAPT打包机制

在AAPT打包的过程中会将res中除了raw和assets之外的资源(如layout、string、drawable等等)打成二进制文件,并且生成R.java以及resources.arsc这两个文件。

R.java中存放着各个Type对应的id:

代码语言:javascript
复制
 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。

代码语言:javascript
复制
    /**
     * 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组成的资源字符串为:

代码语言:javascript
复制
// package/type:name
com.pakcage.test/string:resource_name

在AssetManager中查找资源Id的过程:

  1. 遍历已经添加的AssetsPath路径
  2. 根据对应的AssetsPath路径中查找resources.arsc资源表,匹配资源表中的包名
  3. 匹配到后,根据Type来找到对应的资源类型表
  4. 在资源Type表中匹配Name,找到ID

在标准的Gradle打包中,R.java是不会被修改成常量的,对于资源的引用还是会保持R.string.about,而不会使用常量的0x7f来替换。

插件资源路径,也就是插件APK的路径

插件方案

当使用插件,并且资源外置在插件APK中的时候,需要完成以下事情:

  1. 将插件APK的所在路径添加到AssetManager中,以便AssetsManager可以找到资源路径
  2. 需要将插件中所使用的资源ID按不同插件的包名进行区分,因为AAPT默认会从0x7f开始进行分配

解决方案有多种:

  1. 修改aapt,为插件分配不同的pakcageId,然后将引用R.id的地方修改为常量
  2. 修改aapt过后的R.java文件,合并多个插件的R.java文件,并且重新分配R.java中的id常量,并且重写resources.arsc文件

遇到的问题

  1. 由于在Manifest.xml中定义的Activity最后还是会merge到主包的Manifest.xml中,所以对于Manifest.xml中引用的string、style、theme等等如果不在主包的话,打包会不通过。
  2. 在插件的Activity中使用资源的时候需要小心:
    • 保证getResource中的Resource是已经添加过插件资源路径的
    • 保证资源调用时,Package与Id能够匹配上
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.11.30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 资源标志
    • AAPT打包机制
      • 资源查找过程
        • 插件方案
          • 遇到的问题
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档