How to version local gradle dependencies? - android

My Android project contains a library that is shipped as AAR file.
There are multiple options to include local AAR files.
I can declare a file dependency:
implementation files('libs/mylib.aar')
Or I can put the AAR into another module and then use a project dependency:
implementation project(':mylibmodule')
However, I want to specify the exact version of my library:
mylib:1.0.0
Unfortunately, I do not know how to specify the version without using some remote repository.
Note that I do not want to upload the library to JitPack, MavenCentral or similar.
All I want is to specify the version of a local AAR file.
Update
The AAR file is a Zip-File with the following content:
/proguard.txt
/R.txt
/AndroidManifest.xml
/public.txt
/classes.jar
/res/values/values.xml
Note that the AndroidManifest.xml contains the version of the library.
However, I assume that gradle always expects a pom file for the versioning information.

I realized that gradle allows to specify a local Maven repository at a specific path:
repositories {
maven {
url uri("${projectDir}/mylibdir")
}
}
To use a local Maven repository, I need to build my library as a Maven artifact. To create a Maven artifact, it suffices to create a POM file in the right subfolder.
The AAR file remains unchanged since Maven does not care about the artifact format.
Creating a Maven artifact can be automated with the maven-publish plugin, e.g.:
apply plugin: 'maven-publish'
publishing {
publications {
myRelease(MavenPublication) {
groupId 'com.foo'
artifactId 'my-artifact'
version '1.0.0'
artifact("$buildDir/outputs/aar/my-artifact.aar")
}
}
repositories {
maven {
url "$buildDir/repo"
}
}
}
However, since I do not really need to use Maven, the simpler choice is to add the version to the AAR file name.
I did this with the following snippet in the build.gradle of my library:
android.libraryVariants.all { variant ->
variant.outputs.all {
outputFileName = "${archivesBaseName}-${variant.name}-${defaultConfig.versionName}.aar"
}
}

Related

Android Gradle not finding remote AAR

I was working with Gradle v5.4 and Android Gradle Plugin v3.5.2, and had no problems!
I have a remote Artifactory repository where I upload .aar files that are needed in my project.
When I updated to Gradle v6.5 and Android Gradle Plugin v4.0.1 those .aar files are no longer downloaded.
This is how I add those dependencies:
implementation "ar.com.sebasira:some-library:1.0.0#aar"
This was working just fine before the upgrade.
In the logs I can see that AndroidStudio looks for it in this location:
https://myrepo.com.ar/ar/com/sebasira/some-library/1.0.0/some-library-1.0.0.pom
If I put that URL in the browser, indeed there's nothing to be found, but if I change the last part (the extension) to .aar I can download the artifact.
I thought that adding #aar was to instruct Gradle to look for .aar file but it seems not to be working.
I've also try adding the dependency like in this other way with no luck.
implementation group: 'ar.com.sebasira', name: 'some-library', version: '1.0.0', ext: 'aar'
I've found out that since Gradle v6.0 onwards, Gradle assumes that if no .pom file is present in the remote repository is because the artifact does not exists, so it does not look for it by default. According to release notes:
If Gradle fails to locate the metadata file (.pom or ivy.xml) of a module in a repository defined in the repositories { } section, it now assumes that the module does not exist in that repository.
...
You can opt into the old behavior for selected repositories by adding the artifact() metadata source.
So the solution is to add that to repository in question, like this:
repositories {
maven {
url 'the-repo-url'
metadataSources {
artifact()
}
}
}

Kotlin multiplatform library aar wont show sources when added as Dependency in Android Studio

I'm trying to publish a Kotlin Multiplatform library including sources using the maven-publish plugin. This is generally working but when I want to have a look at the code of the dependency inside my Android Studio project I can't see the sources but instead will see decompiled Kotlin code.
I tried several approaches of adding a sources.jar to the generated aar file already. Right now I'm following this approach: https://stackoverflow.com/a/28704799.
But I still can't see the sources(gradle clean cache and restart included).
Library build.gradle:
apply plugin: 'maven-publish'
task sourceJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier "sources"
}
publishing {
publications {
bar(MavenPublication) {
groupId 'com.foo'
artifactId 'bar'
version '0.1'
artifact(sourceJar)
artifact("$buildDir/outputs/aar/bar-release.aar")
}
}
repositories {
maven {
url "$buildDir/repo"
}
}
}
I also tried using different sourceSets like specifying one by name since the content of android.sourceSets.main.java.srcDirs is leading to a path where no sources are inside.
The library is included in the app project like this:
dependencies {
implementation 'com.foo:bar:0.1'
}
Looking at the local maven repository I can even see the bar-release-sources.jar but it seems like it's not part of the aar?

Maven publication of multi-modules android library

I am working on an Android SDK made of multiple library modules and a test app module:
mySDK
|-test-app
|-lib-core
|-lib-ui
|-...
I would like to publish it on a Maven repository, with all library modules embedded (but not the test-app).
I know how to publish a single library module using Maven Publish Plugin but can't figure out how to make a Maven publication containing multiple library modules.
How would you do that ?
Just upload each module as a standalone module.
It is not mandatory to upload all the modules at the same time, the dependencies are just described in the pom file.
It can be useful putting a base script in a single gradle file with some common settings and properties (you can read them from a gradle.properties file), something like:
rootFolder/maven_push.gradle:
apply plugin: 'maven'
//....
pom.artifactId = POM_ARTIFACT_ID
pom.project {
name POM_NAME
packaging POM_PACKAGING
description POM_DESCRIPTION
url POM_URL
//...
}
//...
and then in each module/build.gradle file add:
apply from: '../maven_push.gradle'
Each module is a library by itself, so configure each one of them (besides the app) to be packaged as AAR files and deployed to the desired repo. If you are going to use the Maven publish plugin, just apply the steps to each module(to the module's build.gradle files). A good practice is to centralize the groupId and version values, perhaps in the gradle.properties file, or in the main gradle file. Same procedure applies to other plugins, like the android-gradle-maven plugin.

How to publish in my maven local repository an existing aar with gradle?

I have a project that have the following structure:
projectRoot
build.gradle
module1/
build.gradle
artifact1.aar
module2/
....
My artifact1.aar is a compiled artifact and i have no access to the sources.
my module 1 gradle build file is the following:
configurations.maybeCreate("default")
artifacts.add("default", file('artifact1.aar'))
With this the code contains in the .aar is available in module 2 by simply reference a gradle project dependency.
But i want to publish the .aar in my maven local, in order that it can be accessible for other android project.
I check the maven-publish plugin and the android-maven-publish plugin but the two seems to be called after java-library plugin or com.android.library plugin.
So my question is how to publish in my maven local repository an existing aar with gradle ?
I'm using gradle in version 4.8.
I used an rxbinding aar for this example.
As you correctly mentioned, there has to be a subproject in the "publisher" project, which must contain the aar, and a build file with the following content:
// rxbinding/build.gradle
apply plugin: "maven-publish"
configurations.maybeCreate("default")
def publishArtifact = artifacts.add("default", file('rxbinding-2.1.1.aar'))
publishing {
publications {
aar(MavenPublication) {
groupId = 'my.sample.artifact'
artifactId = 'somerandomname'
version = '1.0.0'
artifact publishArtifact
}
}
}
You can apply the maven-publish plugin to any project, but then you have to define the artifacts manually, like we've just done here. Some plugins (like the java-library plugin) are integrated with the maven-publish plugin to automatically publish the default artifacts of the project.
Now run ./gradlew rxbinding:publishToMavenLocal - This should place the artifact into your local repo
Add implementation 'my.sample.artifact:somerandomname:1.0.0' to the consumer app, in any project on your machine.
It is very important to mention any aar published this way, will not bring it's dependencies, so you have to know what libs are needed to actually use the published aar.
I have also created an example project, where you can try this.
If you have maven installed, you could use the install-file goal of the maven-install-plugin.

How to develop a library and an application side-by-side in Android Studio?

I'm currently developing both a library (with no activities) and an application that depends on the library. Currently, I have these as separate projects, and I can copy the generated .aar file from the library project into the application project's libs folder, and re-sync gradle. However, this is an inefficient process because I have to rebuild and manually re-copy the .aar file every time I make a change to the library project. My question is, how can I streamline this process so that my application automatically uses the library's most recently generated .aar file?
1) In your app's settings.gradle include your lib as a project:
include ':lib-project'
project(':lib-project').projectDir = new File('../path/to/lib/project/lib-project')
The path to your lib project is relative to the settings.gradle location on your filesystem
2) in your app's build.gradle add lib project as a dependency:
dependencies {
compile project(':lib-project')
...
}
how can I streamline this process so that my application automatically uses the library's most recently generated .aar file?
Option #1: Dedicated Library
Step #1: Put your app project and the library project as children of a common root directory for the overall project. For the purposes of this answer, I'll call these app/ and library/, respectively.
Step #2: In the top level (i.e., the common root directory), have a settings.gradle file that lists these modules:
include ':app', ':library'
Step #3: In the top level, have a build.gradle file that sets up the Gradle for Android plugin and any other common stuff of interest, such as:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
(note that the above file is what you get from a native Android Studio project, created by the IDE)
Step #3: In the library/ directory, have a build.gradle file that uses the com.android.library plugin
Step #4: In the app/ directory, have a build.gradle file that has compile project(':library') in its dependencies to pull in the library
It may be that your AAR is the deliverable, not the app (e.g., the library is an open source one for community use, and the app is a demo app). In that case, you might use debugCompile in app/ to pull in the local library project for debug builds, but have releaseCompile to pull in the AAR from a published source, to confirm that you can build from the same thing that users of the AAR use.
Most of my CWAC libraries are set up this way (e.g., cwac-richedit).
Option #2: Publish the AAR Locally
You can use the maven plugin and the uploadArchives task to upload to a local Maven-style repo:
apply plugin: 'maven'
uploadArchives {
repositories.mavenDeployer {
pom.groupId = PUBLISH_GROUP_ID
pom.artifactId = PUBLISH_ARTIFACT_ID
pom.version = PUBLISH_VERSION
repository(url: LOCAL_REPO)
}
}
Here, my constants are pulled in from a gradle.properties file, and LOCAL_REPO is a file:/// URL pointing to a local repo. You can then run gradle uploadArchives to generate the AAR and push it to the local repo.
Then, your app can have a maven { url LOCAL_REPO } closure in the repositories closure, and can pull in the AAR artifact from there as if it was coming from a public repo (e.g., Maven Central).
My CWAC libraries use the uploadArchives task, but only for publishing to my local mirror of my Amazon S3-hosted Maven repo.
This approach would be if you really wanted to work off of the AAR, but wanted to do so from multiple projects. Note that you can certainly publish this to some other sort of Maven repo (e.g., a Sonatype server) for enterprise use.
Option #3: Mod a Module to Point to the Library Elsewhere
This is Pavel Dudka's approach in his answer. I haven't tried this. Off the cuff, this would be a good approach if you want to depend upon the library from multiple apps, but you're not really concerned about having an actual AAR as a thing to distribute around.
And I'm sure there are other options than these three.

Categories

Resources