为啥不能使用pom文件中的maven依赖?

Posted

技术标签:

【中文标题】为啥不能使用pom文件中的maven依赖?【英文标题】:How come maven dependencies in POM file can't be used?为什么不能使用pom文件中的maven依赖? 【发布时间】:2021-04-07 10:00:47 【问题描述】:

背景

我的任务是为开发人员提供一种方法,将单个依赖项添加到 android 项目的 build.gradle 文件中,以使用我准备的一些(混淆的)SDK(AAR 文件 - Android 库)。

SDK 本身使用各种依赖项,因此它们在最终代码中可用很重要,这意味着使用 SDK 的人不会看到由于 class-not-found 而导致的崩溃。

SDK 作为私有存储库存储在 Github 上,开发人员可以通过 Jitpack 使用,它会扫描存储库中的 POM 文件和其他一些文件。

单独使用 AAR 文件,您必须设置与 SDK 相同(或更新)的依赖项。

但是,如果您在发布时使用 POM 文件,则使用者(使用 SDK 的人)不需要编写 SDK 上的每个依赖项,因为它是从 POM 文件添加的。

问题

由于某种原因,这种行为对我来说不存在。这意味着好像 SDK 不使用任何依赖项,所以如果我尝试使用任何依赖项,我将无法访问类,并且如果我在使用某些依赖项时尝试使用 SDK,则会导致异常ClassNotFoundException。

起初我认为这是因为一些 Proguard 规则,但后来我注意到它也发生在 debug-variant 上(使用 SDK 的应用程序)。

例如,当库在依赖项中使用它时:

implementation 'androidx.security:security-crypto:1.1.0-alpha03'

如果我不使用它,我将无法访问此依赖项的任何类,如果 SDK 尝试访问它的任何类,应用程序将崩溃。

因此,我必须添加 SDK 已经使用的所有依赖项,而不是使用 SDK 的单个依赖项。

我尝试过的

要生成 AAR 文件,我使用“assembleRelease”gradle 任务,要生成 POM 文件,我使用“generatePomFileForReleasePublication”(或“publishReleasePublicationToMavenLocal”)gradle 任务。

该库具有相当多的依赖关系。这是它的 build.gradle 文件:

plugins 
    id 'com.android.library'
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'kotlin-parcelize'
    id 'io.michaelrocks.paranoid'
    id 'maven-publish'
    id 'com.github.dcendents.android-maven'


android 
    compileSdkVersion 30
    defaultConfig 
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
    

    buildTypes 
        release 
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            consumerProguardFiles 'consumer-rules.pro'
        
    
    compileOptions 
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    
    kotlinOptions 
        jvmTarget = '1.8'
    
    configurations 
        all 
            exclude module: 'httpclient'
        
    
    packagingOptions 
        //for google login token
        exclude 'META-INF/DEPENDENCIES'
    


dependencies 
    api "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    api 'androidx.core:core-ktx:1.6.0-alpha01'
    api 'androidx.collection:collection-ktx:1.2.0-alpha01'
    api 'androidx.security:security-crypto:1.1.0-alpha03'
    def room_version = "2.2.6"
    api "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
    api "androidx.room:room-ktx:$room_version"
    api 'com.squareup.retrofit2:retrofit:2.9.0'
    api 'com.squareup.retrofit2:converter-gson:2.9.0'
    api 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
    api 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'
    api('com.google.android.gms:play-services-auth:19.0.0')
    api('com.google.auth:google-auth-library-oauth2-http:0.25.0')
    api('com.google.apis:google-api-services-people:v1-rev99-1.22.0') 
        exclude group: 'com.google.guava'
    
    api 'io.michaelrocks:libphonenumber-android:8.12.20'


afterEvaluate 
    publishing 
        publications 
            release(MavenPublication) 
                from components.release
            
        
    

运行“generatePomFileForReleasePublication”任务我得到了POM文件“pom-default.xml”:

<?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">
  <!-- This module was also published with a richer model, Gradle metadata,  -->
  <!-- which should be used instead. Do not delete the following line which  -->
  <!-- is to indicate to Gradle or any Gradle module metadata file consumer  -->
  <!-- that they should prefer consuming it instead. -->
  <!-- do_not_remove: published-with-gradle-metadata -->
  <modelVersion>4.0.0</modelVersion>
  <groupId>MySdk</groupId>
  <artifactId>library</artifactId>
  <version>unspecified</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib</artifactId>
      <version>1.4.32</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>androidx.core</groupId>
      <artifactId>core-ktx</artifactId>
      <version>1.6.0-alpha01</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>androidx.collection</groupId>
      <artifactId>collection-ktx</artifactId>
      <version>1.2.0-alpha01</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>androidx.security</groupId>
      <artifactId>security-crypto</artifactId>
      <version>1.1.0-alpha03</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>androidx.room</groupId>
      <artifactId>room-runtime</artifactId>
      <version>2.2.6</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>androidx.room</groupId>
      <artifactId>room-ktx</artifactId>
      <version>2.2.6</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.squareup.retrofit2</groupId>
      <artifactId>retrofit</artifactId>
      <version>2.9.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.squareup.retrofit2</groupId>
      <artifactId>converter-gson</artifactId>
      <version>2.9.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp</artifactId>
      <version>5.0.0-alpha.2</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>logging-interceptor</artifactId>
      <version>5.0.0-alpha.2</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.google.android.gms</groupId>
      <artifactId>play-services-auth</artifactId>
      <version>19.0.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.google.auth</groupId>
      <artifactId>google-auth-library-oauth2-http</artifactId>
      <version>0.25.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.google.apis</groupId>
      <artifactId>google-api-services-people</artifactId>
      <version>v1-rev99-1.22.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
        <exclusion>
          <artifactId>*</artifactId>
          <groupId>com.google.guava</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>io.michaelrocks</groupId>
      <artifactId>libphonenumber-android</artifactId>
      <version>8.12.20</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-parcelize-runtime</artifactId>
      <version>1.4.32</version>
      <scope>runtime</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>io.michaelrocks</groupId>
      <artifactId>paranoid-core</artifactId>
      <version>0.3.3</version>
      <scope>runtime</scope>
      <exclusions>
        <exclusion>
          <artifactId>httpclient</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
</project>

根据各个网站的说法,这似乎是有效且好的,但遗憾的是,正如我所写,当我使用它时,好像这些依赖项都不存在,我需要在消费者端声明它们。

在 Jitpack 的文件 ("jitpack.yml" ) 中,我有这样的内容:

install: 
  - FILE="-Dfile=library-release.aar" 
  - mvn install:install-file $FILE -DgroupId=my-sdk -DartifactId=MySdk -Dversion=1.0 -Dpackaging=aar -DgeneratePom=true

我尝试了什么:

    我尝试使用“实现”和“api”。没有帮助。 我试图从所有dependency 标签中删除scope。没有帮助。 我尝试在消费者端添加transitive = true,但这并没有做任何事情,可能是因为无论如何它都是默认的。 删除 POM 文件在 Jitpack 上没有显示警告,表明它甚至可能不会检查它。 我注意到 POM 文件提到“这个模块也发布了更丰富的模型,应该使用 Gradle 元数据”,所以我尝试找到这个文件,但找不到。运行publishToMavenLocal 任务,我得到了另一个文件(“module.json”),甚至把它而不是单独的pom-default.xml 文件(也作为一个完整的替换),它没有帮助。 我认为“jitpack.yml”文件和 gradle 文件之间存在一些不一致,所以我为它们设置了相同的“groupId”、“artifactId”和“version”值。

问题

    为什么依赖项在消费者端被忽略了?我怎样才能解决这个问题?这可能是我错过的非常简单的事情...... Jitpack 究竟需要哪些文件?哪些是强制性的?哪些是可选的? 是否也可以避免packagingOptions exclude 'META-INF/DEPENDENCIES' 在消费者方面的部分? 奖励:我注意到 JavaDocs(或者在我的情况下是 Kdocs,因为我在 Kotlin 中编写了所有内容)也被完全忽略了。我怎样才能使这些内容也可访问和可读?

【问题讨论】:

嘿,很抱歉回复延迟,但我刚刚阅读了您的问题,我想从您这边了解一件事。当您说 SDK 在 Jitpack 上发布时,它是托管在安全的地方还是公开可用的?意思是它是否托管在代理/私有环境中。像内部服务器一样,gradle 可能无法解决传递依赖关系。我在我的组织中看到了同样的问题,我们的 nexus 存储库有两个 url,一个以 maven-public 包开头,一个以 maven-release 开头,但发布的一个以某种方式最终无法解决所有 deps。 我看到的第二件事是您正在使用 gradle 任务生成 POM 文件,我认为这些文件足以解决消费者方面的传递依赖问题,这意味着问题取决于您的 Jitpack 托管。此外,我不确定打包选项,但对于文档,您可以尝试使用 JavaDocs 类型。这是参考:gist.github.com/Robyer/a6578e60127418b380ca133a1291f017 我写了“SDK 作为私有存储库存储在 Github 上”。 Github 存储 SDK 文件。 Jitpack 可以访问那里(必须授权访问)。 Jitpack 现在可以完全访问那里的所有存储库和文件。 Jitpack 就像一个中介。它查看存储库的文件,并为您生成依赖项。对于开源的 Android 库,这非常简单:输入 URL 即可。我自己的一个例子:github.com/AndroidDeveloperLB/AutoFitTextView。如果你把 URL 放到 Jitpack 的网站上,你会得到你需要使用的依赖。就是这样 因此,对于开源案例,它可以完美运行。但是,在这个问题上,它不是开源的。我已经生成了一个混淆的 AAR 文件,并尝试生成 POM 文件(和文档,但现在让我们把它作为奖励)。 Jitpack 无法使依赖项成为可选。现在要使用 SDK,使用它的人必须把 SDK 使用的所有依赖项都放好(你可以看到它相当多)。 是的,我知道 Jitpack 是如何工作的,但是在您共享 AutoFitTextView 的 SDK 的情况下,我可以通过在我自己的应用程序中输入工件名称来访问 SDK,或者我需要具有访问它的凭据。如果它需要授权,那就是问题所在,因为 Gradle 无法通过传递的 deps 突破。 【参考方案1】:

好的,我已经找到了执行此操作的方法。答案来自 Jitpack 支持本身。首先是他们的引述:

这是由安装命令和“-DgeneratePom=true”引起的 范围。它将生成一个新的 pom 文件,但它不知道 关于依赖关系的任何事情。

如果你已经有一个包含所有依赖项的 pom 文件,那么你 可以将其添加到 GitHub 存储库。代替 ' -DgeneratePom=true' 你可以使用'-DpomFile='

我们建议在运行 JitPack 之前在本地尝试该命令。

另一种选择是将库的所有源代码放在 JitPack 并从源代码构建。

事实上,如果我使用它(并且在库的依赖项中有“api”),我的大部分问题都会得到解答:

    它修复了依赖问题(是的,您不必自定义 -DgroupId=my-sdk -DartifactId=MySdk -Dversion=1.0 ):
install: 
  - FILE="-Dfile=library-release.aar" 
  - mvn install:install-file $FILE -Dpackaging=aar -DpomFile=pom-default.xml

    目前存在的文件似乎只有这些:jitpack.yml、library-release.aar、pom-default.xml。

    显然现在不需要了。可能是通过修复依赖问题的同一件事来修复的。

话虽如此,现在我有这些问题:

    “pom-default.xml”中关于使用不同文件的建议是什么(“这个模块也发布了更丰富的模型,Gradle 元数据,应该使用它。”)?它在哪里?可能是“module.json”文件吗?我尝试改用它,但随后 Jitpack 出现错误。

    这个用例的 Jitpack 文档在哪里?他们有一些关于私有存储库的信息,但没有关于 AAR 文件的信息。事实上,我看不到“jitpack.yml”文件。

    自定义-DgroupId=my-sdk -DartifactId=MySdk -Dversion=1.0 部分的目的是什么?在“jitpack.yml”文件中还是在库的 gradle 文件中?我认为他们根本没有做任何事情......似乎 Github 存储库本身就是决定消费者如何使用它的存储库。

    如何在此处添加 JavaDocs 和 Kdocs(Kotlin 的)?

尽管这是我问题的主要答案,但我会为其余回答我问题的人提供赏金:)

【讨论】:

***.com/questions/67042935/…帮帮我兄弟 感谢@androiddeveloper,几个月来我一直在寻找这个信息。 Jitpack 关于私有 repo 和发布 aar/jar 的文档很差。 @AkashRaj 不客气。后来我试图弄清楚如何添加Kdocs(如Java-Docs,但用于Kotlin),但失败了,但当我无法再检查时有人回答:***.com/q/67267094/878126请看看,如果你这样做,让我知道它是否确实有效。 我要收藏这个。目前,该项目使用 Java。如果我们迁移到 Kotlin,我会试一试。谢谢你的建议。 @androiddeveloper @AkashRaj 等等,Java 不存在这个问题?你如何为 Java 做到这一点?也很有趣……【参考方案2】:

我认为问题出在您的 jitpack.yml 上。 Jitpack 默认的install 命令依赖于maven-publish,因此使用生成的pom.xml。您使用对您的依赖项一无所知并且无法生成正确的 pom.xml 的自定义命令覆盖它,因为该命令是基于 Maven 的,而您的项目是基于 Gradle 的。

删除 jitpack.yml 或其install 部分,一切正常。

更新

您必须在 Gradle 配置中配置 Maven 发布才能使其正常工作。为此,您必须申请 maven-publish 插件

apply plugin: 'maven-publish'

并配置发布

afterEvaluate 
    publishing 
        publications 
            release(MavenPublication) 
                from components.release
                groupId = 'my-sdk'
                artifactId = 'MySdk'
                version = '1.0'
            
        
    

请查看官方 Jitpack 的Android sample。他们在 build.gradle 中配置 Maven 发布,既不使用 jitpack.yml,也不使用 ma​​ven 实用程序。

【讨论】:

删除 jitpack.yml 无效。花了 40 分钟,然后 Jitpack 才写了 No build file found. Looking for Gradle/Maven/Sbt/Lein build file in the root of the project See the documentation at https://jitpack.io/docs/ (当然,这个链接上没有任何关于这个文件的内容)。你到底说我可以在文件中更改什么,而不是删除它?另外,也许文件名不正确,无法处理?目前我得到的文件是 "library-release.aar", "module.json", "pom-default.xml" 。我需要哪些,以哪些名字命名? “在项目的根目录中寻找 Gradle/Maven/Sbt/Lein 构建文件”意味着您应该在根目录中有 build.gradle 并且您可能会这样做。当您删除 jitpack.yml 时,Jitpack 不会发布您的工件吗? 当我删除“jitpack.yml”(然后提交并推送更改)并告诉 Jitpack 检查存储库时,它会冻结 40 分钟,然后给我我写的错误。跨度> 我对 Jitpack 没有任何经验,但他们的 sample 没有 jitpack.yml,我认为这是正确的。 看看他们的样本。它使用maven-publish插件,这个插件是Jitpack成功发布所必需的。

以上是关于为啥不能使用pom文件中的maven依赖?的主要内容,如果未能解决你的问题,请参考以下文章

为啥有排除 pom.xml / maven 中依赖项的依赖项的选项?

为啥 javax.websocket 不能解决?

3.将maven项目jar纳入maven仓库,Mave项目依赖另外一个Maven项目的案例

如何配置maven pom文件来解决jar包冲突

为啥 Intellij 在 pom.xml 中找不到任何 Maven 依赖项?

pom.xml这个文件是maven压缩包里面自带的配置文件吗,为啥下载的包里没有,同时做一些别的指导