In daily development, it is inevitable to publish your library to a Maven repository, which makes it easier to use.

Publish aar packages to the Maven repository using Gradle plugins:

  1. Maven plugin (old version), completely Deprecated after Gradle 6.2 (added the @deprecated annotation)

  2. Maven – publish plug-in

Maven plugin is a plugin provided in Gradle 1.0 for publishing AAR/JAR packages to Maven repositories. In Gradle 1.3, a new publishing plug-in, maven-publish, was introduced. This new plug-in introduces some new concepts and features that make Gradle publishing more powerful and is now the preferred option for publishing artifacts.

1. Basic Concepts


1. What is POM?

Project Object Model (POM) refers to the Project Object Model, which describes the basic information of Project components. A valid POM node contains the following information:

configuration describe For instance (‘ com. Making. Bumptech. Glide: glide: 4.11.0 ‘)
groupId Name of organization/company com.github.bumptech.glide
artifactId Component name glide
version Component version 4.11.0
packaging Packaged format aar/jar

2. What is a repository?

In a project, we will need to rely on various binary and tripartite libraries. These dependencies must be stored in a Place called a repository. Using repositories helps us manage project artifacts, such as JARS, AArs, and so on.

Mainstream build tools have a three-tiered warehouse concept:

  • 1. Local repository: Whether Linux or Windows is used, the computer has a directory for storing dependent files downloaded from the central repository or remote repository.
  • 2. Central Repository: The repository provided by the open source community where the vast majority of open source libraries are stored. For example, Maven Central, the community’s Central repository;
  • 3. Private warehouse: a custom warehouse of a company or organization, which can be understood as the storage location of a two-party library.

Build time searches for dependencies in the following order:

  • 1. Search in the local repository. If no, go to Step 2.
  • 2. Search in central warehouse and private warehouse in the order ofrepositoriesFind the order of the declarations in. If yes, download the dependent files to the local repository. If no, go to Step 3.
  • 3. If the dependency cannot be found, an error “cannot find dependency” is thrown.

With these basic concepts in mind, here is how to publish aar/ JAR packages through the Maven and Maven-publish plug-ins provided by Gradle.

Second,Maven plug-in


Maven plug-in is 1.0 when Gradle, using document: docs.gradle.org/4.8/usergui…

To use the Maven plugin, follow these steps:

1. Use the Maven plugin

In the build.gradle file of the library module that needs to publish the AAR package, apply the Maven plugin:

apply plugin: "maven"
Copy the code

2. Configure POM

In the build.gradle file, add the following configuration information:

def localDefaultRepo = "file://" + new File(System.getProperty("user.home"), '.m2/repository').absolutePath
uploadArchives {
    repositories.mavenDeployer {
        / / repository (url: uri (' ~ / m2 / repository)) / / comment 1
        // Configure the warehouse address
        repository(url: uri(localDefaultRepo))
        // repository(url: uri('.. /repo'))
      
        // Configure POM information
        pom.groupId "com.mei.http"
        pom.artifactId "myhttp"
        pom.version "1.0.0 - the SNAPSHOT"
        pom.packaging "aar"
      
      	// pom.project {
        // groupId "com.mei.http"
        // artifactId "myhttp"
        / / version 1.0.1 - the SNAPSHOT ""
        // packaging "aar"
        // }}}Copy the code

As shown above, specify the address of the warehouse and configure poM information. Once configured, you can see the Upload /uploadArchives task in the task task list.

The repository address configured here is a local path to publish the AAR to a local folder. USER_HOME/.m2/repository/ is Gradle’s default local repository location, where USER_HOME is the user directory.

2-1. Default local repository

[root@localhost] [root@localhost] [root@localhost] [root@localhost] [root@localhost]

repository(url: uri('/.m2/repository'))
println "path=${uri('~/.m2/repository')}"
Copy the code

Printed path:

path=file:/Users/mei/WorkSpace/AndroidDemo/MAarPublish/myhttpjava/~/.m2/repository/

After the uploadArchives task is executed, there is no AAR file in the USER_HOME/.m2/repository/ directory, such as:

So at this point, the AAR file cannot be loaded to use.

implementation 'com. Mei. HTTP: myhttp: 1.0.0 - the SNAPSHOT'
Copy the code

What’s causing this? It’s just a path problem.

When absolute paths are used, that is:

def localDefaultRepo = "file://" + new File(System.getProperty("user.home"), '.m2/repository').absolutePath
Copy the code

When localDefaultRepo is used for the repository, the aar package can be seen in the USER_HOME/.m2/repository/ directory, as shown in the following example:

Then the AAR package is released.

use

In the build.gradle file of the project, introduce the default local repository, such as:

allprojects {
    repositories {
        .....
        mavenLocal() // Use the default local repository}}Copy the code

In your app’s build.gradle file, reference the myhttp library:

dependencies {
		.....
    implementation 'com. Mei. HTTP: myhttp: - the SNAPSHOT 1.0.1'
}
Copy the code

This way, you can use the code in myhttp in your app.

2-2. Customize the local warehouse

In addition to using the default local repository, you can also specify a custom local repository, that is, you can specify a directory as the local repository, for example:

uploadArchives {
    repositories.mavenDeployer {
        // Configure the warehouse address
        repository(url: uri('.. /repo'))
      
        // Configure POM information
        pom.groupId "com.mei.http"
        pom.artifactId "myhttp"
        pom.version "1.0.0 - the SNAPSHOT"
        pom.packaging "aar"}}Copy the code

Create a repo folder in the root directory of this project, and use it as a local repository. After executing uploadArchives, you can see the repo directory in the root directory of this project.

Build. Gradle (” aar “); build. Gradle (” aar “);

allprojects {
    repositories {
				.....
       maven {
           url '.. /repo' // If this is the path of the project, you can directly display it like this}}}Copy the code

If other projects want to use the library, they need to use the absolute path, i.e. :

allprojects {
    repositories {
				.....
       maven {
           url '/Users/mei/WorkSpace/AndroidDemo/MAarPublish/repo'}}}Copy the code

3. Upload source code and documents

Through the above steps, the AAR is basically released successfully, but the aar package code, no comments, no source code, just decompile some code information, the experience is not very good, such as:

The problem is that the source code and documentation are not uploaded when the AAR file is uploaded.

3-1. Upload the source code

Reference: docs.gradle.org/current/dsl…

Create a Task to upload source code as follows:

task uploadSourceJar(type: Jar) {
  Myhttp-1.0.2-20210927.115550-2-sources.jar = myhttp-1.0.2-20210927.115550-2-sources.jar
    classifier = 'sources'
    println "srcDirs=${project.android.sourceSets.main.java.sourceFiles}"
  // Specify the source file path
    from project.android.sourceSets.main.java.sourceFiles
}

// Specify the task to be executed when the packet is sent
artifacts {
    archives uploadSourceJar
}
Copy the code

After adding the above code, upload the source code when executing the uploadArchives task as follows:

In Android Studio, check out the source code for myHTTP as follows:

You can actually see the source code and comments.

Extension: an artifact

The Artifact method provides Object objects, what are they? There are three main types.

  1. artifact 'my-file-name.jar'Specific documents.
  2. artifact sourceJartasksourceJarOutput, such as here, is packaged with source codeJarThe package.
  3. artifact source: sourceJar, classifier: 'src', extension: 'zip'throughsource,classifierAs well asextensionStructure of theMavenArtifactInstance, parameter corresponding to the source file, name category (artifactId-classifier) and the extension name (.jar/.zip, etc.).

3-2. Generate a document and upload it

Reference Documents:

  • Docs.gradle.org/current/dsl…
  • Blog.didispace.com/books/Gradl…

By doing this, the source code is uploaded to the Maven repository, and the source and comment information is available when referencing the AAR file.

If it’s an SDK, then you need to upload the document for easy access.

task androidJavadocs(type: Javadoc) {
    doLast {
        source = project.android.sourceSets.main.java.srcDirs
        // Need to generate doc code path
        classpath += project.files(project.android.getBootClasspath().join(File.pathSeparator))
        failOnError = false // The task does not stop abnormally if javadoc parsing fails}}// Resolve JavaDoc Chinese comment generation failure
tasks.withType(Javadoc) {
    options.addStringOption('Xdoclint:none'.'-quiet')
    options.addStringOption('encoding'.'UTF-8')
    options.addStringOption('charSet'.'UTF-8')
}

task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
    doLast {
        //archiveFileName The archive name. If the name has not been explicitly set
        // , the pattern for the name is:
        //[archiveBaseName]-[archiveAppendix]-[archiveVersion]-[archiveClassifier].[archiveExtension]
        // the classifier part of the archive name, followed by the class-specific name. e.g. xxxx-javadoc.jar
        classifier = 'javadoc'
        from androidJavadocs.destinationDir
    }
}

artifacts {
    // Add comments to aar packages
    archives androidJavadocsJar
}
Copy the code

Add the code above to generate a Java document.

4. Upload the remote Maven repository

To upload an AAR package to a remote Maven repository, simply replace the maven repository address above with the remote Maven repository address. In addition, you need to provide the Maven repository user name and password, as private maven repositories are usually required to build a user name and password.

Details are as follows:

uploadArchives {
    repositories.mavenDeployer {
      / / assume that remote maven warehouse address is: http://10.0.192.56:8081/repository/core/
      // Account: meiTest, password: 123456
        repository(url: "http://10.0.192.56:8081/repository/core/") {
            authentication(userName: "meiTest", password: "123456")}// Configure POM information
        pom.groupId "com.mei.http"
        pom.artifactId "myhttp"
        pom.version "1.0.0 - the SNAPSHOT"
        pom.packaging "aar"}}Copy the code

As shown above, replace the Maven repository address and add the repository account and password to upload to the remote repository.

use

To upload the AAR package to maven private repository, you need to verify the account and password, and also verify the account and password when using the aar package. For example:

allprojects {
    repositories {
        ....
        // Specify the private server path and account password
        maven{
            url 'http://10.0.192.56:8081/repository/core/'
            credentials {
                username = "meiTest"
                password = "123456"}}}}Copy the code

Three,Maven – publish plug-in


Plugin class: MavenPublishPlugin

Documents:

  • Maven-publish plugin documentation

  • MavenPublication Parameter description

After Gradle 6.2, the Maven plugin is completely deprecated and can only be used with Maven-publish. Therefore, the maven-publish plugin is also required. Here’s how to use it.

Maven-publish plugin basic use

Application plug-in:

apply plugin: "maven-publish"
Copy the code

When maven-publish is used to publish an AAR package, the basic configuration information is as follows:

publishing {
    // Configure the Maven repository
    repositories { RepositoryHandler handler->
        handler.mavenLocal()  // Publish to the default local Maven repository USER_HOME/.m2/repository/
    }
  // Configure the publication artifacts
    publications {PublicationContainer publication->
      // The name can be defined arbitrarily. Here I define it as Maven because my AAR package is published to the Maven repository, so I define it as Maven for its own good
      // Name: maven
        maven(MavenPublication) {// Container-configurable information MavenPublication
            // Rely on the bundleReleaseAar task and upload its output AAR
            afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) }
            groupId = "com.mei.http"
            artifactId = "myhttp"
            version = "1.0.4 - the SNAPSHOT"}}}Copy the code

Maven-publish PublishingExtension PublishingExtension maven-publish PublishingExtension PublishingExtension PublishingExtension PublishingExtension PublishingExtension PublishingExtension PublishingExtension PublishingExtension PublishingExtension PublishingExtension PublishingExtension PublishingExtension

  • Repositories: Used to configure the Maven repository address

    Multiple addresses can be configured, and when a publish task is performed, the AAR package is published to all specified Maven repository addresses.

    repositories { RepositoryHandler handler ->
        handler.mavenLocal()
        handler.maven {
            url "${rootDir}/repo"
        }
        // Warehouse user name and password
        // handler.maven { MavenArtifactRepository mavenArtifactRepository ->
        // // Maven repository address
        / / url 'http://10.0.192.56:8081/repository/core/'
        // // Account and password for accessing the warehouse
        // credentials {
        // username = "meiTest"
        // password = "123456"
        / /}
        // }
    }
    Copy the code
  • Publications: Configures information about the JAR to be published, that is, information about the product AAR package. Publications is a container whose type is PublicationContainer, and whose information type can be configured is MavenPublication. Publications is a set of lists, and the objects stored in the set are MavenPublication, and the names of the objects can be defined by themselves. Therefore, multiple publications can be configured, such as:

    publications { PublicationContainer publicationContainer ->
      // Publish the snapshot package
        debug(MavenPublication) {
            afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) }
            groupId = "com.mei.http"
            artifactId = "myhttp"
            version = "1.0.4 - the SNAPSHOT"
        }
      // Release the official package
        release(MavenPublication) {
            afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) }
            groupId = "com.mei.http"
            artifactId = "myhttp"
            version = "1.0.4"
        }
    Copy the code

Publish the aar:

After the above configuration is added, you can publish the AAR package by executing the Publishing /publish task in the Tasks list on the right of the AS.

After configuring the two release products, debug and Release, you can see that there are indeed official packages and test packages in the default local repository, as shown in the following figure:

2. Upload the source code

Maven-publish: maven-publish: maven-publish: maven-publish: maven-publish: Maven-publish: Maven-publish: Maven-publish: Maven-publish: Maven-publish: Maven-publish: Maven-publish

The user is prompted to select the source code. You can see the code here, which was decomcompiled by Android Studio from bytecode. So you need to upload the source code here.

Add tasks to upload source code, for example:

// 1. Add task to upload source code
task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    archiveClassifier = "sources"
}

publishing {
    repositories { RepositoryHandler handler ->
        handler.mavenLocal()
    }
    publications { PublicationContainer publicationContainer ->
        maven(MavenPublication) {
            artifact sourceJar // Add task to upload source code
          
            afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) }
            groupId = "com.mei.http"
            artifactId = "myhttp"
            version = "1.0.5 - the SNAPSHOT"}}}Copy the code

After adding the code in the comments above, the AAR package is uploaded along with the source code when it is released, as in:

As can be seen from the above code, source code is indeed uploaded, comments can be seen.

3. Dependency passing

By following the steps above, the aar package is released without dependency passing, as shown in demo: After publishing an AAR package and referencing myHttpjava, which relies on OkHttp, the OKHTTP-related Api cannot be used in the APP project because the dependency is not passed through. In the APP module:

Dependencies {... implementation'com. Mei. HTTP: myhttp: 1.0.4 - the SNAPSHOT'
}
Copy the code

Okhttp-related apis are not available, but myHttpjava’s own classes can be called, such as:

As you can see from the figure above, the OkHttp dependency is indeed not passed through.

In the Maven repository, you can open the.pom file as shown:

MyHttpjava library (); myHttpjava library ();

This is just myHttpjava’s declaration information, not dependent libraries such as OkHttp’s declaration information. Aar packages published using the Maven plugin are delivered by default, such as:

Of course, the Maven-publish plugin also provides support for dependency passing. Add the library dependency information manually to the POM file (see MavenPom class for configuration information).

maven(MavenPublication) {
    // Rely on the bundleReleaseAar task and upload its output AAR
    afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) }
    artifact sourceJar
    groupId = "com.mei.http"
    artifactId = "myhttp"
    version = "1.0.6 - the SNAPSHOT"
    // The dependency is declared in the POM file and passed to the user
    pom.withXml {
        def dependenciesNode = asNode().appendNode('dependencies')
        configurations.implementation.allDependencies.each {
            // Avoid empty nodes or artifactId= Unspecified nodes
            if(it.group ! =null&& (it.name ! =null && "unspecified"! = it.name) && it.version ! =null) {
                println "dependency=${it.toString()}"
                def dependencyNode = dependenciesNode.appendNode('dependency')
                dependencyNode.appendNode('groupId', it.group)
                dependencyNode.appendNode('artifactId', it.name)
                dependencyNode.appendNode('version', it.version)
                dependencyNode.appendNode('scope'.'implementation')}}}}Copy the code

Add the above POM module. When publishing the AAR package, open the POM file and see the declaration information of the dependent library, as shown in the figure below:

When using the myHTTP library in the APP module, the OkHttp Api is available, although the OkHttp library is still not referenced manually. Indicates that the dependency is indeed passed.

We can also see whether a dependency is passed by printing the information of the dependency library, such as:

Information configured in the POM closure will be saved in the. Pom file, such as description, name, licenses, developers, SCM, etc., for example:

pom {
    name = "Demo"
    description = "A demonstration of Maven POM customization"
    url = "http://www.example.com/project"
}
Copy the code

Results:

Release the AAR package of Kotlin project and upload the source code


When configuring the task of uploading source code, the basic configuration is as follows:

task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    archiveClassifier = "sources"
}
Copy the code

In this configuration, if the library project is written in Java, the source code can be uploaded normally, but if the library is written by Kotlin, the source code cannot be viewed when the AAR package is published.

Through the android. SourceSets. Main. Java. SrcDirs specify source, only to recognize the Java file, the kt file is ignored, but by looking at the official documentation, can know the from functions is to specify the source path, So replace the argument to the from function with the source path:

task sourceJar(type: Jar) {
    from android.sourceSets.main.java.getSrcDirs() // The source path
    archiveClassifier = "sources"
}
Copy the code

When you publish the AAR package, you will find that the source code is normally accessible.

Conclusion:


1.The maven-publish plugin differs from maven:

  • The Maven plugin is old and simple to configure, and was completely abandoned after Gradle 6.2.
  • The Maven-publish plugin, which has been supported since Gradle 1.3, is now the common solution. It is more powerful and slightly more complex to configure, but it is still recommended.

2. Reference:

  • The Android AAR package is published to the Maven repository summary
  • Android engineering practice: Componentized release
  • Create and build local or remote Maven repositories
  • Maven-publish: Publish android Library to Maven repository
  • Publish the Kotlin project AAR package containing the source code to Maven