First thing first, all credits to for his post about Publishing Multi Module Android Libraries, so my post will be based on his work but with more details ( steps ) for newbies like me who struggle to publish their multi-module android library, as you know publishing to maven isn’t something easy you do as clicking a button, also I’ll trait an issue I got when following his tutorial and how I solved it.
We’ll publish to Maven Local and also to Github Packages, so let’s start!
The Setup
Open Android Studio and create a new project, choose an empty activity to keep things easy for us
I named my project PublishLibraryTuto
Now we will create for this tutorial two android libraries and a java library
Go to File -> New -> Now Module
We’ll call our first android library my-android-lib-1
And do the same for the second android library and call it my-android-lib-2.
Now we’ll create our Java library and call it my-java-library
Our project should looks like that
We’ll make our app module depends on the others lib, so go to app’s build.gradle and add the following lines inside your dependencies block and Sync Project with Gradle Files
1 2 3 4 5 |
... implementation project(path: ':my-android-lib-1') implementation project(path: ':my-android-lib-2') implementation project(path: ':my-java-library') ... |
In your app module, you can see that now you have access to other modules’ class
The Publishing logic
So we want to be able to publish all our libraries at once and without duplicating the publication’s logic inside our modules, we can do that by putting our publish logic inside the project build.gradle
Open your build.gradle file and go to your allprojects block and add set the group and version variables, by doing that we will have the same group and version for all modules.
1 2 3 4 5 6 7 8 |
allprojects { group = "com.appfiza.android" version = "1.0.0" repositories { google() mavenCentral() } } |
Now, just below this block code, we add subprojects block with the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
subprojects { apply plugin: "maven-publish" project.afterEvaluate { if (!plugins.hasPlugin("android")) { publishing { publications { maven(MavenPublication) { artifactId = "$project.name" if (plugins.hasPlugin("java")) { from components.java } else if (plugins.hasPlugin("android-library")) { from components.release } } } } } } } |
Basically what’s happening here, is we’re checking if our module is not an application module, to avoid publishing the app module
1 |
if (plugins.hasPlugin("java")) { from components.java } |
For publishing java modules
1 |
else if (plugins.hasPlugin("android-library")) { from components.release } |
And this part is for android modules.
If you Gradle sync, you’ll get the following error
1 2 3 4 5 6 7 |
org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':my-android-lib-1'. at org.gradle.configuration.project.LifecycleProjectEvaluator.wrapException(LifecycleProjectEvaluator.java:75) at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:68) at org.gradle.configuration.project.LifecycleProjectEvaluator.access$400(LifecycleProjectEvaluator.java:51) at org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate.run(LifecycleProjectEvaluator.java:191) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29) ... |
Even if we’re using afterEvaluate, it seems like it doesn’t recognize the release property.
The workaround I found and I post it on StackOverflow is to add another afterEvaluate after the maven block, so our code we’ll look like this now :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
subprojects { apply plugin: "maven-publish" project.afterEvaluate { if (!plugins.hasPlugin("android")) { publishing { publications { maven(MavenPublication) { afterEvaluate { artifactId = "$project.name" if (plugins.hasPlugin("java")) { from components.java } else if (plugins.hasPlugin("android-library")) { from components.release } } } } } } } } |
Try to Gradle Sync now, you will have a successful build.
Publish To MavenLocal
In your Android Studio, click on Gradle -> Tasks -> publishing -> publishToMavenLocal
If you can’t find the Gradle Tasks, go to Android Studio Settings -> Experimental and uncheck “Do not build Gradle list during Gradle sync“
After publishing, let’s check our local repository, it’s located at $USER/.m2/repository
And our library will be in $USER/.m2/repository/com/appfiza/android
Publish to Github Packages
To publish to Github Packages we need to specify the repository URL and our credentials, we update our subprojects code like below :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
subprojects { apply plugin: "maven-publish" project.afterEvaluate { if (!plugins.hasPlugin("android")) { publishing { publications { maven(MavenPublication) { afterEvaluate { artifactId = "$project.name" if (plugins.hasPlugin("java")) { from components.java } else if (plugins.hasPlugin("android-library")) { from components.release } } repositories { maven { url = "https://maven.pkg.github.com/BackPackerDz/PublishLibraryTuto/" credentials { username = YOUR_GITHUB_USERNAME password = YOUR_GITHUB_TOKEN } } } } } } } } } |
You can check how to generate your Github access token here
Now rather than selecting publishToMavenLocal, select publish, if everything is ok, you’ll get a successful message from Gradle, but go to your GitHub repository and check if it’s been published
My repository GitHub repo packages
How to retrieve our libraries for another project?
Create another fresh new project, and go to your project’s build.gradle and inside allprojects block in repositories add the following code
1 2 3 4 5 6 7 |
maven { url = "https://maven.pkg.github.com/BackPackerDz/PublishLibraryTuto" credentials { username = YOUR_GITHUB_USERNAME password = YOUR_GITHUB_TOKEN } } |
And in your app’s build.gradle add this to get your libraries
1 2 3 |
implementation 'com.appfiza.android:my-java-library:1.0.1' implementation 'com.appfiza.android:my-android-lib-2:1.0.1' implementation 'com.appfiza.android:my-android-lib-1:1.0.1' |
And you can start using them
That’s it, here is the Github repository if you need the code.
Hope my tutorial helped you, if you have any question, just leave a comment! 😃
Pingback: How to get a react native module in native via Maven - App Fiza
Thanks for the useful article. Can we do sdk library with multiple modules, and generate single aar file, which will include all related modules?
I mean structure:
app
mylibrary
lib1
lib2
And finally generate mylibrary.aar (which contains lib1 and lib2)
Hello Vitalii,
It’s not possible, your AAR file will not include the modules only the dependencies, which you’ll have to implement in your Gradle config (lib1 & lib2).
This is why it’s better to push your libraries to Maven, Gradle will retrieve them using the pom.xml file.
Thanks for this article, can we publish individual lib module instead of all lib module together. basically my project structure will be –
app
lib1
lib2
lib3
I want to publish only lib2 with new version, is it possible ?
Hi,
very useful article, but I have a question. is it possible to publish only one library for example publish lib1 with version 1.0.1 and lib2 and mylibrary to remain at version 1.0.0