In my day job, I develop Android libraries, (let's call them) libA and libB. At some point, we've realized there's a lot of shared code between them and so we've moved this code to another folder and referenced it using the sourceset directive.
When we build a project, we started getting 'Error: Program type already present', which makes me think the Android compiler just got smarter or a change to the project structure (we've merged the projects) made the duplication visible. In any case, this issue is still intermittent but it was probably always a bad idea. Google has this to say about the subject.
The solution I'm considering is moving the shared code to a separate module. This way, each class is compiled exactly once. I have made a simple project to test this architecture.
The resulting project would have the following modules:
- Demo App (lib* or shared app for all)
- libA
- libB
- sharedLib
Which raises the following questions:
- Is this the right way to go? I realized this is potentially an opinion based but this is such an edge case, I've not been able to find any discussions of it in the sea of the more general questions about namespace collision.
- How do we distribute the shared code? Ideally, I'd like to somehow bundle it into the aar of lib*. (Currently, the lib* aar does not include the shared code.) Otherwise, I'd just distribute two aar files.
- How does the java/android compiler handle this? Say I try to compile two libraries with the same package/class, I assume it will issue the above error or just pick one and try to compile.
- How do popular libraries deal with this? I can easily see okHTTP bundled into several 3rd party libraries and the main application. I'm specifically asking about API breaking version differences and non-API breaking versions.
- Just for completeness sake, I know that the DEX does not have the option for multiple classes with the same name. I'm assuming this is all sorted out during the java compilation. IIRC, I did check and DEX creation has a linter/validator that checks this. Extra points for clearing this up and referencing relevant link.
Notes:
- This is not an issue for C/C++ and such, as you have the option to use static libraries and duplicate the code.
- Some S/O questions about namespace colission are actually about variable shadowing (e.g. java namespace collisions).
- This answer proved to me my instinct regarding this issue was right. Different jars could cause this issue but compilation would detect it.
- This question and especially an answer by CommonsWare hint at a far larger discussion.