如何从具有 gradle 依赖关系的代码创建一个 Android 库?
Posted
技术标签:
【中文标题】如何从具有 gradle 依赖关系的代码创建一个 Android 库?【英文标题】:How to create an Android library from the code that have gradle dependency? 【发布时间】:2017-08-04 15:39:21 【问题描述】:我正在创建一个基于以下组件的具有依赖关系的 android 库。
-
我的图书馆代码
布局和资源文件
将依赖项分级为第三方。
首先我想为我的库创建 .jar 文件,但后来我发现 laulyoit 和资源文件不是用 jar 编译的。然后我决定创建 AAR 文件。请建议这是正确的举动还是有其他选择?
现在主要问题是我被 gradle 依赖所困扰。我们正在创建一个付费图书馆,它使用一些第三方,如谷歌,只能通过 Gradle 获得。现在由于我正在创建一个 AAR 文件,因此没有 Manifest.xml 和 Gradle 文件,我如何将第三方与我自己的代码集成。并且我们有严格的指示,我们不能告诉图书馆的用户包括第三方来包括。简而言之,我们不能让用户知道我们的图书馆正在使用什么样的第三方。 那么有什么方法可以创建一个 AAR 文件,该文件还预先编译了 gradle 依赖项,而不会向用户透露我们正在使用哪些服务?
更新 1
这是我的图书馆 build.gradle
apply plugin: 'com.android.library'
android
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
dexOptions
preDexLibraries = false
javaMaxHeapSize "4g" // 2g should be also OK
buildTypes
release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
dependencies
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2',
exclude group: 'com.android.support', module: 'support-annotations'
)
compile 'com.android.support:appcompat-v7:+'
compile 'com.google.android.gms:play-services-vision:10.2.1'
testCompile 'junit:junit:4.12'
在我将我的 .aar 文件移动到本地 maven 并创建然后使用我的应用程序项目中的输出文件之后。这是相同的 gradle。
apply plugin: 'com.android.application'
android
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig
applicationId "com.jarvis.myapplication"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
buildTypes
release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
dependencies
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2',
exclude group: 'com.android.support', module: 'support-annotations'
)
compile('com.company:mylibrary:1.0@aar')
transitive = true
compile 'com.android.support:appcompat-v7:25.3.0'
testCompile 'junit:junit:4.12'
【问题讨论】:
How to build an android library with Android Studio and gradle?的可能重复 @KishanCS 感谢您的建议。我会检查你分享的链接是否能解决我的问题。谢谢 本教程可能会对您有所帮助。 youtube.com/watch?v=RYiZZprUNJw请看一下。 【参考方案1】:如果您创建一个 .aar 项目,那么是一个清单文件,它将在编译时与应用程序的清单合并。这一切都很好。 您可以在 .aar 项目中使用任何 gradle 依赖项,甚至是 proguard 混淆和签名。
要在主应用程序中编译 .aar 库,请将其放在 build.grade 文件的 dependencies
中:
dependencies
compile(name:'your_lib_name', ext:'aar')
您必须将 .aar 文件复制到您的 app
文件夹中的 libs
文件夹中。
但有一点很清楚: 如果有人使用您的 .aar 文件,他或她可以随时在 android studio 中查看合并的清单文件,并且您无法隐藏您的依赖项。至少,据我所知。 Android 由开源库(甚至通过 maven)强力驱动,在大多数情况下,您甚至必须包含使用的外部库的许可证,用户可以在应用程序中以菜单项或链接的形式看到这些许可证。否则,在某些情况下,您会违反许可,甚至可能违反使用条款。你不能隐藏它们。
【讨论】:
这是我尝试过的:- compile(name:'com.google.android.gms:play-services-vision:9.8.0', ext:'aar') 但我得到了错误:- 找不到:- com.google.android.gms:play-services-vision:9.8.0 gms play 不是 aar 库。只需将其添加为普通的 Maven 依赖项即可。像这样:编译'com.google.android.gms:play-services-gcm:10.2.1' @Grisgram 尝试相同,但得到错误:- 错误:任务':app:transformClassesWithDexForDebug'的执行失败。 > com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexException: 多个dex文件定义Lcom/google/android /gms/vision/CameraSource$1; 请在您的问题中发布您的 build.gradle 和 proguard 规则文件,以便我分析 这看起来像是多 dex 文件问题。为您的应用程序启用多 dexing。更多信息可以在这里找到:developer.android.com/studio/build/multidex.html【参考方案2】:嗨@user3572586,
aar 文件不包含传递依赖项,也不包含 有一个描述库使用的依赖项的 pom 文件。
这意味着,如果您使用 flatDir 存储库导入 aar 文件 您还必须在项目中指定依赖项。
您应该使用 maven 存储库(您必须在 私有或公共 maven 存储库),您不会遇到同样的问题。
这种情况下,gradle使用pom文件下载依赖 这将包含依赖项列表。
要对用户隐藏付费库,最好为项目中的单个库创建包,然后生成 .aar 文件。我自己创建了一个实时流库,在将依赖项模块移到我的项目内部然后制作 .aar 文件时面临同样的问题。
【讨论】:
【参考方案3】:您可以在您的库项目中创建一个包含所有必需依赖项的*.aar
文件。
现在将这个 *.aar 文件手动或作为 依赖模块 添加到目标项目。一旦主项目被合并,这将给出合并的Android Manifest file
。
以下结构将库项目 (libraryModule) 添加为对主项目的依赖项。 libraryModule 再次对 internallib
具有内部依赖性MainProject ===> libraryModule ===> internallib
根据您的评论,可以通过在build.gradle
(模块:app)中添加以下内容来解决多索引问题
defaultConfig
.....
multiDexEnabled true
.....
【讨论】:
【参考方案4】:首先:AAR 文件有清单。而且,如果您使用 gradle 构建它们,它们将具有 gradle 构建脚本。
所以,你的问题的第一部分是没有实际意义的。只需创建一个 AAR 库并使用 gradle-maven 插件 (gradle) 或 maven-android 插件 (maven) 添加依赖项。
对于第二部分,有点棘手。你想要的本质上是一个带阴影的 AAR 或 Uber-AAR,一个 AAR 文件,它将依赖项捆绑到自身中。您可以通过使用 maven-shade 插件或 gradle-shade 插件来实现这一点(取决于您使用哪个系统来创建 aar)。使用这种方法,您的客户可能会遇到严重的问题。您会看到,在 java 中,您的项目使用依赖范围和类路径的概念。范围意味着需要依赖的时间以及带来依赖的人。类路径是项目使用的整个类的集合,包括依赖项或项目本身的类(因此客户端将始终能够知道您在使用什么,因为编译器也需要知道)。因此,路径中不能有多个版本的依赖项,因为类会发生冲突,导致项目无法编译。这就是为什么我们通常不会试图隐藏我们正在使用的依赖项。它可以更轻松地解决冲突。如果您使用流行的依赖项(如谷歌地图),您的图书馆可能会成为您客户的问题,因此被丢弃。您最好使用设计的合约来开发库,然后使用某些依赖项来开发具有特定实现的辅助插件。这样,您的项目将更容易维护并且不依赖于依赖项。在这种情况下,如果最坏的情况发生并且您的实现的依赖项与您客户的项目不兼容,那么在不影响您的代码的情况下创建辅助实现会更容易。
maven shade插件链接: https://maven.apache.org/plugins/maven-shade-plugin/
gradle shade插件链接: https://github.com/zawn/android-shade-plugin
【讨论】:
以上是关于如何从具有 gradle 依赖关系的代码创建一个 Android 库?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Gradle 创建具有实现依赖项的可执行胖 jar