1. Gradle push | Maven Plugin Publish the Plugin

The Maven Publish plug-in provides the ability to Publish build artifacts to the Apache Maven repository. Modules published to the Maven repository can be used by Maven, Gradle, and other tools that understand the format of the Maven repository.

1.1 add-in task | the Tasks

  • Generate MavenPom PubName generatePomFileFor * * Publication –

    Create a POM file for a publication named PubName and populate it with known metadata, such as project name, project version, and dependencies. The default location for POM files is build/publications/$pubName/ POM-default.xml.

  • The publish * RepoName PublicationTo PubName * * * Repository – PublishToMavenRepository

    Publish the PubName publication to a repository named RepoName. If you have a repository definition without an explicit name, RepoName will be “Maven”.

  • The publish * PubName * PublicationToMavenLocal – PublishToMavenLocal

    Copy PubName publications along with published POM files and other metadata to the local Maven cache — typically *$USER_HOME/.m2/repository*.

  • publish

    Depends on: All tasks publish*PubName*PublicationTo*RepoName*Repository Aggregate tasks that publish all defined publications to all defined repositories. It does not include the local Maven cache for replication publications.

  • publishToMavenLocal

    Depends on: All tasks publish*PubName*PublicationToMavenLocal copies all defined publications to the local Maven cache, including their metadata (POM files, etc.).

/ / generated MavenPom
generateMetadataFileForDebugPublication
generateMetadataFileForReleasePublication
generatePomFileForDebugPublication 
generatePomFileForReleasePublication

//PublishToMavenRepository
publish
publishAllPublicationsToMavenRepository
publishDebugPublicationToMavenRepository
publishReleasePublicationToMavenRepository

//PublishToMavenLocal
publishToMavenLocal
publishDebugPublicationToMavenLocal
publishReleasePublicationToMavenLocal

Use the following command if your project uses the Gralde Wrapper component
./gradlew task [name]
./gradlew task :lib-net:publishToMavenLocal
Copy the code

1.2 build product | Publications

There are four main things you can configure in Maven publications:

  • A componentFor example, a Java Module, Android Library Module
    • Through this method to specify MavenPublication. The from (org.gradle.api.com ponent. SoftwareComponent)
  • Custom artifacts
    • Custom built products through this method MavenPublication. An artifact (java.lang.object) method.
  • Standard metadata
    • For example, artifactId, groupId, and Version.
  • Other configurations of POM files
    • Set mavenvenvenes.pom (org.gradle.api.action) with this method

1.3 warehouse | Repositories

The plug-in provides a repository of type Mavenartice Repository

Define the publication repository:

publishing {
   repositories {
      maven {
          url "url"
          credentials {
              username = 'name'
              password = 'pwd'}}}}Copy the code

Snapshot and release repositories

publishing {
    repositories {
        maven {
            def releasesRepoUrl = layout.buildDirectory.dir('repos/releases')
            def snapshotsRepoUrl = layout.buildDirectory.dir('repos/snapshots')
            url = version.endsWith('SNAPSHOT')? snapshotsRepoUrl : releasesRepoUrl } } }Copy the code

1.4 Complete Example

The following example demonstrates how to sign and distribute Java libraries containing source code, Javadoc, and custom POM:

build.gradle

plugins {
    id 'java-library'
    id 'maven-publish'
    id 'signing'
}

group = 'com.example'
version = '1.0'

java {
    withJavadocJar()
    withSourcesJar()
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            artifactId = 'my-library'
            from components.java
            versionMapping {
                usage('java-api') {
                    fromResolutionOf('runtimeClasspath')
                }
                usage('java-runtime') {
                    fromResolutionResult()
                }
            }
            pom {
                name = 'My Library'
                description = 'A concise description of my library'
                url = 'http://www.example.com/library'
                properties = [
                    myProp: "value"."prop.with.dots": "anotherValue"
                ]
                licenses {
                    license {
                        name = 'The Apache License, Version 2.0'
                        url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                developers {
                    developer {
                        id = 'johnd'
                        name = 'John Doe'
                        email = '[email protected]'
                    }
                }
                scm {
                    connection = 'scm:git:git://example.com/my-library.git'
                    developerConnection = 'scm:git:ssh://example.com/my-library.git'
                    url = 'http://example.com/my-library/'
                }
            }
        }
    }
    repositories {
        maven {
            // change URLs to point to your repos, e.g. http://my.org/repo
            def releasesRepoUrl = layout.buildDirectory.dir('repos/releases')
            def snapshotsRepoUrl = layout.buildDirectory.dir('repos/snapshots')
            url = version.endsWith('SNAPSHOT')? snapshotsRepoUrl : releasesRepoUrl credentials { username ='name'
              password = 'pwd'
            }
        }
    }
}

signing {
    sign publishing.publications.mavenJava
}


javadoc {
    if(JavaVersion.current().isJava9Compatible()) {
        options.addBooleanOption('html5'.true)}}Copy the code

As a result of the above configuration, the following artifacts will be published:

  • POM file:My - library - 1.0. Pom
  • Key JAR artifacts:My - library - 1.0. The jar
  • Explicitly configured source code:My - library - 1.0 - sources. The jar
  • Explicitly configured Javadoc:My - library - 1.0 - the javadoc. Jar

The signature plug-in is used to generate a signature file for each artifact. In addition, checksum files are generated for all artifacts and signature files.

1.5 Using Maven to distribute plug-ins in Android

Android Gradle plugin 3.6.0 and later includes support for the Maven Publish Gradle plugin, which allows you to Publish build artifacts to the Apache Maven repository. The Android Gradle plug-in creates a component for each build variant artifact in your application or library module that you can use to customize and publish to the Maven repository.

The components created by Android plug-ins depend on whether the module uses an application plug-in or a library plug-in, as described in the following table.

Android Gradle plug-in Published artifact Component name
com.android.library AAR components.variant
com.android.application APK ZIP, and available ProGuard or R8 mapping files components.variant_apk
com.android.application An Android Application Package (AAB) components.variant_aab

1.6 Example for Android

// Because the components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.
afterEvaluate {
    publishing {
        publications {
            // Creates a Maven publication called "release".
            release(MavenPublication) {
                // Applies the component for the release build variant.
                from components.release
                // You can then customize attributes of the publication as shown below.
                groupId = GROUP
                artifactId = ARTIFACT_ID
                version = VERSION

            }
            // Creates a Maven publication called “debug”.
            debug(MavenPublication) {
                // Applies the component for the debug build variant.
                from components.debug
                groupId = GROUP
                artifactId = ARTIFACT_ID + "-debug"
                version = VERSION
            }
        }
        repositories {
            maven {
                // change URLs to point to your repos, e.g. http://my.org/repo
                url = URL
                credentials {
                    username USER_NAME
                    password PASSWORD
                }
            }
        }
    }
}



Copy the code

1.7 Android Custom POM File version Example

apply plugin: 'maven-publish'

println("-- -- -- -- -- -- -- - ${project. The name} : Maven Publish Gradle -- -- -- -- -- -- -- --")
// Release and snapshot control switches
def isUploadToRelease = rootProject.ext.mavenRepo['isUploadToRelease']
// The remote Maven repository URL Release
def MAVEN_REPO_RELEASE_URL = rootProject.ext.mavenRepo['mavenRepoUrlRelease']
// Call the snapshots of the remote Maven repository
def MAVEN_REPO_SNAPSHOTS_URL = rootProject.ext.mavenRepo['mavenRepoUrlSnapshots']
// Remote Maven repository user name
def USER_NAME = rootProject.ext.mavenRepo['userName']
// Remote Maven repository password
def PASSWORD = rootProject.ext.mavenRepo['password']
// Uniquely identifies each component to be specified
def GROUP = group.toString()
// Todo defaults to the project name
def ARTIFACT_ID = project.name
// The version number is specified for each component
def VERSION = version.toString()
// Remote Maven repository URL
def URL = isUploadToRelease ? MAVEN_REPO_RELEASE_URL : MAVEN_REPO_SNAPSHOTS_URL

println("dependencies_path: $GROUP:$ARTIFACT_ID:$VERSION")
println("MAVEN_REPO_RELEASE_URL: $MAVEN_REPO_RELEASE_URL")
println("MAVEN_REPO_SNAPSHOTS_URL: $MAVEN_REPO_SNAPSHOTS_URL")


/ / https://docs.gradle.org/7.0/userguide/publishing_maven.html#publishing_maven
//https://developer.android.com/studio/build/maven-publish-plugin

// Because the components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.


task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier "sources"
}

afterEvaluate {
    publishing {
        publications {
            maven(MavenPublication) {
                groupId GROUP
                artifactId ARTIFACT_ID
                version VERSION
                artifact bundleReleaseAar
                artifact sourceJar

                // Configure a POM based on the input data.
                pom.withXml {
                 
                    final dependenciesNode = asNode().appendNode('dependencies')

                    //dependenciesNode:dependencies[attributes={}; value=[]]
                    println "dependenciesNode:" + dependenciesNode
                    ext.addDependency = { Dependency dep, String scope ->
                        / / the Dependency: DefaultExternalModuleDependency {group = 'com. Qlife. Android', name = 'lib - baidu - face, version = "1.0.0", configuration='default'}
                        //scope:compile
                        println "Dependency:" + dep
                        println "scope:" + scope

                        if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
                            return // invalid dependencies should be ignored

                        final dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('artifactId', dep.name)

                        if (dep.version == 'unspecified') {
                            dependencyNode.appendNode('groupId', project.ext.pomGroupID)
                            dependencyNode.appendNode('version', project.ext.pomVersion)
                            System.println("${project.ext.pomGroupID} ${dep.name} ${project.ext.pomVersion}")}else {
                            dependencyNode.appendNode('groupId', dep.group)
                            dependencyNode.appendNode('version', dep.version)
                            System.println("${dep.group} ${dep.name} ${dep.version}")
                        }

                        dependencyNode.appendNode('scope', scope)
                        // Some dependencies may have types, such as AAR, which should be mentioned in the POM file
                        // Some dependencies may have types, such as aar, that should be mentioned in the POM file
                        def artifactsList = dep.properties['artifacts']
                        if(artifactsList ! =null && artifactsList.size() > 0) {
                            final artifact = artifactsList[0]
                            dependencyNode.appendNode('type', artifact.getType())
                        }

                        if(! dep.transitive) {// In the case of non-passable dependencies, all of its dependencies should be forcibly excluded from the POM file
                            // In case of non transitive dependency, all its dependencies should be force excluded from them POM file
                            final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
                            exclusionNode.appendNode('groupId'.The '*')
                            exclusionNode.appendNode('artifactId'.The '*')}else if(! dep.properties.excludeRules.empty) {// For passes with exclusion, all exclusion rules should be added to the POM file
                            // For transitive with exclusions, all exclude rules should be added to the POM file
                            final exclusions = dependencyNode.appendNode('exclusions')
                            dep.properties.excludeRules.each { ExcludeRule rule ->
                                final exclusionNode = exclusions.appendNode('exclusion')
                                exclusionNode.appendNode('groupId', rule.group ? :The '*')
                                exclusionNode.appendNode('artifactId', rule.module ? :The '*')}}}// List all "api" dependencies (for new Gradle) as "compile" dependencies
                    configurations.api.getDependencies().each { dep -> addDependency(dep, "compile")}// List all "implementation" dependencies (for new Gradle) as "runtime" dependencies
                    configurations.implementation.getDependencies().each { dep -> addDependency(dep, "runtime") }

                }
            }
        }
        repositories {
            maven {
                url = URL
                credentials {
                    username USER_NAME
                    password PASSWORD
                }
            }
        }
    }
}

task cleanBuildPublishLocal(type: GradleBuild) {
    tasks = ['clean'.'build'.'publishToMavenLocal']
}

task cleanBuildPublish(type: GradleBuild) {
    tasks = ['clean'.'build'.'publish']}Copy the code

1.8 Maven POM file format

The Project Object Model (POM) is the basic unit of work of The Maven Project. It is an XML file that contains the basic information of the Project, describing how the Project is built, declaring Project dependencies, and so on.

When executing a task or goal, Maven looks for the POM in the current directory. It reads the POM, gets the required configuration information, and then executes the target.

The following configurations can be specified in the POM:

  • Project depend on
  • The plug-in
  • Performance targets
  • Project building profile
  • Project version
  • Project Developer List
  • Related mailing list information

All POM files require a project element and three required fields: groupId, artifactId, and Version.

node describe
project Project root tag.
modelVersion Model version needs to be set to 4.0.0.
groupId A unique identifier of a company or organization, and a path generated during configuration, such as com.panyname. project-group. Maven will place the jar package of the project in the local path: /com/companyname/project-group
artifactId ArtifactId is used to distinguish the unique ID of a groupId from multiple items. GroupId, together with artifactId, defines the location of the artifact in the repository.
version This is the project version number. In repositories of artifacts, it is used to distinguish between different versions.
packaging The type of artifact produced by the project, such as JAR, WAR, EAR, POM. Plug-ins can create their own component types, so not all of the component types listed above
dependencies This element describes all dependencies associated with the project. These dependencies form part of the project construction process. They are automatically downloaded from the repository defined by the project.
dependency dependency
scope Dependency scope. During a project release, help determine which artifacts are included. Refer to dependency mechanisms for more information.

-compile: indicates the default range for compiling

-Provided: similar to compilation, but supports what you’d expect from the JDK or container, similar to classpath

– Runtime: used during execution

– test: used for the test task

– system: the corresponding elements need to be provided externally. Obtain it from systemPath

– systemPath: Applies only to system. Provide the corresponding path

-optional: Indicates whether the dependency is passed when the project itself is dependent. Used for continuous dependencies

POM labels in detail

A simple Android dependency library poM file is shown below


      
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <! -- This module was also published with a richer model, Gradle metadata, -->
  <! -- which should be used instead. Do not delete the following line which -->
  <! -- is to indicate to Gradle or any Gradle module metadata file consumer -->
  <! -- that they should prefer consuming it instead. -->
  <! -- do_not_remove: published-with-gradle-metadata -->
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.qlife.android</groupId>
  <artifactId>lib-net-release</artifactId>
  <version>1.0.1</version>
  <packaging>aar</packaging>
  
  <dependencies>
    <dependency>
      <groupId>com.squareup.retrofit2</groupId>
      <artifactId>retrofit</artifactId>
      <version>server</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>logging-interceptor</artifactId>
      <version>4.2.2</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>com.github.jaydroid1024.JDispatcher</groupId>
      <artifactId>jdispatcher-api</artifactId>
      <version>0.0.7</version>
      <scope>runtime</scope>
    </dependency>.</dependencies>
</project>

Copy the code

2. Aliyun – Cloud Effect Maven repository

If you want to build a Nexus Repository Manager (NXRM) server, download the NXRM from the Nexus official website

Ali Cloud Maven central warehouse for Ali Cloud cloud effect to provide a public agent warehouse, to help r&d personnel to improve research and development production efficiency, using Ali Cloud Maven central warehouse as a download source, faster and more stable.

Alibaba Cloud Service is an enterprise-level one-stop DevOps platform, covering the whole r&d cycle of products from demand to operation. Maven private repository Packages are also provided for free and reliable

2.1 Common proxy repository

The name of the warehouse Ali Cloud warehouse address Ali Cloud warehouse address (old version) Source address
central Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… repo1.maven.org/maven2/
jcenter Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… jcenter.bintray.com/
public Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… Aggregation of central and JCenter
google Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… maven.google.com/
gradle-plugin Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… plugins.gradle.org/m2/
spring Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… Repo. Spring. IO/libs – milest…
spring-plugin Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… Repo. Spring. IO/plugins – rel…
grails-core Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… repo.grails.org/grails/core
apache snapshots Maven.aliyun.com/repository/… Maven.aliyun.com/nexus/conte… repository.apache.org/snapshots/

2.2 Android related agent warehouse

The name of the warehouse Ali Cloud warehouse address
central Maven.aliyun.com/repository/…
jcenter Maven.aliyun.com/repository/…
public Maven.aliyun.com/repository/…
google Maven.aliyun.com/repository/…
gradle-plugin Maven.aliyun.com/repository/…

Compared with the

buildscript {
    repositories {
      //central
      maven { url 'https://maven.aliyun.com/repository/central' }
      //jcenter&public
      maven { url 'https://maven.aliyun.com/repository/public' }
      //google
      maven { url 'https://maven.aliyun.com/repository/google' }
      //gradle-plugin
      maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
      mavenCentral()
      maven { url "https://jitpack.io" }
      google()
      jcenter()
    }
}
Copy the code

2.3 Private warehouse of products

  • Cloud Packages automatically creates two Maven repositories for you, a Release library and a Snapshot library.

    • The Maven Release library is used to store releases that are stable and currently updated, and can be used for releases.

    • The Maven Snapchat library is used to store unstable, in-development versions, known as snapshot versions.

    • Depending on whether -snapshot is configured in the version field of the build.gradle file in your project directory.

  • After entering the warehouse, you can complete the warehouse voucher setting, product file uploading and downloading, and private database migration through the warehouse guide.

  • The package list displays all binary package files in the repository. You can search for package files by Group Id or Artifacts Id.

  • Click the package file to display the package file information. By default, the latest version information is displayed. Click to switch the package version.

  • The default enterprise owner is the repository owner, and other enterprise members need to set members and roles in the repository. The relationship between warehouse openness and member roles is as follows:

Warehouse roles Warehouse openness: Private warehouses Warehouse openness: visible within the enterprise
The owner Access, download, upload, delete, warehouse management Access, download, upload, delete, warehouse management
The administrator Access, download, upload, delete, warehouse management Access, download, upload, delete, warehouse management
Members of the development Access, download, upload Access, download, upload
Ordinary members Access, download Access, download
Non-warehouse member There is no Access, download

2.4 Gradle push

  1. Setting warehouse credentials
apply plugin: 'maven-publish'

println("-- -- -- -- -- -- -- - ${project. The name} : Maven Publish Gradle -- -- -- -- -- -- -- --")
// Release and snapshot control switches
def isUploadToRelease = rootProject.ext.mavenRepo['isUploadToRelease']
// The remote Maven repository URL Release
def MAVEN_REPO_RELEASE_URL = rootProject.ext.mavenRepo['mavenRepoUrlRelease']
// Call the snapshots of the remote Maven repository
def MAVEN_REPO_SNAPSHOTS_URL = rootProject.ext.mavenRepo['mavenRepoUrlSnapshots']
// Remote Maven repository user name
def USER_NAME = rootProject.ext.mavenRepo['userName']
// Remote Maven repository password
def PASSWORD = rootProject.ext.mavenRepo['password']
// Uniquely identifies each component to be specified
def GROUP = group.toString()
// Todo defaults to the project name
def ARTIFACT_ID = project.name
// The version number is specified for each component
def VERSION = version.toString()
// Remote Maven repository URL
def URL = isUploadToRelease ? MAVEN_REPO_RELEASE_URL : MAVEN_REPO_SNAPSHOTS_URL

println("dependencies_path: $GROUP:$ARTIFACT_ID:$VERSION")
println("MAVEN_REPO_RELEASE_URL: $MAVEN_REPO_RELEASE_URL")
println("MAVEN_REPO_SNAPSHOTS_URL: $MAVEN_REPO_SNAPSHOTS_URL")


/ / https://docs.gradle.org/7.0/userguide/publishing_maven.html#publishing_maven
//https://developer.android.com/studio/build/maven-publish-plugin
// Because the components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.
afterEvaluate {
    publishing {
        publications {
            // Creates a Maven publication called "release".
            release(MavenPublication) {
                // Applies the component for the release build variant.
                from components.release
                // You can then customize attributes of the publication as shown below.
                groupId = GROUP
                artifactId = ARTIFACT_ID
                version = VERSION

            }
            // Creates a Maven publication called “debug”.
            debug(MavenPublication) {
                // Applies the component for the debug build variant.
                from components.debug
                groupId = GROUP
                artifactId = ARTIFACT_ID + "-debug"
                version = VERSION
            }
        }
        repositories {
            maven {
                url = URL
                credentials {
                    username USER_NAME
                    password PASSWORD
                }
            }
        }
    }
}
Copy the code
  1. Set up the repository download configuration
allprojects {
    repositories {
        //central
        maven { url 'https://maven.aliyun.com/repository/central' }
        //jcenter&public
        maven { url 'https://maven.aliyun.com/repository/public' }
        //google
        maven { url 'https://maven.aliyun.com/repository/google' }
        //gradle-plugin
        maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
        mavenCentral()
        maven { url "https://jitpack.io" }
        google()
        jcenter()

        /**Maven private server configuration */
        // Storage type local dev Production
        def currentMavenRepositoryType = rootProject.ext.mavenRepo['currentMavenRepositoryType']
        def localMavenRepositoryType = rootProject.ext.mavenRepositoryType['local']
        maven {
            // Distinguish between local and remote repositories
            if(currentMavenRepositoryType ! = localMavenRepositoryType) { credentials { username rootProject.ext.mavenRepo['userName']
                    password rootProject.ext.mavenRepo['password']
                }
            }
            url rootProject.ext.mavenRepo['mavenRepoUrlRelease']
        }
        maven {
            // Distinguish between local and remote repositories
            if(currentMavenRepositoryType ! = localMavenRepositoryType) { credentials { username rootProject.ext.mavenRepo['userName']
                    password rootProject.ext.mavenRepo['password']
                }
            }
            url rootProject.ext.mavenRepo['mavenRepoUrlSnapshots']}}}Copy the code

2.5 Gradle pull

  1. Setting warehouse credentials
allprojects {
    repositories {
        //central
        maven { url 'https://maven.aliyun.com/repository/central' }
        //jcenter&public
        maven { url 'https://maven.aliyun.com/repository/public' }
        //google
        maven { url 'https://maven.aliyun.com/repository/google' }
        //gradle-plugin
        maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
        mavenCentral()
        maven { url "https://jitpack.io" }
        google()
        jcenter()

        /**Maven private server configuration */
        // Storage type local dev Production
        def currentMavenRepositoryType = rootProject.ext.mavenRepo['currentMavenRepositoryType']
        def localMavenRepositoryType = rootProject.ext.mavenRepositoryType['local']
        maven {
            // Distinguish between local and remote repositories
            if(currentMavenRepositoryType ! = localMavenRepositoryType) { credentials { username rootProject.ext.mavenRepo['userName']
                    password rootProject.ext.mavenRepo['password']
                }
            }
            url rootProject.ext.mavenRepo['mavenRepoUrlRelease']
        }
        maven {
            // Distinguish between local and remote repositories
            if(currentMavenRepositoryType ! = localMavenRepositoryType) { credentials { username rootProject.ext.mavenRepo['userName']
                    password rootProject.ext.mavenRepo['password']
                }
            }
            url rootProject.ext.mavenRepo['mavenRepoUrlSnapshots']}}}Copy the code
  1. Configuration Package Information
dependencies {
    def currentMavenRepositoryType = rootProject.ext.mavenRepo['dependenceTypeIsModule']
    if (currentMavenRepositoryType) {
        implementation project(path: ':lib-net')}else {
        implementation rootProject.ext.libNet
    }
}
Copy the code

Grade dependency management

3.1 Dependency types

dependencies {
  
    // The dependency of the local repository module
    implementation project(":mylibrary")

    // Dependencies on local binaries
    implementation fileTree(dir: 'libs'.include: ['*.jar'])
  	implementation files('libs/foo.jar')
    implementation project(path: ':foo-aar-module')
  
    // Dependencies on remote binaries
    implementation 'com. The example. The android: app - magic: 12.3'

}
Copy the code

Local library module dependencies

This relies on an Android library module named “myLibrary” (which must match the name of the library defined using include: in your settings.gradle file). When you build your application, the build system compiles the library module and packages the compiled content into APK.

Local binary dependencies

Gradle declares a dependency on JAR files in the module_name/libs/ directory of the project (because Gradle reads the relative path to the build. Gradle file).

You can also specify individual JAR/AAR files or create a dependency like the local repository module by creating an AAR/JAR module

Remote binary dependencies

Implementation 'com. Example. Android: app - magic: 12.3'Copy the code

This is actually a shorthand for the following code:

Implementation Group: 'com.example. Android ', name: 'app-magic', version: '12.3'Copy the code

This declares a dependency on the version 12.3 “app-Magic” library in the “com.example.android” namespace group.

Such remote dependencies require you to declare the appropriate remote code base, which Gradle should look for. If the corresponding library does not exist locally, Gradle extracts it from the remote site.

3.2 Dependency Dependency Mode Configuration

In the Dependencies code block, you can choose one of a number of different dependency configurations, each of which gives Gradle a different description of how to use the dependency. The following table describes the various configurations used by dependencies in Android projects.

The new configuration The configuration is deprecated Behavior description
implementation compile Gradle adds dependencies to the compile classpath and packages dependencies into the build output. When the module is configuredimplementationDependencies are compiled at Gradle timeThis dependency is not passed to other modules. That is, other modules can use this dependency only at run time. Use this dependency configuration insteadapicompileDeprecated yesSignificantly reduce build timesBecause it reduces the number of modules that need to be recompiled to build the system. For example, ifimplementationA dependency changes its API, and Gradle only recompiles the dependency and the modules that directly depend on it. Most applications and test modules should use this configuration.
api compile Gradle adds dependencies to the compile classpath and build output. When a module containsapiMakes Gradle dependentExport the dependency to another module in pass-through modeSo that these modules can use the dependency both at run time and compile time. This configuration behaves like thiscompile(deprecated), but it should be used with extreme care only for dependencies that need to be exported to other upstream consumers in pass-through mode. That’s because ifapiA dependency changes its external API, and Gradle recompiles all modules that have access to the dependency at compile time. Therefore, have a large number ofapiDependencies are displayedIncrease build time. Unless you want to expose a dependency’s API to a separate module, the library module should use it insteadimplementationDependencies.
compileOnly provided Gradle only adds dependencies to the compiled classpath that is,It is not added to the build output. This configuration can be useful if you create an Android module that requires a dependency at compile time but is not required at run time. If you use this configuration, your library module must include a runtime condition that checks if a dependency is provided and then appropriately changes the behavior of the module so that it can function without the dependency. To do soUnimportant transient dependencies are not added, therefore,Helps reduce the size of the final APK. This configuration behaves like thisprovided(now deprecated).Pay attention to: You can’tcompileOnlyThe configuration works with AAR dependencies.
runtimeOnly apk Gradle only adds dependencies to the build output for use at run time. That is, it will not be added to the compiled classpath. This configuration behaves like thisapk(now deprecated).
annotationProcessor compile To add a dependency to a library that acts as an annotation processor, you must useannotationProcessorConfigure to add it to the annotation processor classpath. This is because using this configuration canImprove build performance by separating the compile classpath from the annotation processor classpath. If Gradle finds a comment handler on the compilation classpath, it is disabledAvoid compilationFeature, which has a negative impact on build time (Gradle 5.0 and later ignore comment handlers found on the compilation classpath). The Android Gradle plugin assumes that the dependency is a comment handler if the JAR file contains the following files:META-INF/services/javax.annotation.processing.Processor. A build error is generated if the plug-in detects a comment handler on the compiled classpath.

3.3 Dependency Order

The order in which dependencies are listed indicates the priority of each library: the first library has priority over the second, the second library has priority over the third, and so on. This order is important when merging resources or listing elements from libraries into applications.

For example, if your project declares the following:

  • Rely onLIB_ALIB_B(In that order)
  • LIB_ADepends on theLIB_CLIB_D(In that order)
  • LIB_BAlso depends onLIB_C
//app
dependencies {
    implementation('LIB_A')
    implementation('LIB_B')}//LIB_A
dependencies {
    implementation('LIB_C')
    implementation('LIB_D')}//LIB_B
dependencies {
    implementation('LIB_C')}Copy the code

The order of flat dependencies would look like this:

  1. LIB_A
  2. LIB_D
  3. LIB_B
  4. LIB_C

This ensures that both LIB_A and LIB_B can replace LIB_C; And LIB_D still takes precedence over LIB_B because LIB_A (which depends on the former) has precedence over LIB_B.

3.4 Dependency conflict

Resolve conflicts between classpath

When Gradle parses the compiled classpath, it first parses the runtime classpath and then uses the results to determine which versions of dependencies should be added to the compiled classpath. In other words, the runtime classpath determines the version numbers required for identical dependencies downstream on the classpath.

The runtime classpath of an application also determines the version number Gradle needs to use for matching dependencies in the runtime classpath of the application’s test APK. Figure 1 illustrates the classpath hierarchy.

For example, when an application uses the implementation dependency configuration to add a version of a dependency, and a library module uses runtimeOnly configuration to add another version of that dependency, conflicts can occur with different versions of the same dependency in multiple classpath.

Android Gradle plugin 3.3.0 and later attempts to resolve some downstream version conflicts automatically when resolving dependencies on runtime and compile-time classpath. For example, if the runtime classpath contains library A version 2.0 and the compiled classpath contains library A version 1.0, the plug-in will automatically update the dependency on the compiled classpath to library A version 2.0 to avoid errors.

However, if the runtime classpath contains library A version 1.0 and the compiled classpath contains library A version 2.0, the plug-in does not downgrade its dependency on the compiled classpath to library A version 1.0, and you still receive an error similar to the following:

Conflict with dependency 'com.example. Library :some-lib:2.0' in project 'my-library'. Resolved versions for Runtime Differ with classpath (1.0) and compile classpath (2.0).Copy the code

To resolve this problem, perform one of the following operations:

  • Treat the dependencies of the required version asapiDependencies are added to the library module. That is, only library modules declare dependencies, but application modules also have pass-through access to their apis. – Alternatively, you can declare dependencies in both modules at the same time, but make sure that each module uses the same version. considerConfigure project global propertiesTo ensure that versions of each dependency remain consistent throughout the project.

Exclude pass dependencies

As the scope of an application grows, it may contain many dependencies, both direct and transitive (libraries that the imported libraries in the application depend on). To exclude pass-through dependencies that are no longer needed, you can use the exclude keyword, as follows:

dependencies {
    implementation('some-library') {
        exclude group: 'com.example.imgtools', module: 'native'
    }
}
Copy the code

If you define a exclude in the Configuration, all transitive dependencies (specified) are removed. When you define exclude, specify either group only, module name only, or both.

Here are some typical examples of using exclude:

  • A licensing issue
  • The dependency cannot be obtained from the remote repository
  • This is not needed at Runtime
  • Version conflict

Force the current version

Implementation (' com. Squareup. Okhttp: okhttp - mt: 2.5.0 ') {force = true}Copy the code

For example, if a dependency contains okHTTP, there will be a version conflict. If a dependency contains okHTTP, there will be a version conflict.

Indirect dependencies transitive

They are called “transitive dependencies” and are more appropriate.

Implementation (' com. At meituan. Android. Terminus: library: 6.6.1.16 @ aar ') {transitive = true}Copy the code

Adding @aar to the end of the script means that you are downloading the AAR package and not the other libraries that the aar package depends on. If you want to download the aar dependent libraries without using @aar, you need to add the transitive=true condition.

4. Reference materials

  • Ali cloud | cloud Maven
  • Ali cloud | cloud products warehouse Package the official document
  • Ali cloud | cloud Package products warehouse address
  • Android developers | Android Maven Publish docs
  • Gradle user guide | Gradle Maven Publish official page
  • What is Maven
  • Novice tutorial | Maven tutorial
  • Publish an Android library to Maven with aar and source jar
  • Android developers | add build dependencies
  • Rely on the management of Gradle user guide | Gradle