Android Studio Gradle 未使用传递依赖项
Android Studio Gradle not using transitive dependencies
在一个单独的项目中遇到这个问题,我做了一个测试项目来验证这个问题。
- 打开Android Studio 3.0,我创建了一个新的基础项目。它的主要模块叫做
app
.
- 我添加了一个库模块,名为
libraryone
。
- 在
libraryone
中,我添加了对Gson的依赖,并使用Gson添加了一个class和一个静态方法。
- 在
app
中,我添加了对libraryone
的依赖。我和 transitive = true
一起简单地测试了它,因为互联网似乎模糊地同意这样做可能会有所帮助。 (它没有。)
- 在
app
中,在MainActivity
中,我使用了libraryone
中的class。这有效(只要我没有设置 transitive = false
即可)。
- 但是,我无法从
MainActivity
本身引用 Gson。它给出了 "Cannot resolve symbol 'Gson'" 错误,来自 Android Studio 以及来自命令行 Gradle。这……不寻常且令人恼火,因为这意味着您必须在一组项目中重复所有的公共依赖项,并且 classes 无论如何都包含在输出中。肯定是我做错了什么,或者这是一个错误?
我的代码如下:
MainActivity.java(在app
)
package com.erhannis.test.dependencytest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.erhannis.test.libraryone.LibClass;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String s = LibClass.convert(new Object());
System.out.println("out: " + s);
new com.google.gson.Gson(); // This line gives a compile-time error: "Cannot resolve symbol 'Gson'"
}
}
LibClass.java(在libraryone
)
package com.erhannis.test.libraryone;
import com.google.gson.Gson;
public class LibClass {
public static String convert(Object o) {
Gson gson = new Gson();
return gson.toJson(o);
}
}
build.gradle (app
)
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.erhannis.test.dependencytest"
minSdkVersion 18
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation (project(path: ':libraryone'))
}
build.gradle (libraryone
)
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 18
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.google.code.gson:gson:2.8.2'
}
因为你把传递依赖声明为implementation
。使用 api
而不是 implementation
更改:
implementation 'com.google.code.gson:gson:2.8.2'
至:
api 'com.google.code.gson:gson:2.8.2'
可以找到你应该在你的库中声明传递依赖的原因here
您正在使用:
implementation (project(path: ':libraryone'))
implementation 'com.google.code.gson:gson:2.8.2'
勾选 official doc:
When your module configures an implementation
dependency, it's letting Gradle know that the module does not want to leak the dependency to other modules at compile time. That is, the dependency is available to other modules only at runtime.
在这里你可以找到非常good blog关于它的。
最好的解决方案是为 aar 依赖创建一个私有 Github/Gitlab 存储库。如果需要,您也可以将其设置为 public。 aar 文件在本地使用时不包含传递依赖。我们需要使用 .pom 文件将其发布到某处。方法如下,
- 在 Github
中创建个人访问令牌
Github -> Settings -> Developer Settings -> Personal Access token - with write:packages / read:packages access level
(create two tokens if you need to distribute privately
将id 'maven-publish'
添加到模块级别的插件gradle
将以下代码添加到模块级别 gradle
task sourceJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
archiveClassifier.set("sources")
}
publishing {
publications {
bar(MavenPublication) {
groupId 'com.your'
artifactId 'artifact'
version '1.0'
artifact sourceJar
artifact("$buildDir/outputs/aar/YourLibraryName-release.aar")
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
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) {
final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
exclusionNode.appendNode('groupId', '*')
exclusionNode.appendNode('artifactId', '*')
} else if (!dep.properties.excludeRules.empty) {
final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
dep.properties.excludeRules.each { ExcludeRule rule ->
exclusionNode.appendNode('groupId', rule.group ?: '*')
exclusionNode.appendNode('artifactId', rule.module ?: '*')
}
}
}
configurations.compile.getDependencies().each { dep -> addDependency(dep, "compile") }
configurations.api.getDependencies().each { dep -> addDependency(dep, "compile") }
configurations.implementation.getDependencies().each { dep -> addDependency(dep, "runtime") }
}
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/GITHUB_USERID/REPOSITORY")
credentials {
username = "GITHUB_USERID" // Better if you use env variable
password = "WRITE_ACCESS_TOKEN"
}
}
}
}
在 Gradle 工具栏中,您可以在库模块的 publishing 子目录下找到 publish目录。 (确保在发布之前从模块目录中的 build->build 构建 aar)
要在您的项目中使用它,
将以下内容添加到您的 应用级别 gradle 文件 内 android { }标签
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/GITHUB_USERID/REPOSITORY")
credentials {
username = "GITHUB_USERID" // Better if you use env variable
password = "READ_ACCESS_TOKEN"
}
}
}
终于在依赖中
implementation 'com.your:artifact:1.0'
*Gitlab 也和这个很相似
在一个单独的项目中遇到这个问题,我做了一个测试项目来验证这个问题。
- 打开Android Studio 3.0,我创建了一个新的基础项目。它的主要模块叫做
app
. - 我添加了一个库模块,名为
libraryone
。 - 在
libraryone
中,我添加了对Gson的依赖,并使用Gson添加了一个class和一个静态方法。 - 在
app
中,我添加了对libraryone
的依赖。我和transitive = true
一起简单地测试了它,因为互联网似乎模糊地同意这样做可能会有所帮助。 (它没有。) - 在
app
中,在MainActivity
中,我使用了libraryone
中的class。这有效(只要我没有设置transitive = false
即可)。 - 但是,我无法从
MainActivity
本身引用 Gson。它给出了 "Cannot resolve symbol 'Gson'" 错误,来自 Android Studio 以及来自命令行 Gradle。这……不寻常且令人恼火,因为这意味着您必须在一组项目中重复所有的公共依赖项,并且 classes 无论如何都包含在输出中。肯定是我做错了什么,或者这是一个错误?
我的代码如下:
MainActivity.java(在app
)
package com.erhannis.test.dependencytest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.erhannis.test.libraryone.LibClass;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String s = LibClass.convert(new Object());
System.out.println("out: " + s);
new com.google.gson.Gson(); // This line gives a compile-time error: "Cannot resolve symbol 'Gson'"
}
}
LibClass.java(在libraryone
)
package com.erhannis.test.libraryone;
import com.google.gson.Gson;
public class LibClass {
public static String convert(Object o) {
Gson gson = new Gson();
return gson.toJson(o);
}
}
build.gradle (app
)
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.erhannis.test.dependencytest"
minSdkVersion 18
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation (project(path: ':libraryone'))
}
build.gradle (libraryone
)
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 18
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.google.code.gson:gson:2.8.2'
}
因为你把传递依赖声明为implementation
。使用 api
而不是 implementation
更改:
implementation 'com.google.code.gson:gson:2.8.2'
至:
api 'com.google.code.gson:gson:2.8.2'
可以找到你应该在你的库中声明传递依赖的原因here
您正在使用:
implementation (project(path: ':libraryone'))
implementation 'com.google.code.gson:gson:2.8.2'
勾选 official doc:
When your module configures an
implementation
dependency, it's letting Gradle know that the module does not want to leak the dependency to other modules at compile time. That is, the dependency is available to other modules only at runtime.
在这里你可以找到非常good blog关于它的。
最好的解决方案是为 aar 依赖创建一个私有 Github/Gitlab 存储库。如果需要,您也可以将其设置为 public。 aar 文件在本地使用时不包含传递依赖。我们需要使用 .pom 文件将其发布到某处。方法如下,
- 在 Github
Github -> Settings -> Developer Settings -> Personal Access token - with write:packages / read:packages access level
(create two tokens if you need to distribute privately
将
id 'maven-publish'
添加到模块级别的插件gradle将以下代码添加到模块级别 gradle
task sourceJar(type: Jar) { from android.sourceSets.main.java.srcDirs archiveClassifier.set("sources") } publishing { publications { bar(MavenPublication) { groupId 'com.your' artifactId 'artifact' version '1.0' artifact sourceJar artifact("$buildDir/outputs/aar/YourLibraryName-release.aar") 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 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) { final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion') exclusionNode.appendNode('groupId', '*') exclusionNode.appendNode('artifactId', '*') } else if (!dep.properties.excludeRules.empty) { final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion') dep.properties.excludeRules.each { ExcludeRule rule -> exclusionNode.appendNode('groupId', rule.group ?: '*') exclusionNode.appendNode('artifactId', rule.module ?: '*') } } } configurations.compile.getDependencies().each { dep -> addDependency(dep, "compile") } configurations.api.getDependencies().each { dep -> addDependency(dep, "compile") } configurations.implementation.getDependencies().each { dep -> addDependency(dep, "runtime") } } } } repositories { maven { name = "GitHubPackages" url = uri("https://maven.pkg.github.com/GITHUB_USERID/REPOSITORY") credentials { username = "GITHUB_USERID" // Better if you use env variable password = "WRITE_ACCESS_TOKEN" } } } }
在 Gradle 工具栏中,您可以在库模块的 publishing 子目录下找到 publish目录。 (确保在发布之前从模块目录中的 build->build 构建 aar)
要在您的项目中使用它,
将以下内容添加到您的 应用级别 gradle 文件 内 android { }标签repositories { maven { name = "GitHubPackages" url = uri("https://maven.pkg.github.com/GITHUB_USERID/REPOSITORY") credentials { username = "GITHUB_USERID" // Better if you use env variable password = "READ_ACCESS_TOKEN" } } }
终于在依赖中
implementation 'com.your:artifact:1.0'
*Gitlab 也和这个很相似