How to add a maven manifest to an AAR which specifies dependencies

∥☆過路亽.° 提交于 2019-12-09 03:18:50

问题


I was (finally) able to publish my Android library to an AWS S3 maven repository using this guide. It's published as an AAR instead of JAR file, which means that even though the generated POM file lists all its internal dependencies, they are ignored when adding the library to another project. Seems like a pretty common problem. I understand from this that I just need to list the dependencies in a maven manifest, but how is this done?

I'm really a newbie at this, so the simpler the better... Thanks!

Note: I also found this question, so I added "{transitive=true}" at the end of the dependency implementation line and it worked.

So now to include my library successfully, the dependency must be coded as:

implementation (group: 'com.mygroup', name: 'my_library', version: '1.3', ext: 'aar', classifier: 'release') { transitive=true changing=true }

(I included "changing=true" to force it to re-download the library every time.)

If I don't include "transitive=true", I get the following errors:

    02-04 20:11:48.462 10225-10225/com.mydomain.app.testapplication4 E/dalvikvm: Could not find class 'android.graphics.drawable.RippleDrawable', referenced from method android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering
    02-04 20:14:07.080 10225-10225/com.mydomain.app.testapplication4 E/dalvikvm: Could not find class 'android.app.NotificationChannel', referenced from method com.mydomain.library.mydomain$1.onReceive
    02-04 20:14:07.290 10225-10225/com.mydomain.app.testapplication4 E/AndroidRuntime: FATAL EXCEPTION: main
        java.lang.NoClassDefFoundError: com.google.firebase.iid.FirebaseInstanceId
            at com.mydomain.library.MyActivity.onCreate(MyActivity.java:88)
            at android.app.Activity.performCreate(Activity.java:4701)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1051)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1924)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1985)
            at android.app.ActivityThread.access$600(ActivityThread.java:127)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1151)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4477)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:788)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
            at dalvik.system.NativeStart.main(Native Method)

Here is the latest script I used to publish the library (note that it only publishes the release build, but the dependency line still requires the "release" classifier):

    apply plugin: 'maven-publish'

    group = 'com.mydomain'
    version = '1.3'

    // Add sources as an artifact
    task sourceJar(type: Jar) {
        from android.sourceSets.main.java.srcDirs
        classifier "source"
    }

    // Loop over all variants
    android.libraryVariants.all { variant ->
        if (variant.buildType.name == "release") { // only release build
        variant.outputs.all { output ->
            // This creates a publication for each variant
            publishing.publications.create(variant.name, MavenPublication) {
                // The sources artifact from earlier
                artifact sourceJar

                // Variant dependent artifact, e.g. release, debug
                artifact source: output.outputFile, classifier: output.name

                // Go through all the dependencies for each variant and add them to the POM
                // file as dependencies
                pom.withXml {
                    final dependenciesNode = asNode().appendNode('dependencies')

                    ext.addDependency = { Dependency dep, String scope ->
                        if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
                            return // ignore invalid dependencies

                        final dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', dep.group)
                        dependencyNode.appendNode('artifactId', dep.name)
                        dependencyNode.appendNode('version', dep.version)
                        dependencyNode.appendNode('scope', scope)

                        if (!dep.transitive) {
                            // If this dependency is transitive, we should force exclude all its dependencies them from the POM
                            final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
                            exclusionNode.appendNode('groupId', '*')
                            exclusionNode.appendNode('artifactId', '*')
                        } else if (!dep.properties.excludeRules.empty) {
                            // Otherwise add specified exclude rules
                            final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
                            dep.properties.excludeRules.each { ExcludeRule rule ->
                                exclusionNode.appendNode('groupId', rule.group ?: '*')
                                exclusionNode.appendNode('artifactId', rule.module ?: '*')
                            }
                        }
                    }

                    // List all "compile" dependencies (for old Gradle)
                    configurations.compile.getDependencies().each { dep -> addDependency(dep, "compile") }
                    // 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") }
                }
            }
        }
        }
    }

    // Ensure that the publish task depends on assembly
    tasks.all { task ->
        if (task instanceof AbstractPublishToMaven) {
            task.dependsOn assemble
        }
    }

    // Configure the destination repository with
    // S3 URL and access credentials
    publishing {
        // Properties properties = new Properties()
        // properties.load(file('maven.properties').newDataInputStream())

        repositories {
            maven {
                url "s3://androidsdk.mydomain.com.s3.amazonaws.com"
                credentials(AwsCredentials) {
                    accessKey "myaccesskey"
                    secretKey "mysecretkey"
                }
            }
        }
    }

Here are the dependencies in the library's gradle.build file:

    dependencies {
        api fileTree(include: ['*.jar'], dir: 'libs')
        api 'com.android.support:appcompat-v7:27.1.1'
        api 'com.android.support.constraint:constraint-layout:1.1.3'
        api 'com.android.support:design:27.1.1'
        api 'io.reactivex.rxjava2:rxandroid:2.1.0'
        api 'io.reactivex.rxjava2:rxjava:2.2.4'
        api 'com.github.instacart.truetime-android:library-extension-rx:3.3'
        api 'com.google.dagger:dagger-android:2.15'
        annotationProcessor 'com.google.dagger:dagger-android-processor:2.15'
        annotationProcessor 'com.google.dagger:dagger-compiler:2.15'
        api 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
        api 'com.google.firebase:firebase-core:16.0.7'
        api 'com.google.firebase:firebase-messaging:17.3.4'
    }

I was thinking that the generated POM file below might not match the library's dependencies, but they do. The "scope" tags in the POM file should remove the need for "transitive=true" right?

<?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.mydomain</groupId>
  <artifactId>my_library</artifactId>
  <version>1.3</version>
  <packaging>pom</packaging>
  <dependencies>
    <dependency>
      <groupId>com.android.support</groupId>
      <artifactId>appcompat-v7</artifactId>
      <version>27.1.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.android.support.constraint</groupId>
      <artifactId>constraint-layout</artifactId>
      <version>1.1.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.android.support</groupId>
      <artifactId>design</artifactId>
      <version>27.1.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.reactivex.rxjava2</groupId>
      <artifactId>rxandroid</artifactId>
      <version>2.1.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.reactivex.rxjava2</groupId>
      <artifactId>rxjava</artifactId>
      <version>2.2.4</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.github.instacart.truetime-android</groupId>
      <artifactId>library-extension-rx</artifactId>
      <version>3.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.google.dagger</groupId>
      <artifactId>dagger-android</artifactId>
      <version>2.15</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.nostra13.universalimageloader</groupId>
      <artifactId>universal-image-loader</artifactId>
      <version>1.9.5</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.google.firebase</groupId>
      <artifactId>firebase-core</artifactId>
      <version>16.0.6</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.google.firebase</groupId>
      <artifactId>firebase-messaging</artifactId>
      <version>17.3.4</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

回答1:


You should be able to resolve this by changing your POM XML generation so that the <packaging> section is setup as aar rather than pom:

<?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.humanvideoboard</groupId>
  <artifactId>hvb_library</artifactId>
  <version>1.0</version>
  <packaging>aar</packaging>

However, now that I'm re-examining this, the cause for why it works with transitive dependencies is by the use of implementation vs api when building the library or when building the thing which is using the library. If your library is exposing types from its dependencies as part of its public API, then those build dependencies need to be handled correctly in your library build. See this page for more information.



来源:https://stackoverflow.com/questions/53876071/how-to-add-a-maven-manifest-to-an-aar-which-specifies-dependencies

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!