This tutorial shows how to distribute a local Gradle module of your app in AAR form, along with its dependencies, via a local Maven repository.
This is particularly useful if you cannot deploy your library’s AAR to a remote Maven repository, either public or private, for example because the library is closed-source, so you cannot rely on JCenter, Maven Central or Jitpack, or the library will be used on a machine without Internet connectivity. In the latter case, a local Maven repository will be particularly useful because it will provide all the necessary dependencies of your library.
Credits: this is heavily based on this gist posted by Robyer.
We will use the new maven-publish
plugin to produce the AAR artifact of our library.
In your library build.gradle
file, add the following:
apply plugin: 'maven-publish'
android {
buildTypes {
distributable.initWith(buildTypes.release)
distributable {
minifyEnabled true
proguardFiles 'proguard-rules-distributable.txt' // if you want to use a specific proguard configuration for the AAR artifact
}
}
}
The distributable
build type will use the given progard file for obfuscation. Since it is important not to lose the generated mapping file, we will define a task to give it a descriptive name and copy it somewhere safe:
android.libraryVariants.all { variant ->
if (variant.buildType.name == 'distributable') {
if (variant.mappingFile != null) {
tasks.create(name: "copyDistributableAarProguardMapping", type: Copy) {
group "distribution"
String today = new Date().format('yyyyMMdd_HHmmss')
from variant.mappingFile.path
rename '.*', "${project.name}_${today}_mapping.txt"
into rootDir
}
bundleDistributable.finalizedBy copyDistributableAarProguardMapping
}
}
}
Next, we will configure the maven-publish
plugin to package and deploy the AAR to our local Maven repo. Its path is passed as an URL representing a directory.
publishing {
repositories {
maven {
url "/path/to/our/local/maven/repo"
}
}
publications {
maven(MavenPublication) {
// Customize these
groupId 'com.my.groupid'
artifactId 'my-artifact-id'
version '1.0'
artifact bundleDistributable {
classifier ""
}
pom.withXml {
def node = asNode()
// ugly hack to set the packaging property in the POM as 'aar'
((NodeList) node.get('packaging')).get(0).value = 'aar'
def dependenciesNode = node.appendNode('dependencies')
def cl = { Dependency dep ->
if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
return // ignore invalid dependencies
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dep.group)
dependencyNode.appendNode('artifactId', dep.name)
dependencyNode.appendNode('version', dep.version)
if (!dep.transitive) {
// If this dependency is transitive, we should force exclude all its dependencies them from the POM
def exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
exclusionNode.appendNode('groupId', '*')
exclusionNode.appendNode('artifactId', '*')
} else if (!dep.properties.excludeRules.empty) {
// Otherwise add specified exclude rules
def exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
dep.properties.excludeRules.each { ExcludeRule rule ->
exclusionNode.appendNode('groupId', rule.group ?: '*')
exclusionNode.appendNode('artifactId', rule.module ?: '*')
}
}
}
// List all dependencies and write to POM
configurations.api.getAllDependencies().each cl
configurations.implementation.getAllDependencies().each cl
}
}
}
}
Now, by invoking the following command, Gradle will package an obfuscated AAR of our library and deploy it to our local Maven repo:
gradle :mylibrary:publish
You can also add other libraries, along with their dependencies, to our local Maven repo. This is useful if you plan to distribute this repo to a machine that cannot access the public Maven repos on the Internet.
To do so, you can use maven-repository-provisioner
. Download the jar with dependencies, then use it like so to download, for example, okhttp
:
java -jar maven-repository-provisioner-1.2.0-jar-with-dependencies.jar \
-s http://jcenter.bintray.com/ \
-t /path/to/our/local/maven/repo \
-a "com.squareup.okhttp3:okhttp:3.6.0" \
-ij false -is false
To add an AAR to the local Maven repo, just use Maven itself, as shown in the following command. I have had some headaches with using plain AARs in a project, and I find this way much more reliable and hassle-free.
mvn install:install-file -Dfile=/path/to/library.aar \
-DgroupId=com.my.groupid \
-DartifactId=my-artifact-id \
-Dversion=1.0.0 \
-Dpackaging=aar \
-DlocalRepositoryPath=/path/to/our/local/maven/repo
In your project build.gradle
file, simply add a new repository:
allprojects {
repositories {
maven {
url "/path/to/our/local/maven/repo"
}
}
}
Then, in your app build.gradle
file, you will be able to declare a dependency on your library simply via:
implementation 'com.my.groupid:my-artifact-id:1.0'