Android中R文件ID值

Android中R文件ID值

前言

前端时间在学习 Qigsaw 相关的源码,思考到一个问题。动态加载的feature 包里的 资源id 是否会与主包中的 资源id 冲突。因为主包的 apk 文件不一定是和加载的feature 包是一起打包生成的,feature 包是可以进行升级的。查看 Qigsaw编译脚本对 old.apk 进行增量编译 feature 的时候也没有发现对 R文件 做特殊的处理。

那么 Android 怎么保证两次编译出的 feature 包中的 资源id 不与主包中的冲突呢?我们带着问题阅读文章进行答案的探索(Android中资源属于一个大模块,我们本地只讨论其中与R文件相关的部分)。

  • 不同的 android-gradle 版本可能对 R文件 的格式以及生成目录会略作修改,本文只选了两个版本做参考。
  • 同步的反编译工具反编译出来的结果不仅相关,我们主要以 AndroidStudio 结果为主。

知识回顾

在代码中访问资源

您可以以方法参数的形式传递资源 ID,进而在代码中使用资源。例如,您可以设置一个 ImageView,从而借助 setImageResource() 使用 res/drawable/myimage.png 资源:

ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(R.drawable.myimage);

您还可利用 Resources 中的方法检索个别资源,并且您可通过 getResources() 获得该资源的实例。

语法

以下是在代码中引用资源的语法:

[<package_name>.]R.<resource_type>.<resource_name>
  • <package_name> 是资源所在包的名称(如果引用的资源来自您自己的资源包,则不需要)。
  • <resource_type> 是资源类型的 R 子类。
  • <resource_name> 是不带扩展名的资源文件名,或 XML 元素中的 android:name 属性值(若资源是简单值)。

其实到这里我们已经解决了我们阅读本文的目的。

主包的 资源文件IDfeature 包的 资源文件ID 值是由于 <package_name> 不一致导致最后 ID 值不会相同。

有时间的小伙伴可以继续往下阅读,后面更精彩。

R文件

主工程R文件结构

R.png

插件的R文件结构

Qigsaw-feature-R.png

R文件中每个资源ID值一共4个字段,由三部分组成:PackageId+TypeId+EntryId

  • PackageId:是包的Id值,Android 中如果第三方应用的话,这个默认值是 0x70 ,系统应用的话就是 0x01 ,插件的话那么就是给插件分配的id值,占用一个字节。
  • TypeId: 是资源的类型Id值,一般 Android 中有这几个类型:attrdrawablelayoutanimrawdimenstringboolstyleintegerarraycoloridmenu 等。【应用程序所有模块中的资源类型名称,按照字母排序之后。值是从1开支逐渐递增的,而且顺序不能改变(每个模块下的R文件的相同资源类型id值相同)。比如:anim=0x01占用1个字节,那么在这个编译出的所有R文件中anim 的值都是 0x01
  • EntryId:是在具体的类型下资源实例的id值,从0开始,依次递增,他占用四个字节。

Lib库的R文件

com.android.tools.build:gradle:3.2.0

releasePath :/build/generated/not_namespaced_r_class_sources_release_generateReleaseRFile/out/R.java (Debug包与其对应)

3.2.0-module-lib-r.png

com.android.tools.build:gradle:3.4.1

debugPath :/build/intermediates/complile_only_not_namespaced_r_class_jar_debug_generateDebugRFile/R.jar (Release包与其对应)

3.4.1-module-lib-r.png

我们可以看到 Lib 中的 R 文件都是 public static 不是常量。 这和我们刚开始查看的 主工程 以及 插件R文件 相比缺少了 final 关键词的修饰。

Lib 库中资源id 的使用为引用类型;

module-lib-r-source-layout.png

(PS:至于资源ID为什么不是常量,使用为引用类型,我们继续往后看~!)

AAR中的R文件

AAR-R.png

我们可以看到打包了的 Lib/Modulearr包 之后,我们是找不到 R.java 文件的。只有一个 R.txt

aar 依赖库中资源id 的使用为引用类型;

module-lib-r-jar-layout.png

依赖库R文件的生成

  • 源码依赖的 Lib 库的 R 文件中的 ID 不是常量;
  • aar 依赖的 Lib 库的R 文件是 .txt 文件;
  • 源码依赖的 Lib 库和 aar 依赖的 Lib 库中的 资源ID 的使用都是引用类型;

源码依赖的 Lib 库和 aar 依赖的 Lib 库中的 R 文件的相关产物都是由于:如果依赖库的 R 文件中的 资源ID 在打包之前设置为常量,那么不同依赖库以及主工程的 R 文件必然会产生冲突。所有项目中的 R文件以及其资源ID 都是所有的代码合并之后重新赋值的或者生成的。

  • 源码依赖的 Lib 库的 R 文件会重新在 app 模块的 build 目录中重新生成一个相同的R 文件只不过 资源ID 前面添加了 final 关键词变成了常量;
  • aar 依赖的 Lib 库的R 文件会更具 .txt 文件中的内容,在 app 模块的 build 目录中重新生成一个R 文件而且 资源ID 是添加了 final 关键词的常量;
  • R 文件的生成目录和 主appR 文件是相同的;
APP_R_JAVA.png

这个目录在com.android.tools.build:gradle:3.4.1com.android.tools.build:gradle:3.2.0 版本下都是相同的。

APP_CLASS_R_ID.png
  • AAR的class文件 在主工程编译时,不会再次进行编译,也就是说AAR的class文件原封不动的打包进apk
  • 主工程的代码编译时在R 文件生成之后的,所以主工程的资源引用值都是常量且内联为常量值

其实这一点也和之前 R 文件结构中的知识点对应起来。R文件 是在编译主工程的时候进行合并、排序、赋值的。在这之后又返过来生成 R.java 文件,给 资源ID 赋予已经生成好的常量值。

R文件的数量

每个 aar 或者 lib库 都会有一个 R文件,那么一个项目的 R文件 数量为:

app中R文件数量=依赖的module/aar数量 + 1(自身的R文件)

module的R文件数 = 依赖的module/aar数量 + 1(自身的R文件)

后续疑问

我们大概了解的 R 文件的生成和使用。但通过本篇文章的了解我们也许会有更多的疑问?

  • 为什么要有那么多 R.java 文件,而且不同模块的的资源名称还有重复值?
  • 资源名称重复的时候会报异常,但这里的部分模块的资源名称明显有相同的为什么没有报异常?
  • 在编译的时候如果遇到资源重复,那么到底该使用哪个资源,有优先级规则是什么?
  • 为什么 aar 或者 lib库 中使用资源的 class 没有进行 ID值 的内联?
  • R文件 可以混淆么,有什么好处或者什么坑?

官网参考资料

添加应用资源

应用资源概览

文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容