如何从具有 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文件

具有gradle的本地模块依赖性

如何使用 Gradle 创建具有实现依赖项的可执行胖 jar

gradle - 如何在 jar 中声明 jar 的依赖关系

如何从build.gradle导入依赖关系到pom.xml

Gradle 无法构建具有 Docker 依赖项的 JAR