Reputation: 741
I'm currently developing a custom library for Android.
My idea is to have a version for the app (I'm currently setting it in de build.gradle file and it works fine), and a different version for the library.
Is there a best practice in order to achieve this without having the two build.gradle files merged together?
I found a couple of similar questions on SO but they were 4 years old and not very helpful.
Upvotes: 9
Views: 4216
Reputation: 1209
The solution for this is not Git as you probably already figured out. OP wants to externally version a library, potentially as a means to provide an API to a third-party without providing the source code.
This is not trivial with Gradle but it is doable.
You can do this at different levels, I'll explain the easiest and most straight-forward.
First you need to add a version
variable to your gradle.properties
file. You can set this variable with a simple one-liner:
version=0.1.0-SNAPSHOT
In your project create a file called versioning.gradle
and paste the following code inside (I found this online a long time ago, I don't have the source anymore):
ext {
/**
* Builds an Android version code from the version of the project.
* This is designed to handle the -SNAPSHOT and -RC format.
*
* I.e. during development the version ends with -SNAPSHOT. As the code stabilizes and release nears
* one or many Release Candidates are tagged. These all end with "-RC1", "-RC2" etc.
* And the final release is without any suffix.
* @return
*/
buildVersionCode = {
//The rules is as follows:
//-SNAPSHOT counts as 0
//-RC* counts as the RC number, i.e. 1 to 98
//final release counts as 99.
//Thus you can only have 98 Release Candidates, which ought to be enough for everyone
def candidate = "99"
def (major, minor, patch) = version.toLowerCase().replaceAll('-', '').tokenize('.')
if (patch.endsWith("snapshot")) {
candidate = "0"
patch = patch.replaceAll("[^0-9]","")
} else {
def rc
(patch, rc) = patch.tokenize("rc")
if (rc) {
candidate = rc
}
}
(major, minor, patch, candidate) = [major, minor, patch, candidate].collect{it.toInteger()}
(major * 1000000) + (minor * 10000) + (patch * 100) + candidate;
}
}
Once you've done this, be sure to include the versioning.gradle
file from your main build.gradle
file by adding apply from: '../versioning.gradle'
near where the Android plugin is loaded.
Then, in your defaultConfig block, you want to change the default version variables to the following values:
versionCode buildVersionCode()
versionName version
If you're truly building an Android library, then the expected output is an .aar
file.
Therefore, add the following gradle code to your build.gradle
file:
libraryVariants.all {
variant -> variant.outputs.each {
output -> output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace(".aar", "-${defaultConfig.versionName}.aar")
)
}
}
And that's it! Your output file will have a name with the version number you specify in the gradle.proprties
file.
This will version your library and/or API in a very static manner. Meaning that there's no way for a developer to dynamically get the version number through a method call.
Be sure to also have a method available that supplies client developers with the version number AND be sure to keep the two in sync. Only then you have a properly versioned library.
Upvotes: 7
Reputation: 4193
Why would you want to do this?
If the problem is that you need to be able to take different actions in the programs using the library depending on the version, then simply create a public static final constant somewhere in the library.
If the reason is cosmetic (e.g., for presentation), then simply put it in your Readme, Changelog, or wherever you need it. Messing up the build files for this purpose is a bad idea.
Based on your explanation:
My recommendation is to put it in the library's AndroidManifest.xml in that case (android:versionCode and android:versionName). This is what Google does with many of their own libraries, and it's harmless wrt the build.
Upvotes: -4