Solution 1 :
Are the rules around these class resources documented somewhere?
The Android build behavior when creating APKs is described in the Add app resources section of the user guide. Look for the heading on Resource merging.
You are correct that all of the sources are combined into a single namespace. The idea is that resource merging makes the resulting APK smaller1.
Android is not constrained to be Java(tm) compliant, and they have made different design decisions.
1 – An APK is just like a fat JAR or uberJAR in the classic Java world. You would not expect multiple copies of a resource in a fat JAR. The getResources API would only give you a single resource for any name in that context as well.
Problem :
In Java VM, a classloader can have multiple domains, generally JAR files (which are similar to APK files). Each of these domains have a single namespace. That is, every resource has a unique name.
Calling ClassLoader.getResources(“foo”) can, therefore, return multiple URLs. However, looking at Android, the build seems to flatten the resource namespace, overwriting resources with the same path. This wreaks havoc with mechanisms like the Java ServiceLoader. It also seems to void any use of the META-INF/MANIFEST.MF
.
For example, if I use liba.jar
and libb.jar
, and both have a resource OSGI-OPT/com.example.Foo
, then only one seems to end up in the APK.
Are the rules around these class resources documented somewhere?
Comments
Comment posted by Peter Kriens
Thx. I agree that Android is not Java but this deviation means in principle that Java libraries can give nasty problems, nor can the getResources() contract be followed. Ah well, don’t think they’ll change it for me though 🙂
Comment posted by Stephen C
In response to your comments: 1) There is (should be) no expectation that any Java(tm) library will just run on Android. There are bigger differences than this. 2) The contract is still followed. Just not in the way that a Java(tm) programmer may have expected. 3) You are right about that.