Android中R文件ID值

文章目录

  • Android中R文件ID值
    • 前言
    • 知识回顾
      • 在代码中访问资源
      • 语法
    • R文件
      • Lib库的R文件
      • AAR中的R文件
      • 依赖库R文件的生成
      • R文件的数量
    • 后续疑问
    • 官网参考资料

前言

前端时间在学习 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文件结构

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包与其对应)

com.android.tools.build:gradle:3.4.1

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

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

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

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

AAR中的R文件

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

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

依赖库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 文件是相同的;

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

  • 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文件 可以混淆么,有什么好处或者什么坑?

官网参考资料

添加应用资源

应用资源概览

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

想阅读作者的更多文章,可以查看我 个人博客 和公共号:

Android中R文件ID值相关推荐

  1. Android Studio中R文件丢失可能的产生原因 以及解决方案

    一.Android Studio中R文件丢失可能的产生原因: 1.一般出现这种情况很有可能是R文件因为某种原因无法自动生成,多数是res资源文件的错误导致的. (1)在资源文件res中的资源文件大写例 ...

  2. android 读写文件 简书,Android 中的文件操作

    Android 文件操作 概述 Android 中的文件操作主要涉及到两个部分,一个是内部存储的读写,一个是外部存储的读写两者的主要区别如下表: 内部存储 外部存储 始终可用 它并非始终可用,因为用户 ...

  3. Android Studio R文件找不到

    求学的三个条件是:多观察.多吃苦.多研究. 方法一: 重新编译一次. 方法二: 检查res是否有错误.res有错误时也会导致R文件错误.(查看日志) 方法三: 其他文件中的R文件可以正常使用,某一个A ...

  4. android 生成aar文件,Android 中.aar文件生成方法与用法

    https://i.cnblogs.com/EditPosts.aspx?opt=1 无论是用Eclipse还是用Android Studio做android开发,都会接触到jar包,全称应该是:Ja ...

  5. mysql查询最小的id_Mysql查询表中最小可用id值的方法

    今天在看实验室的项目时,碰到了一个让我"棘手"的问题,其实也是自己太笨了.先把 sql 语句扔出来 // 这条语句在id没有1时,不能得到正确的查询结果. select min(i ...

  6. 修改Android中的文件权限

    在Android中有一个精简版的linux系统,因为是linux系统,那么有时候在写Android应用程序的时候会遇到权限问题.我们都知道在shell中可以通过chmod命令来修改权限,所以就希望通过 ...

  7. Android studio R文件丢失或错误解决方法

    Android studio R文件丢失或错误解决方法 参考文章: (1)Android studio R文件丢失或错误解决方法 (2)https://www.cnblogs.com/dean-Li/ ...

  8. JAVA中获取文件MD5值的四种方法

    JAVA中获取文件MD5值的四种方法其实都很类似,因为核心都是通过JAVA自带的MessageDigest类来实现.获取文件MD5值主要分为三个步骤,第一步获取文件的byte信息,第二步通过Messa ...

  9. Android中Assets文件路径

    Android中Assets文件绝对路径是不存在的 一般Assets文件夹里放些网页文件html.css.js 在网页文件中引用assets里的文件可以使用file:///android_asset/ ...

最新文章

  1. 程序员肚子越来越大_肚子越来越大,除了肥胖还可能是疾病信号!腰间搓一搓,排出痰浊,消脂防病~...
  2. Airflow 中文文档:调度和触发器
  3. sort()函数与升序、降序
  4. 学习笔记:DHCP服务器的配置
  5. 深度学习之----双线性插值,转置卷积,反卷积的区别与联系
  6. [BZOJ4872][六省联考2017]分手是祝愿(期望DP)
  7. php max file uploads,php上传多文件max_file_uploads限制问题
  8. 日程列表html,日程安排FullCalendar
  9. 加拿大比索大学计算机科学硕士,来悉尼大学恍恍惚惚一年后,我给大家吐血整理了经验贴…....
  10. 树莓派(4B)入门教程
  11. C++ 笔记 加号运算符重载
  12. FeignException$InternalServerError [500] during [POST]同时出现converter.HttpMessageConversionException
  13. 对于程序员来说什么才是A站B站。。。Z站?
  14. 《大掌门》欧阳刘彬:基于Cocos2d-x引擎开发经验分享
  15. 华纬科技冲刺深交所:拟募资4亿 二代接班金雷,控制65%股权
  16. 华为手机有哪些隐藏功能,用了才知道太好用啦!
  17. 数据结构与算法笔记:抽象思维之转换视角,提炼共性(分书和八皇后问题算法重构)
  18. 2022最全Java后端面试真题、两万字1000+道堪称史上最强的面试题不接受任何反驳
  19. 新高考计算机科学与技术,2017年浙江新高考:“技术科目”成“黑马”
  20. python可视化数据分析-Python数据分析与可视化从入门到精通

热门文章

  1. 如果整数A的全部因子(包括1,不包括A本身)之和等于B;且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。求3000以内的全部亲密数
  2. 算法设计与分析-----动态规划
  3. 12V-240V蓄电池放电容量测试仪(放电仪)功能介绍及技术参数
  4. 考研英语 - word-list-40
  5. 用神经网络表示与逻辑,神经网络实现逻辑运算
  6. 警告!来历不明的疫情邮件或许是黑客陷阱
  7. saf java_Android SAF实现外置SD卡的写入JAVA层与JNI层hook
  8. POJ 2449 Remmarguts' Date [第k短路]
  9. 【爬虫实践】获取某城市天气数据
  10. linux使用阿里云镜像仓库yum源