使用 gradle 不能解决 aar 库的传递依赖性

我已经调查了一段时间,可能看到了最流行的答案在这里有关 传递依赖性传递依赖性,但不知何故,它仍然不清楚我如何使这个工作。

所以:

我有一个给定级别配置的 android 库:

apply plugin: 'android-library'
apply plugin: 'android-maven'


version = "1.0.0"
group = "com.somepackage"


buildscript {
repositories {
mavenCentral()
mavenLocal()
}


dependencies {
classpath 'com.github.dcendents:android-maven-plugin:1.0'
}
}


android {
compileSdkVersion 19
buildToolsVersion '19.0.3'


defaultConfig {
minSdkVersion 10
}
}


repositories {
maven { url 'http://www.bugsense.com/gradle/' }
}


dependencies {
provided 'com.google.android.gms:play-services:+'
provided 'com.android.support:appcompat-v7:+'
compile 'com.google.code.gson:gson:2.2.4'
compile 'com.bugsense.trace:bugsense:3.6'
compile 'commons-net:commons-net:3.3'
}

然后,我将它部署到本地 maven repo,所部署库的 gradle install.POM 文件如下所示:

<?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.sprezzat</groupId>
<artifactId>app</artifactId>
<version>1.0.0</version>
<packaging>aar</packaging>
<dependencies>
<dependency>
<groupId>com.bugsense.trace</groupId>
<artifactId>bugsense</artifactId>
<version>3.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

最后,我的 android 应用程序的 gradle 配置使用上面的库作为一个依赖项:

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.+'
}
}
apply plugin: 'android'


repositories {
mavenCentral()
mavenLocal()
}


android {
compileSdkVersion 15
buildToolsVersion "19.0.2"


defaultConfig {
minSdkVersion 10
targetSdkVersion 18
}
}


dependencies {
compile 'com.google.android.gms:play-services:+'
compile 'com.android.support:appcompat-v7:+'
compile 'com.somepackage:LIBRARY_NAME:1.0.0@aar'
}

在手机上部署应用程序之后,我得到了属于我的 android 库的编译依赖类的 NoClassDefFoundError

使用 gradle dependencies检查我的 android 应用程序依赖关系:

apk - Classpath packaged with the compiled main classes.
+--- com.google.android.gms:play-services:+ -> 4.3.23
|    \--- com.android.support:support-v4:19.0.1 -> 19.1.0
+--- com.android.support:appcompat-v7:+ -> 19.1.0
|    \--- com.android.support:support-v4:19.1.0
\--- com.somepackage:LIBRARY_NAME:1.0.0

根据上面的树,没有检测到所有的传递依赖关系。问题在哪里? 应该如何正确地解决?

52076 次浏览

I have solved my problem by setting transitive attribute for my aar dependency:

compile ('com.somepackage:LIBRARY_NAME:1.0.0@aar'){
transitive=true
}

you should not use "@aar", if use "@" is become "Artifact only notation", if you want to use "@" and want have dependence transitive, you should add "transitive=true"

Try this if you are using aar locally:

compile(project(:your-library-name)) {
transitive=true
}

Simply adding @aar at the end of the dependency is what worked for me.

dependencies {
implementation 'org.videolan.vlc:libvlc:3.0.13@aar'
}

For me complete publishing solution looks like this:


apply plugin: 'com.github.dcendents.android-maven'


group = GROUP
version = VERSION


// you could move it to env variable or property
def publishFlavorless = true
def firstTask = null


android.libraryVariants.all { variant ->


if (variant.name.toLowerCase().contains("debug")) {
// Workaround for https://github.com/gradle/gradle/issues/1487
if (publishFlavorless && firstTask == null) {
def bundleTask = tasks["bundle${variant.name.capitalize()}Aar"]
firstTask = bundleTask
artifacts {
archives(firstTask.archivePath) {
builtBy firstTask
name = project.name
}
}
}
return
}


def bundleTask = tasks["bundle${variant.name.capitalize()}Aar"]


artifacts {
archives(bundleTask.archivePath) {
classifier variant.flavorName
builtBy bundleTask
name = project.name
}
}
}


install {
repositories.mavenInstaller {
// This generates POM.xml with proper parameters
pom.project {
name POM_NAME
artifactId POM_ARTIFACT_ID
// For aar it is equal to 'aar' with jar transitive dependencies won't work
packaging POM_PACKAGING
description POM_DESCRIPTION
}
}
}

The transitive = true block is required as well ...

I was having a similar problem and felt I could share the steps of solving the problem.

The basic idea of not being able to use the transitive dependencies while you are publishing your own aar is actually not having the .pom file generated with the expected transitive dependencies.

I was using 'maven-publish' plugin for my android aar dependency to publish it in my own private maven repository. The transitive dependencies were not resolved when my other projects were adding my aar dependency in their build.gradle. Hence here what I did to modify the .pom file while publishing my aar.

An important thing to note here that, the dependencies which you want to have the transitive behavior should be imported using the api in your library project's build.gradle file like the following.

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
api 'com.android.volley:volley:1.0.0'
api "com.google.code.gson:gson:$globalGsonVersion"
}

Now as I said earlier, I was using maven-publish plugin to publish the aar dependency and hence my publishing task in the gradle looks like the following.

publishing {
publications {
mavenAar(MavenPublication) {
from components.android
}


mavenJava(MavenPublication) {
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
// Iterate over the api dependencies (we don't want the test ones), adding a <dependency> node for each
configurations.api.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}


repositories {
maven {
// Your repository information goes here
}
}
}

Hence, I used another mavenJava task to publish the .pom file in my private maven repo so that when the aar file is added as a dependency to some other module, it gets the .pom information and download the transitive dependency.

To complete the answer, this is how you should add the dependency in the build.gradle file for your own published aar to me imported.

api('com.example.masudias:my_lib:1.0.0@aar') {
transitive = true
}

Transitive dependency

transitive means that the consumer(e.g. app) includes a producer and all producer's dependencies(e.g. libraries). It increase build time and can create some issues with dependency versions

By default, Gradle dependency has transitive = true

api ('com.package:library:0.0.1')
//the same
api ('com.package:library:0.0.1') {
transitive = true
}

When you use @artifact notation it has transitive = false

api ('com.package:library:0.0.1@aar')
//the same
api ('com.package:library:0.0.1@aar') {
transitive = false
}

AAR file doesn't contain transitive dependencies. So even if use api instead of implementation it wont work.

In our team we had developed a library to use in our applications and we wanted it to be for internal use only. Earlier we used to include whole module that seems to work. Later we decided to move to aar file but we were also facing same issue of classpath not found. After some research we came to know that we can also use local maven repo. We decided to use that.

Here is step by step process

Publishing repo

1.In your Library's root build.gradle file you need to include

id 'com.github.dcendents.android-maven' version '2.0' apply false

2.In you library's module level build.gradle file you need to add

a) In plugins

id 'maven-publish'

b) At bottom of gradle file add

publishing {
publications {
release(MavenPublication) {
groupId = 'com.demo.android'
artifactId = 'qrcodescanner'
version = '1.0.0'


afterEvaluate {
from components.release
}
}
}
repositories {
maven {
name = "qrcodescanner"
url = "${project.buildDir}/repo"


}
}
}

3.Depends on the name you have given a gradle tasks will be generated you can check using gradlew tasks or by using gradle window at top right corner in android studio, Our was

publishReleasePublicationToQrcodescannerRepository

4.Run it and repo will be generated in given path

gradlew publishReleasePublicationToQrcodescannerRepository
  1. Final step you need to publish it to maven local using

    gradlew publishToMavenLocal

if it doesn't work you can try gradlew clean and gradlew build before executing it.

Using local repo

1.You need to add mavenLocal() in root level build.gradle file of your project you wanted to use it in like this before other central repos

allprojects {
repositories {
mavenLocal()
google()
jcenter()
maven { url "https://jitpack.io" }
mavenCentral()
}
}
  1. Now you need to include your dependency in the project like we do with other dependencies as well

implementation 'com.demo.android:qrcodescanner:1.0.0' keep in mind format should groupdId:artifactId:version

That's it.

References :

Publish Library

Local Maven