Sometime I can see a R.txt file in some .aar (and in such case there is also a non-empty ./res directory in the aar). What the exact purpose of this R.txt file? Also sometime I can see some AAR with a non-empty ./res directory but without any R.txt, is it normal ?
A R.txt
file in a foo.aar
file serves
foo.aar
, and.apk
or .aar
files which depend on foo.aar
.The purpose of R.txt
is basically the same as of R.java
-- mapping resources to IDs --, therefore you'll find a R.txt
in an .aar
file with a non-empty /res
folder. In case of an empty /res
folder there's either no R.txt
at all, or an empty R.txt
of size zero.
As described in the Chromium Googlesource article on the Life of an Android Resource, R.txt is an intermediate file on the way to an APK, containing a list of resources and their IDs. It is also archived to help with debugging, as a simple .txt
file is easier to parse than the final .java
file.
Actually it's not that intermediate, as it is also characterized as a final file that is put into the out/*/apks
directory next to the final .apk
file. Now, in case of an library .aar
file it is put directly into the output (.aar
) file together with other debugging and configuration files like lint.jar
.
In an .aar
file, which can be used as a dependency for other libraries as well as for APKs, R.txt
has an additional role. Except for being used for debugging it also serves as an input for the next level file build in the dependency hierarchy.
Lets take a look on the entries in R.txt
. Their structure is as follows (read "res" as "resource"). A line ends with a newline.
<type> <res_class> <res_name> <res_id>
This information matches the information in R.java
like this:
public static final class <res_class> {
public static final <type> <res_name> = <res_id>;
//...
}
The above mentioned article shows a sample R.java
from package org.chromium.ui
.
public final class R {
public static final class attr {
public static final int buttonAlignment = 0x7f030038;
public static final int buttonColor = 0x7f03003e;
public static final int layout = 0x7f030094;
public static final int roundedfillColor = 0x7f0300bf;
public static final int secondaryButtonText = 0x7f0300c4;
public static final int stackedMargin = 0x7f0300d4;
}
public static final class id {
public static final int apart = 0x7f080021;
public static final int dropdown_body_footer_divider = 0x7f08003d;
public static final int dropdown_body_list = 0x7f08003e;
public static final int dropdown_footer = 0x7f08003f;
}
public static final class layout {
public static final int dropdown_item = 0x7f0a0022;
public static final int dropdown_window = 0x7f0a0023;
}
}
The corresponding R.txt will therefore be:
int attr buttonAlignment 0x7f030038
int attr buttonColor 0x7f03003e
int attr layout 0x7f030094
int attr roundedfillColor 0x7f0300bf
int attr secondaryButtonText 0x7f0300c4
int attr stackedMargin 0x7f0300d4
int id apart 0x7f080021
int id dropdown_body_footer_divider 0x7f08003d
int id dropdown_body_list 0x7f08003e
int id dropdown_footer 0x7f08003f
int layout dropdown_item 0x7f0a0022
int layout dropdown_window 0x7f0a0023
Now, in an APK building without AARs, the resource IDs from R.txt
will be taken over as-is to R.java
. However, this won't work with AARs because of the variable structure of resource ID's.
type
field won't be guaranteedly the same for the same resource type across several .aar
files. A layout
resource might be of type 0a
in one file, but be 03
in an other, while in the first one 03
stands for int
.entry
field is an autoincrement number, which per se can only be valid without collision within the same file.So, this way you can have the same ID, lets say 0x7f030038
, in several R.txt
files from your dependency AARs, which will describe completely different resources. Therefore, while building an APK (or another higher-level AAR), all the R.txt
files from dependencies will be put together with the APK's own temporary R.txt
file and a new, final, R.txt
will be written, with unique IDs for the APK's resources.