maven central, jCenter or even jitpack which let you upload artifacts easily, for free and are repositories which are usually already used in any Android application. If you are developing a library which will be diffused internally then you will have to upload your artifacts on a private repository and provide repository address and credentials to the developers who will have to integrate your library on their project.
In the case where you have the infrastructure to do so, you can install a binary repository manager on a server you own and administer it by yourself. If you do not want to bother with maintaining it, SaaS private binary repository manager exists which will provide excellent service for a reasonable price. You can find different repository systems on this quite complete page. You can compare their different characteristics and whether a SaaS version exists or not.
Proguard is a tool widely used but often misunderstood. Ignoring how your library will work when Proguard is activated in the integrating application might lead to some compilation error or even crashes at runtime.
To understand properly this point, let’s make a quick recap of how Proguard works when a library is integrated into a project using Proguard features:
.aar/.jar
) is generated and then exposed to integrators.A first solution to make sure that your library will work properly when integrated in an app is to provide a set of Proguard rules that the integrator will have to put in its own set of proguard rules. You can easily verify that these rules are appropriate by creating a sample application integrating your lib and applying the “standard” Proguard rule.
An easier solution (and more convenient for the developer integrating your library) is to take advantage of the consumerProguardFiles property. This property, as stated in the documentation, allows you to specify a set of Proguard rules which will be merged to the integrating app set of Proguard rules. This is similar to the first solution, except that the integrating developer do not have to manually add the rules (therefore there is no risk that he forgets to do so). Keep in mind that the rules you set in this file will then be applied to the entire app + libraries bytecode, so put very specific rules to prevent impacting bytecode not related to your library.
In some cases, for instance when you do not want anyone to be able to easily read your library bytecode, you want to apply a first Proguard pass before exposing your library binaries. In that case, you can use the “regular” proguardFiles property. Of course you will have to take great care of the rules you add in this file (for instance you do not want your public APIs to be obfuscated). If you do so then your library bytecode is subject to two Proguard passes : a first time by you when you generate the library binary and a second time after being integrated in the app. This example of proguard files shows what can be the appropriate rules when you want to process your library before exposing it.
The gradle snippet below is an example of a proguard configuration of an .aar library with a Proguard pass before exposing the binary :
This point is self-explanatory. If you include too much libraries in your own library the developer who will integrate it in his project might face some issues :
It is common when you develop an Android library to have the need of defining your own resource (string, integer, theme…). If this is done the wrong way, it can lead to some issues when the library is integrated. Indeed, what happen if the resource name that you use is redefined elsewhere in application?
Before giving some insights on how is it possible to tackle this issue, let’s make a quick recap of Android’s resource conflict merging policy :
The solution to this problem is to make sure that all the resources you define have a unique name. The recommended way is to use a scheme which will ensure that the resource name will probably be unique. The android gradle plugin provides a convenient way of having this kind of scheme : the resourcePrefix parameter. If you set a string to this parameter you will be “forced” to have all your library’s resource names be prefixed with the parameter you gave. This is a good way to keep in mind to use a unique pattern to avoid name conflicts. Meanwhile, do note that you will still be able to generate your .aar if the resource names do not comply with the prefix you set : this safeguard only warns you in Android Studio if you do not follow the rule you set.
The following gradle file extract shows how to define resourcePrefix
:
This screenshot is an example of the kind warning you have if your resource name does not comply with the rule you set :
When you design the way your library will be used it is important to keep in mind that your library will be integrated with many others into a project. So solutions that might seem elegant or are more convenient for you can, in a concrete complex project, be at best constraining and in the worst case make the integration simply impossible.
A typical example of invasive library is a library, in order to be used, which requires that the Android Application object is inherited from a particular BaseApplication
class of the library. This is quite a bad choice because in the case where we have to integrate another library who has made the same design choice, then we are stuck. Maybe this design is the one that leads to the fewer code change in the integrating project but it is too invasive.
In more general terms, favor a design which allows integrating developers to isolate the different calls of your library.
In this article we have seen some points that you should keep in mind when developing your library. This will prevent you from having to modify your binaries after their integration in applications.
Of course, this list is not exhaustive at all. You can find other tips and tricks for developing an Android library on the related Android Developer page and great advices for designing your API here.
Last but not least, do not forget that the most important thing is probably to maintain an easy way to communicate with the people using your library : doing so you will contribute to increase the “Developer experience” of your library.