pellyadolfo
pellyadolfo

Reputation: 991

Missing optional namespace concept in Android resources merging

In my android app I have created a library which shares some string resources with the main project.

Main project --------------> main resources (e.g. string)
library project -----------> library resources (e.g. string)

Lets assume:

<string name="app_name">The new app name</string> (in main)
<string name="app_name">The standard app name</string> (in library)

Google states that there is a merge in compilation time and recommends using hardcoded prefixes at resource level to prevent the merge:

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.

I think I have a mix of required behaviors:

I think hardcoding a prefix is unnecesarily extending strings size so I would expect google providing a kind of attr, per resource file or per resource, to optionally internally prefix (with something as package name) so developer can access a non overriden resource. Something as:

<string name="app_name" prefix="yes"></string>

('prefix' attr added by me instructing compiler to save resource as e.g. package_name.app_name to prevent merge with app_name) and in library code it would access string as

getResources().getPrefixedString(R.id.app_name)

I also know that I can invoke resources by identifier, in a kind of reflection, as

getResources().getIdentifier("res_name", "res_type", "com.library.package");

but there are 3 drawbacks with this approach if I want to manually simulate this behavior:

  1. lower performance
  2. I still have to add my hardcoded namespace as a prefix to all the required strings and
  3. resources cannot be invoked from XML itself (unless you hardcode the prefix as well).

Is there currently any mechanism to instruct the compiler if I want to merge a resource or not?

Upvotes: 1

Views: 1033

Answers (1)

CommonsWare
CommonsWare

Reputation: 1007265

Is there currently any mechanism to instruct the compiler if I want to merge a resource or not?

Not in the way that you are expecting, per your comments.

Thats is why I would expect being able to optionally define a kind of namespace to prevent merging of library resources

That is not supported by the build tools at this time. Prefixes to maintain resource uniqueness are up to the developer.

You are certainly welcome to write your own tools to assist yourself in this area. For example, you could write a Gradle task that examines relevant resources and, if they lack the prefix and do not have some XML attribute to say "ignore this one", fails the build.

I also know that I can invoke resources by identifier, in a kind of reflection

This does not work the way you expect.

You appear to think that libraries have resources independent of the application. This is incorrect. Libraries contribute resources to the application, but all the resources are part of one big pool. Hence, you cannot use getIdentifier() and provide some library name and get a value back. You provide the application ID of the application and get the one resource in that application matching your criteria (assuming such a resource exists). Whether that resource comes from a library or from an app module does not matter.

Upvotes: 4

Related Questions