Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android resources key collision

I have two Android projects, a main one (package name com.adip.sampler) and a library that is added to main (package name com.samples.projb). In both of them in resources I have an integer-array with same key: my_int_values:

In main project:

<integer-array name="my_int_values">
    <item>10</item>
    <item>20</item>
    <item>30</item>
    <item>40</item>
    <item>50</item>
    <item>60</item>
    <item>70</item>
    <item>80</item>
</integer-array>

while in library:

<integer-array name="my_int_values">
    <item>34</item>
    <item>35</item>
    <item>36</item>
    <item>37</item>
</integer-array>

In main project from an activity if I am investigating what are the values from these arrays (both main project and library):

protected void showLocalStrings() {
    Log.d("RESSampler", "In Main: " + Arrays.toString(getResources().getIntArray(com.adip.sampler.R.array.my_int_values)));
    Log.d("RESSampler", "In Libr: " + Arrays.toString(getResources().getIntArray(com.samples.projb.R.array.my_int_values)));
}

then I'm seeing this in Logcat:

In Main: [10, 20, 30, 40, 50, 60, 70, 80]
In Libr: [10, 20, 30, 40, 50, 60, 70, 80]

It seems that main project is overriding the values defined in library array ... I doubled checked if I am reading from resources with correct key and that is ok. Until I took a look in each generated R class. In the main project this is what I have for com.adip.sampler.R.array.my_int_values:

public static final class array {
    public static final int my_int_values=0x7f060000;
}

while in library project com.samples.projb.R.array.my_int_values:

public static final class array {
    public static final int my_int_values = 0x7f060000;
}

Android tool has generated the same value, so no wonder I am getting this behavior. I can get rid of this behavior if I change the key from one of the integer arrays, but imagine that you have some big projects with a lot of resources, dependency libraries and sooner or later you may bump into this kind of issue: having the same type of resources with the same key value (I've checked with string and with string-array and above behavior appears there as well). So the questions would be:

  1. Why this issue appears? Or if it's not an issue what explains this behavior?
  2. How to avoid it best? I am guessing that trying to have some kind of uniqueness in defining the keys will do the trick, but developers tend to be lazy ...

This appears using multiple variants of latest ADTs and Eclipse versions (Juno and Indigo). Checked on Windows only.

like image 302
gunar Avatar asked Oct 10 '13 21:10

gunar


2 Answers

Reading from Library Projects at Android Developers, there are many references where they clearly say merging happens at build time and resources with same IDs overwrite each other.

For resources with same ID from a library and application

In cases where a resource ID is defined in both the application and the library, the tools ensure that the resource declared in the application gets priority and that the resource in the library project is not compiled into the application .apk. This gives your application the flexibility to either use or redefine any resource behaviors or values that are defined in any library.

For resources with same ID from two libraries

... your application can add references to multiple library projects, then specify the relative priority of the resources in each library. This lets you build up the resources actually used in your application in a cumulative manner. When two libraries referenced from an application define the same resource ID, the tools select the resource from the library with higher priority and discard the other.

Solution suggested in documentation

Use prefixes to avoid resource conflicts

To avoid resource conflicts for common resource IDs, consider using a prefix or other consistent naming scheme that is unique to the project (or is unique across all projects).

How to set priority in libraries from command line

If you are adding references to multiple libraries, note that you can set their relative priority (and merge order) by manually editing the project.properties file and adjusting the each reference's .n index as appropriate.

like image 69
auselen Avatar answered Nov 15 '22 11:11

auselen


Personally, I would change the names of the resources. If you read anything about naming conventions, it should be something meaningful and "my_int_array" isn't really too helpful, especially in a library that other people or project could potentially use.

Ideally, you want to be able to forget about this for 6 months, come back and look at it and know what that array is for/contains, without having to delve through code to deduce what the array is for by what's done with it.

This post; https://stackoverflow.com/a/7249410/1222199 contains a few different answers on naming conventions.

Finally, not sure about the conflict, couldn't dig anything up. I'm guessing it's to do with the way it's automatically generated, might be worth logging it as a bug and see if you get any response from the development team.

like image 32
Trent Avatar answered Nov 15 '22 12:11

Trent