background

I am an Android SDK developer, is to develop SDK for customers to use. In the past, our SDK development was based on the principle of not relying on the third party if possible, and we used the API provided by the native. Due to the last crawler Android Push which strong — analysis of wandoujia 1400 APPS to get the use of OkHttp APP accounted for a very high proportion, coupled with the SDK provided by foreign SaaS service companies for access to third-party open source SDK is very open. So we also want to switch the underlying network library from traditional HttpURLConnection to OkHttp3. But this was the beginning of the nightmare…

Dependency generation problem

Development went well and we added the okHTTP dependency to our SDK module

dependencies {
    ...
    implementation 'com. Squareup. Okhttp3: okhttp: 3.12.1'
}
Copy the code

Added SDK Module dependencies in the test Demo APP

dependencies {
    ...
    implementation project(':sdk-lib')}Copy the code

Well, the Demo APP works perfectly, the code runs and flies. However, when we publish to Maven and then create a new APP to add our dependencies directly, there is a problem.

dependencies {
    ...
    implementation 'com. XXXX. XXXX: SDK - lib: 1.0.0'
}
Copy the code

“NoClassDefFoundError”? ! Didn’t I add the OkHttp dependency in my SDK-lib already? !

 java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/MediaType;
Copy the code

The difference between Implementation and API

Refer to the dependency configuration on the official website

<?xml version="1.0" encoding="UTF-8"? >
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xxxx.xxxx</groupId>
  <artifactId>sdk-lib</artifactId>
  <version>1.0.0</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp</artifactId>
      <version>3.12.1</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</project>
Copy the code

We see that the type of scope is Runtime. Baidu’s basic approach is to re-add the OkHttp dependency in the dependency of the main APP, or use API to replace implementation. If we use the API dependency and look at the poM file of the dependency, we find that the scope type is compile.

<?xml version="1.0" encoding="UTF-8"? >
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xxxx.xxxx</groupId>
  <artifactId>sdk-lib</artifactId>
  <version>1.0.0</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp</artifactId>
      <version>3.12.1</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>
Copy the code

Create a new APP and rely on the new SDK-lib. Sure enough, the code is flying.

More complicated case

If it’s basically over here, isn’t it just another hydrology? As we all know, we often have different dependencies for development and release, such as module dependencies for development and Online Maven library dependencies for release. For example, the SDK-lib SDK relies on a self-developed core module.

dependencies {
    ...
    debugApi project(':core-lib')
    releaseApi "com.xxxx.xxxx:core:$coreVersion"
}
Copy the code

When we use the gradle generatePomFileForReleasePublication Task generated Pom file found that dependence is not the core – lib, what the hell? ! What happened to using an API? !

<?xml version="1.0" encoding="UTF-8"? >
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xxxx.xxxx</groupId>
  <artifactId>sdk-lib</artifactId>
  <version>1.0.0</version>
  <packaging>aar</packaging>
</project>
Copy the code

To solve the problem

Gradle’s maven-publish plugin is no longer enough for us, so let’s write our own POM dependencies and add all implementation and API dependencies to them. Add it to build. Gradle of your APP as follows

publishing {
    publications {
        mavenAgent(MavenPublication) {
            artifact "${project.buildDir}/outputs/aar/${project.name}-release.aar"
            groupId yourGroupId
            artifactId yourArtifactId
            version yourVersion
            pom.withXml {
                writePom(asNode())
            }
        }
    }
}

void writePom(node) {
    def allDependencies = new HashSet<DependencySet>()
    allDependencies.addAll(configurations.api.allDependencies)
    allDependencies.addAll(configurations.releaseApi.allDependencies)
    allDependencies.addAll(configurations.implementation.allDependencies)
    allDependencies.addAll(configurations.releaseImplementation.allDependencies)
    def iterator = allDependencies.iterator()
    while (iterator.hasNext()) {
        def dep = iterator.next()
        // Remove project dependencies
        if (dep.name == "unspecified" || dep.version == "unspecified") {
            iterator.remove()
        }
    }

    def depsNode = node.appendNode('dependencies')
    allDependencies.each { dep ->
        def depNode = depsNode.appendNode('dependency')
        depNode.appendNode('groupId', dep.group)
        depNode.appendNode('artifactId', dep.name)
        depNode.appendNode('version', dep.version)
        depNode.appendNode('scope'.'compile')}}Copy the code

We perform our two subordinate tasks in the Gradle task list (where mavenAgent is your own publication alias) and look at dependencies.

<?xml version="1.0" encoding="UTF-8"? >
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xxxx.xxxx</groupId>
  <artifactId>sdk-lib</artifactId>
  <version>1.0.0</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp</artifactId>
      <version>3.12.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.xxxx.xxxx</groupId>
      <artifactId>core</artifactId>
      <version>1.0.0</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>
Copy the code

Ok, you’re done! Publish to the online JCenter repository! Make your code fly!