U8SDK——打包工具资源合并原理

作者: 分类: U8SDK 发布时间: 2018-08-31 21:05 6U8SDK——打包工具资源合并原理已关闭评论

最近终于闲下来重构了U8SDK中资源合并的逻辑。 随着U8SDK的使用者越来越多,通过U8SDK来打包的游戏也越来越多。这些同学在使用打包工具过程中,有时候会遇到资源冲突,从而导致打包失败。

国内的游戏开发基本都用u3d,cocos2dx等引擎,游戏母包中真正的Android资源目录下的原生资源其实并不多。但是U8SDK除了让游戏快速接入渠道SDK之外,还可以接入各种第三方和游戏业务相关的功能性插件。当将渠道SDK,各种需要的插件都打入一个包时, 我们就可能会遇到资源冲突的情况。

由此可知,U8SDK打包工具在打一个渠道包的时候,需要合并三种资源——母包资源,渠道SDK资源,和配置的所有第三方插件的资源。

之前的版本,U8SDK打包工具中会对values下面的资源文件进行一个简单的查重和合并处理。 比如母包values下面有一个strings.xml文件, 渠道SDK的values下面也有一个strings.xml文件, 那么这两个文件内容将会被合并并排重。

但是我们知道,values下面资源文件名称其实并没有严格的限制,比如u8_strings.xml也是一个正确的string类型的资源文件。 那么母包里面如果有u8_strings.xml这个文件,里面定义了一个u8_txt字符串。打某个渠道包的时候, 这个渠道SDK里面有一个strings.xml,里面也定义了一个u8_txt字符串。 这个时候, 按照上面的默认处理,打包工具在编译资源的时候,会提示资源重复的错误。

那么我们能不能正确地来合并这些资源呢? 或者说,让打包工具能够在95%以上的情形下都能正确地合并资源呢?

做到这个其实并不难,但是我们先要熟悉一下Android中资源的种类,以及哪些情况下的资源算是冲突的。

Android中资源种类有很多, 比如string,color,dimen,drawable等等。 不过对于我们这个需求来说, 我们只需要知道, Android里面的资源可以分为两大类: “values里面的”“values外面的”。注意下,”values里面的”是泛指,他其实还有很多变体, 比如values-port, values-sw320dp-land等等,所有这些都属于”values里面的”。

基于上面的定义, 我们可以得出资源合并的处理规则:

1、”values里面的”资源是需要合并的,比如strings,dimens,colors,integers等资源文件。

2、”values外面的”资源是直接覆盖的。 比如drawable,layout,anim等资源目录下的文件。

有了规则, 我们还需要定义一个优先级。 多个不同资源目录下的资源进行合并, 当有资源冲突的时候, 我们需要知道留下哪个。 如上面提到的, 我们这里主要有三种资源——母包资源,渠道SDK资源,以及第三方插件资源。 那么我们定义的资源优先级是, 母包资源优先级 > 渠道SDK资源优先级 > 插件资源优先级。 所以资源合并的时候, 当渠道SDK资源和母包中的资源出现冲突时, 我们会舍弃渠道SDK里面的资源,留下母包中的资源。

定义好了优先级,我们来细化上面那两条处理规则。第二条规则很简单, 这些资源目录下的文件,都是最小合并个体。 也就是当母包drawable下面有一个ic_close.png, 渠道SDK资源drawable下面也有一个ic_close.png, 那么最终apk中会留下母包中的ic_close.png。 所以”values外面的”资源文件不存在合并, 只需要覆盖或者舍弃即可。

res_merger_single_file

 

我们重点来看第一条规则, 也就是怎么来合并”values里面的”资源文件。”values里面的”资源文件有不同种类,文件名称无要求, 都是xml文件,内容格式比较固定。values中的资源,最小合并个体为具体的配置项。比如strings.xml和tx_strings.xml两个文件,我们在合并的时候, 先读取出这两个文件中所有的配置项,然后逐条对比。 如果两个配置项的name一致,那么我们就根据优先级舍其一。

res_merger_values

 

但是如上面提到的, values下面的资源文件并没有固定的名称, 所以我们以目录为单位来做合并处理。 我们先将每个values目录下的所有资源文件中的配置项都读取出来,然后相同类型的资源,根据name来判断是否冲突, 如果冲突,就根据优先级来舍掉。

这么一分析, 其实资源合并的逻辑还是挺简单的, 但是我们也别忘了,values下面还有一种特殊的资源——styleable或者叫declare-styleable。 这类资源, 如果存在同名的资源,我们可能并不能简单的舍弃如此简单了, 而是需要将两个同名的styleable资源合二为一。 同时,styleable中的子配置项attr也可以引用全局配置attr。 所以针对这个情况,我们也需要注意下, 不能将两个attr类型的资源配置项简单的查重之后直接舍弃。当然了,这个只是其中的一种特殊情况。

res_merger_styleable

有了上面的思路,我们就可以大概设计一下我们的组件, 如下图所示。 这里就不贴代码了,有兴趣的同学,可以看U8SDK打包工具源码中的res_merger.py文件。为了了解Android资源合并的原理同时为了避免资源合并遗漏的情形,代码中部分设计和合并过程参考了Android Studio中对于资源合并的处理方式。

 

res_merger_class

 

本文出自 U8SDK技术博客,转载时请注明出处及相应链接。

本文永久链接: http://www.uustory.com/?p=2228

评论功能已经关闭,请加入U8SDK技术群进行讨论和咨询:207609068
Ɣ回顶部
U8SDK技术群 x
技术同学请加入
点击加入