Nexus as a binary repository for APKs
Brief tutorial, to show how to use Nexus OSS as a binary repository for APKs
If you use Nexus OSS to store your finished binary artifacts, you will of course want to do the same for your APKs. Since I’m currently working on an Android app professionally, I’ve now had the chance to gain my experience with it. Because I don’t want to make the same pitfalls again next time, I will explain it here step by step.
My previous experiences with Gradle are (fortunately) hardly worth mentioning, so first an extensive Google research was on the agenda. This soon led me to the Maven plugin for Gradle and the following configuration for uploadArchives
:
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
repository(url: "file://localhost/tmp/myRepo/")
}
}
}
A corresponding call with gradlew clean assemble uploadArchives
ran successfully, but no artifacts were stored. So I then became aware of the Gradle user guide Publishing artifacts and realized that the APKs must be declared so that uploadArchives
also knows what is to be uploaded.
To add the APKs of all build variants (debug, release and/ or productflavors) created with assemble
the following addition helps:
android.applicationVariants.all { variant ->
def apkFile = file(variant.outputs.outputFile[0])
tasks."assemble${variant.name.capitalize()}" << {
artifacts {
archives file: apkFile
}
}
}
Unfortunately, now with the added APKs uploadArchives
does not work anymore, because within one POM there must not be multiple artifacts of the same type and classifier. The following error message appears:
:app:uploadArchives FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:uploadArchives'.
> Could not publish configuration 'archives'
> A POM cannot have multiple artifacts with the same type and classifier. Already have MavenArtifact app:apk:apk:null, trying to add MavenArtifact app:apk:apk:null.
So the configuration of the artifacts has to be extended a bit. The easiest way to do this is via the classifier
, as in the following snippet:
android.applicationVariants.all { variant ->
def apkFile = file(variant.outputs.outputFile[0])
tasks."assemble${variant.name.capitalize()}" << {
artifacts {
archives file: apkFile, name: variant.baseName, type: 'apk', classifier: variant.baseName
}
}
}
This completes the first part. The APKs end up in the configured repository. Now only the default values of the POM generation have to be adjusted if needed, in my case groupId
, artifactId
and version
:
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
repository(url: "file://localhost/tmp/myRepo/")
pom {
groupId 'de.sainth.android'
artifactId 'meineTolleApp'
version android.defaultConfig.versionName
}
}
}
}
Last but not least, replace the local repository with the real one. To avoid having to check in the credentials for the Nexus, it is a good idea to store them in the central ~/.gradle/gradle.properties
and point to it.
nexusUser=Benutzername
nexusPassword=Passwort
This is how the following configuration for the interaction of Gradle and Nexus for APK storage is created in the end:
apply plugin: 'maven'
android.applicationVariants.all { variant ->
def apkFile = file(variant.outputs.outputFile[0])
tasks."assemble${variant.name.capitalize()}" << {
artifacts {
archives file: apkFile, name: variant.baseName, type: 'apk', classifier: variant.baseName
}
}
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: "https://mein.nexus.de/repo/") {
authentication(userName: "$nexusUser", password: "$nexusPassword")
}
pom {
groupId 'de.sainth.android'
artifactId 'meineTolleApp'
version android.defaultConfig.versionName
}
}
}
}