开发Android的朋友都知道每个资源都有一个唯一的 ID,是个常量,在打包成apk的时候就已经固定了的。但是工具 apktool 在重新打包 apk 的时候会对资源重新编译 ,编译资源的时候自然需要对所有资源ID进行重新编排,这是一个随机的过程。试想假设原包里面 drawable/a.png id=0x7f020003, 那么重新编排资源ID后就可能是 0x7f020004。又假设原包 0x7f020004 对应图片 b.png,那你重新打包后的 apk 当显示 a.png 的时候就会替换成 b.png,这还好不会出错,倘若生成的一个 id 原包不存在,那会导致程序崩溃的!

到这里,为了解决这个问题,public.xml就派上用场了,它的作用就是固定资源R的ID值。

平时应用开发时候基本看不到这个文件,只有使用apktool后,在 res/values/目录下会自动生成一个 public.xml文件,里边的值就与R文件、资源相关。

在 framework 开发时候,遇到一些资源要固定 ID,就可以用 /frameworksbase/core/res/res/values/public.xml 这个文件的特性来处理。

我们用个 style 做为例子来看看具体怎么操作的。

我们先定义一个 Dialog 样式,在文件 /frameworks/base/core/res/res/values/styles.xml</resources> 标签之前添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- LXB PATCH BEGIN -->
<style name="YGTV.Translucent.NoTitle.Dialog" parent="@style/Theme.Dialog">
<item name="android:windowFrame">@null</item> <!--Dialog的windowFrame框为无-->
<item name="android:windowIsFloating">true</item> <!--是否浮现在activity之上-->
<item name="android:windowIsTranslucent">true</item> <!--是否半透明-->
<item name="android:windowNoTitle">true</item> <!--是否显示title-->
<item name="android:background">@color/transparent</item> <!--设置dialog的背景-->
<item name="android:windowBackground">@color/transparent</item>
<!--就是用来控制灰度的值,当为1时,界面除了我们的dialog内容是高亮显示的,dialog以外的区域是黑色的,完全看不到其他内容-->
<item name="android:backgroundDimAmount">0.7</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
<!-- LXB PATCH END -->

然后,找到配置文件 /frameworks/base/core/res/res/values/public.xml,在里边找分组配置 <public-group type="style" first-id="0x010302e2">...</public-group>,把我们新加的资源配置进去,像下边的:

1
2
3
4
5
6
7
 <public-group type="style" first-id="0x010302e2">
......
<!-- LXB PATCH START -->
<public name="YGTV.Translucent.NoTitle.Dialog" />
<!-- LXB PATCH END -->
......
</public-group>

这里需要注意一点,public.xml 文件中各种资源类型都可以添加,有单独添加的,也有分组添加的,但有个规则需要注意 – ID 编码规则。

大家看已有的配置就可以看出来,这个文件内的 id 都是以 0x01 开头的,然后是不同类型 attr:01,id:02,style:03,dimen:05,drawable:08 等等,然后后边的4位是从 0000 开始的,虽然不知道什么意思,也没找到文档说明,但建议也尽量遵循吧。如果自己单个加觉得不方便,那就找对应的分组,分组有 first-id,里边添加的就在这个ID基础上自动+1了。

处理完上边的,我们自定义的这个 Dialog 样式的 ID 就固定了,可以引用、尝试打包不同的apk看看对应的值是不是一样的。