Resource id generation and AARs

1,303 views
Skip to first unread message

William Ferguson

unread,
Dec 16, 2013, 9:27:32 AM12/16/13
to adt...@googlegroups.com
Can someone please explain to me how Resource id generation is going to work now with AARs.

Incorporating APKLIBs was slow but fairly straight forward. I have just spent the last 48 hours trying to get the android-maven-plugin to build an APK that depends on an AAR that has code referencing it own resources. As part of that I have spent a large chunk of time trawling through the android platform tools source and it's not clear to me that all use cases have been covered. 

So I hoping that someone can clarify a raft of questions that surfaced as part of my investigations for which I couldn't find any doco.

An AAR contains the following (plus some optionals)
  • /AndroidManifest.xml (mandatory)
  • /classes.jar (mandatory)
  • /res/ (mandatory)
  • /R.txt (mandatory)

In my APK that consumes this AAR I will presumably also have resources.

Q1: What should happen when there is a name clash between the AAR and APK for those resources? Eg
    - AAR/res/layout/layout_main.xml  vs APK/res/layout/layout_main.xml
    - AAR/res/values/strings.xml  vs APK/res/values/strings.xml
    - AAR/res/values/strings_a.xml (string1)  vs APK/res/values/string_b.xml (string1)
  Should the build break in any/all 3 cases?

Q2: Does/Should AAR classes.jar contain a compiled R class.

Q3: Should that R class have non-final fields. As suggested by http://tools.android.com/tips/non-constant-fields?
    If it has non-final fields then how are those fields updated to reflect the the values generated during the APK build.
    If they are not updated then how are id clashes from more than one dependent AARs prevented?

Q4: If the AAR R class either doesn't exist or has final fields then the final values will have been burnt into the compiled classes that use them.
    During he APK build when the resource ids are generated for all the resource contained in the APK (including the AAR resources), how are the references in compiled classes updated?
    

William

Tor Norbye

unread,
Dec 16, 2013, 1:55:01 PM12/16/13
to adt...@googlegroups.com
On Mon, Dec 16, 2013 at 6:27 AM, William Ferguson <william....@xandar.com.au> wrote:
Can someone please explain to me how Resource id generation is going to work now with AARs.

Incorporating APKLIBs was slow but fairly straight forward. I have just spent the last 48 hours trying to get the android-maven-plugin to build an APK that depends on an AAR that has code referencing it own resources. As part of that I have spent a large chunk of time trawling through the android platform tools source and it's not clear to me that all use cases have been covered. 

So I hoping that someone can clarify a raft of questions that surfaced as part of my investigations for which I couldn't find any doco.

An AAR contains the following (plus some optionals)
  • /AndroidManifest.xml (mandatory)
  • /classes.jar (mandatory)
  • /res/ (mandatory)
  • /R.txt (mandatory)

In my APK that consumes this AAR I will presumably also have resources.

Q1: What should happen when there is a name clash between the AAR and APK for those resources? Eg
    - AAR/res/layout/layout_main.xml  vs APK/res/layout/layout_main.xml
    - AAR/res/values/strings.xml  vs APK/res/values/strings.xml
    - AAR/res/values/strings_a.xml (string1)  vs APK/res/values/string_b.xml (string1)
  Should the build break in any/all 3 cases?

Case 2: they are unrelated. Value files can be named anything. This should not be treated as a clash.
Cases 1 and 3 are the same; for non-value resources, the resource name is derived from the file, so they both define @layout/layout_main. 
Again for case 3 the value of the file name doesn't matter, but they're defining the same string.

I believe the right thing to do here is to treat this as an overlay: the app redefines the resource. At least that's how we treat the case where multiple flavors provide definitions for the same resource. Seems reasonable that a library would be treated similarly, though Xav should confirm.

Q2: Does/Should AAR classes.jar contain a compiled R class.

No. The id's in the R class *must* be changed when the final app is assembled, so it's done at that time (it computes a global set of unique id's, then creates R classes for each namespace required by the various compiled classes, assigning those id's).

Q3: Should that R class have non-final fields. As suggested by http://tools.android.com/tips/non-constant-fields?
    If it has non-final fields then how are those fields updated to reflect the the values generated during the APK build.
    If they are not updated then how are id clashes from more than one dependent AARs prevented?

Id's in library cannot be final since if they were, they would get copied into the various classes.jar classes in the library, and could then clash with other libraries. By being non final, they will defer to runtime to look up the actual value, where they can find the id's actually assigned in the final app assemble.

Q4: If the AAR R class either doesn't exist or has final fields then the final values will have been burnt into the compiled classes that use them.
    During he APK build when the resource ids are generated for all the resource contained in the APK (including the AAR resources), how are the references in compiled classes updated?

Again, it creates multiple R classes, one for each library package, but ensures that the R id's are identical across these classes.

-- Tor

Xavier Ducrohet

unread,
Dec 16, 2013, 2:03:14 PM12/16/13
to adt...@googlegroups.com
App override library resources, always. As Tor said, we don't care about strings.xml, we do the merge on resources, not on files.

Libraries are compiled with non-final resource IDs, and classes.jar does not include the R class.
R.txt is meant to clearly define what resources are in the library.

App generate the final list of resources, merging resources from the app and the libraries. We use aapt to generate the IDs for the combined resources, using the app's package name and using final integers. Once this is done we go through all the libraries and use their R.txt file to manually generate a R class in their own package name. These are final integers as well.
(there's also some code to deal with the case where libraries have the same package name, but we might move away from allowing this).


--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Xavier Ducrohet
Android SDK Tech Lead
Google Inc.
http://developer.android.com | http://tools.android.com

Please do not send me questions directly. Thanks!

William Ferguson

unread,
Dec 17, 2013, 5:56:03 AM12/17/13
to adt...@googlegroups.com
Great, thanks Tor, Xavier.

All of that makes sense to me except for the bit about overlaying resources.

If we are talking about an apk that has a dependency on a single aar then you could I guess decide that the apk resources overlay those of the aar. 

But what about when you have 2 aars that have similarly names resources. The aars are likely to have been developed independently with the name clash entirely unintended/unexpected.

BTW when resources are provided to aapt using the "-S" flag how does it determine which resource is top most? First, last, arbitrary?

William

William Ferguson

unread,
Dec 18, 2013, 5:54:47 PM12/18/13
to adt...@googlegroups.com
*bump*

Xavier Ducrohet

unread,
Dec 18, 2013, 6:31:30 PM12/18/13
to adt...@googlegroups.com
The order of library dependencies is important. Also we recommend devs to use a prefix in their resources when using libraries (look at app compat, it uses the abc_ prefix).

aapt's help output says the left most -S option is higher priority IIRC. (we don't use multiple -S anymore, we merge manually first so that it can be incremental)

I've been thinking about allowing ( through the gradle file) to disable overlays and break on conflicts and then let developers control how the conflicts get resolved but it's a lot of work and low priority.

William Ferguson

unread,
Dec 19, 2013, 9:30:10 AM12/19/13
to adt...@googlegroups.com
Thanks Xavier, very helpful.

If/when you decide to allow aapt to disable overlays it's going to have to default to allow overlay otherwise lots of builds will immediately break.

William

Xavier Ducrohet

unread,
Dec 19, 2013, 1:12:02 PM12/19/13
to adt...@googlegroups.com
indeed.
Reply all
Reply to author
Forward
0 new messages