39

Since I cannot use a private maven in order to share my library, I was thinking in sharing the aar and importing into another project. The problem comes when the aar and jar files does not contain any dependency. So once I manually import the aar in android studio (using Import .JAR/.AA Package) there is no dependency, and I have to manually add all dependencies again. I already generated a pom file through a gradle task, although I cannot find any way to manually import it on the project.

On the build.gradle file automatically generated by the "Import .JAR/.AA Package" is:

configurations.maybeCreate("default")
artifacts.add("default", file('TestSample_1.0.0.aar'))

Is there a way to add the pom/iml file too? something like:

artifacts.add("default", file('pomDependencies.xml'))
Luis Pereira
  • 1,481
  • 3
  • 19
  • 46
  • In my experience you can't do it. Using an aar file you have to add the dependencies manually in your build.gradle. – Gabriele Mariotti Jan 19 '16 at 09:12
  • Thanks for your response @Gabriele Mariotti . Although I have a question, because the gradle knows it when it is compiling from a maven repository, doing something like this: compile "com.lib.testsample:testSample:1.0.0" – Luis Pereira Jan 19 '16 at 09:15
  • Using a maven repo gradle searches for the pom file which describes the dependencies. But using a flat dir to import the aar file I don't know a way to add the same pom file. – Gabriele Mariotti Jan 19 '16 at 09:18
  • When you say `private maven` do you mean a repo like Nexus or Artifactory? You can always publish to a filesystem based repo as well, kind of like your local .m2 directory and then consume your aar from a different build on the same machine, getting all the benefits of transitive dependencies. Is this something that would work for you? – RaGe Jan 19 '16 at 21:24
  • Hi @RaGe, that is interesting so I can publish to a local filesystem and then somebody else can consume the distributed directory on different machines as well with all the dependencies? – Luis Pereira Jan 20 '16 at 08:56
  • Well that's exactly what I'm thinking, but let me try this out to see that it actually works, I don't have an aar producing project handy, will try this later tonight and update. – RaGe Jan 20 '16 at 18:08

2 Answers2

59

1. Publishing

In your aar project, add maven-publish plugin and add necessary plugin configuration.

apply plugin: 'com.android.library'
apply plugin: 'maven-publish'

...

dependencies {
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.novoda:bintray-release:0.2.7'
}
    
...

publishing {
    publications {
        maven(MavenPublication) {
            groupId 'com.example' //You can either define these here or get them from project conf elsewhere
            artifactId 'example'
            version '0.0.1-SNAPSHOT'
            artifact "$buildDir/outputs/aar/app-release.aar" //aar artifact you want to publish

            //generate pom nodes for dependencies
            pom.withXml {
                def dependenciesNode = asNode().appendNode('dependencies')
                configurations.compile.allDependencies.each { dependency ->
                    def dependencyNode = dependenciesNode.appendNode('dependency')
                    dependencyNode.appendNode('groupId', dependency.group)
                    dependencyNode.appendNode('artifactId', dependency.name)
                    dependencyNode.appendNode('version', dependency.version)
                }
            }
        }
    }
    
    //publish to filesystem repo
    repositories{
        maven {
            url "$buildDir/repo"
        }
    }
}

Few things to note:

  1. We're using a custom maven publication, so you have to define what is being published with the artifact clause

  2. We have to generate the pom ourselves, in the code above I'm using all compile config dependencies, you may want to make sure all the configs you care about are covered.

Running gradle publish will publish to a maven repo structure to the repo folder, which you can then consume from a different project.

2. Using published .aar

In a different android project, to use the aar published in #1: In top level build.gradle:

allprojects {
    repositories {
        jcenter()
        maven {
            url "D:/full/path/to/repo"
        }
    }
}

add the path to earlier repo as a maven repository. Note that you may have to use the full path, because $buildDir has a different value for this project. In your app build.gradle:

dependencies {
    ...
    other dependencies
    ...
    implementation ('com.example:example:0.0.1-SNAPSHOT@aar'){transitive=true}
}

transitive=true is required for to fetch the transitive dependencies from the pom file.

RaGe
  • 22,696
  • 11
  • 72
  • 104
  • Publishing to a local maven and then compiling from that directory totally helps, because I can share the directory whenever I want with all dependencies. Thanks @RaGe – Luis Pereira Jan 21 '16 at 09:24
  • BTW, It is a tad bit hacky, but it is possible to host a maven repo on git – RaGe Jan 21 '16 at 15:11
  • Publication should be `MavenPublication` as the error says, and as my code above shows. – RaGe Feb 20 '18 at 15:47
  • Great answer. But what if I had imported some .aar file in my library how do I include that? – Danish Ansari Jul 12 '19 at 12:24
  • @RaGe i have the pom file included in the artifacts also. But still i keep getting the classNotFoundException. Do you have any insights on this? – Kaveri Sep 05 '19 at 12:43
  • 1
    @Kaveri are you able to resolve the issue, because I am also getting the same. – vinita jain Mar 07 '20 at 00:31
  • 1
    FYI, Use 'configurations.implementation' instead of 'configurations.compile' if you're adding dependencies using 'implementation' :) – Vipul Kumar Oct 27 '20 at 13:13
14

Things have changed a little, here's how you do it with the latest versions of gradle

Create the package localy (aar and pom)

Modify your library build.gradle file to include

apply plugin: 'maven-publish'

android {
    ...
    ...
}

dependencies {
    ...
    ...
}

publishing {
    publications {
        maven(MavenPublication) {
            groupId 'com.domain' //You can either define these here or get them from project conf elsewhere
            artifactId 'name'
            version '1.0.0'
            artifact "$buildDir/outputs/aar/sdk-release.aar" //aar artifact you want to publish

            //generate pom nodes for dependencies
            pom.withXml {
            def dependenciesNode = asNode().appendNode('dependencies')
            configurations.implementation.allDependencies.each { dependency ->
                if (dependency.name != 'unspecified') {
                    def dependencyNode = dependenciesNode.appendNode('dependency')
                    dependencyNode.appendNode('groupId', dependency.group)
                    dependencyNode.appendNode('artifactId', dependency.name)
                    dependencyNode.appendNode('version', dependency.version)
                }
            }
        }
    }

    //publish to filesystem repo
    repositories{
        maven {
            url "$buildDir/repo"
        }
    }
}

Run from terminal

./gradlew clean
./gradlew build
./gradlew --console=verbose publishToMavenLocal

The aar and pom files have been created at $HOME/.m2/repository/

How to load the library from a different project

Modify the projects's build.gradle in the following way:

allprojects {
    repositories {
        maven {
            url "/Users/username/.m2/repository/"
        }
        google()
        jcenter()
    }

You can use $rootDir and set a relative path.

Add the library as a dependency in your app module build.gradle

implementation 'com.domain:name:1.0.0'

Aviran
  • 5,160
  • 7
  • 44
  • 76