前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次Gradle依赖相关问题

记一次Gradle依赖相关问题

作者头像
烧麦程
发布2022-12-05 14:14:29
1.2K0
发布2022-12-05 14:14:29
举报
文章被收录于专栏:半行代码

‍最近对之前项目里面依赖的Flutter模块进行了一次升级。因为从1.x升级的时候3.0的flutter需要安卓原生适配compilesdkversion,所以我们APP使用的Flutter版本为2.8.1,现在app的构建版本升上来了,于是对之前的Flutter进行了升级。

Flutter开发的页面从2.8升级到3.3.8倒没有遇到什么问题。但是最后把Flutter模块打包成 aar 以及依赖到安卓工程里面的时候遇到了问题。

问题描述

flutter升级到 v3.3.8 之后,使用 flutter build aar--no-profile--no-debug打出来的aar结构如下图:

代码语言:javascript
复制
├── flutter
│   ├── 1.34.1.6-bae-SNAPSHOT
│   │   ├── flutter-1.34.1.6-bae-20221125.160600-1-debug.aar
│   │   ├── flutter-1.34.1.6-bae-20221125.160600-1-profile.aar
│   │   ├── flutter-1.34.1.6-bae-20221125.160600-1-release.aar
│   │   ├── maven-metadata.xml
│   │   ├── flutter-1.34.1.6-bae-20221125.160600-1.module
│   ├── maven-metadata.xml
│   ├── maven-metadata.xml.md5
│   ├── maven-metadata.xml.sha1
├── flutter_debug
│   ├── 1.34.1.6-bae-SNAPSHOT
├── flutter_profile
│   ├── 1.34.1.6-bae-SNAPSHOT
└── flutter_release
    ├── 1.34.1.6-bae-SNAPSHOT

并且命令行里面会提示:

代码语言:javascript
复制
dependencies {
  releaseImplementation 'com.netease.bae.flutter.baeflutter:flutter:1.34.1.6-bae-SNAPSHOT:release'
}

这里和 2.x 相比,打包产物其实有了变化。之前用 2.x 打包的时候,生成的 flutter module 产物只有 flutter_release 文件夹下面的内容。

并且命令行里面的提示也只是:

代码语言:javascript
复制
releaseImplementation 'com.netease.bae.flutter.baeflutter:flutter_release:1.34.1.6-bae-SNAPSHOT'

这里我们把依赖替换成 3.3.8 提示的内容,暂时忽略这里的 :release

当我们依赖好aar后,编译正式版本的时候会出现编译错误:

代码语言:javascript
复制
Could not determine the dependencies of task ':app:compileAReleaseTestRenderscript'.
> Could not resolve all task dependencies for configuration ':app:AReleaseTestCompileClasspath'.
   > Could not resolve com.netease.bae.flutter.baeflutter:flutter:xxxx.
     Required by:
         project :app > project :appservice
      > No matching variant of com.netease.bae.flutter.baeflutter:flutter:xxxx:20221122.043716-1 was found. The consumer was configured to find an API of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'releaseTest', attribute 'product' with value 'A', attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm' but:
          - Variant 'debugVariantAllApiPublication' capability com.netease.bae.flutter.baeflutter:flutter:xxxx declares an API of a component:
              - Incompatible because this component declares a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'debug' and the consumer needed a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'releaseTest'
              - Other compatible attributes:
                  - Doesn't say anything about org.jetbrains.kotlin.platform.type (required 'androidJvm')
                  - Doesn't say anything about product (required 'A')
          - Variant 'debugVariantAllRuntimePublication' capability com.netease.bae.flutter.baeflutter:flutter:xxxx declares a runtime of a component:
              - Incompatible because this component declares a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'debug' and the consumer needed a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'releaseTest'
              - Other compatible attributes:
                  - Doesn't say anything about org.jetbrains.kotlin.platform.type (required 'androidJvm')
                  - Doesn't say anything about product (required 'A')
          - Variant 'profileVariantAllApiPublication' capability com.netease.bae.flutter.baeflutter:flutter:xxxx declares an API of a component:
              - Incompatible because this component declares a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'profile' and the consumer needed a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'releaseTest'
              - Other compatible attributes:
                  - Doesn't say anything about org.jetbrains.kotlin.platform.type (required 'androidJvm')
                  - Doesn't say anything about product (required 'A')
          - Variant 'profileVariantAllRuntimePublication' capability com.netease.bae.flutter.baeflutter:flutter:xxxx declares a runtime of a component:
              - Incompatible because this component declares a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'profile' and the consumer needed a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'releaseTest'
              - Other compatible attributes:
                  - Doesn't say anything about org.jetbrains.kotlin.platform.type (required 'androidJvm')
                  - Doesn't say anything about product (required 'A')
          - Variant 'releaseVariantAllApiPublication' capability com.netease.bae.flutter.baeflutter:flutter:xxxx declares an API of a component:
              - Incompatible because this component declares a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'release' and the consumer needed a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'releaseTest'
              - Other compatible attributes:
                  - Doesn't say anything about org.jetbrains.kotlin.platform.type (required 'androidJvm')
                  - Doesn't say anything about product (required 'A')
          - Variant 'releaseVariantAllRuntimePublication' capability com.netease.bae.flutter.baeflutter:flutter:xxxx declares a runtime of a component:
              - Incompatible because this component declares a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'release' and the consumer needed a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'releaseTest'
              - Other compatible attributes:
                  - Doesn't say anything about org.jetbrains.kotlin.platform.type (required 'androidJvm')
                  - Doesn't say anything about product (required 'A')
   > Could not resolve com.netease.cloudmusic.look.flutterhybrid:flutterhybrid:xxxx.

这里看起来是 variant 发生了冲突。第一反应对这个报错是比较奇怪的,因为不理解为什么一个aar被依赖的时候,还会存在 variant

但是经过对比,2.8.1 和 3.3.8 打包产物比起来,3.3.8 多出了一个 .module 文件,这个文件的内容是 json 格式的,其中包括了variants 的定义,

为了方便阅读,我只留了name和一些关键的key,内容如下:

代码语言:javascript
复制
"variants": [
  {
    "name":"debugVariantAllApiPublication",
    "attributes":{},
    "dependencies":[
      {
        "group":"io.flutter",
        "module":"flutter_embedding_debug",
        "version":{
          "requires":"1.0.0-857bd6b74c5eb56151bfafe91e7fa6a82b6fee25"
        }
      }
    ],
    "files": [
      {
        "name":"",
        "url":"",
        "size":36580,
        "sha512":"",
        "sha256":"",
        "sha1":"",
        "md5":""
      }
    ]
  },
  {
    "name":"releaseVariantAllApiPublication",
    "attributes":{},
    "dependencies":[],
    "files": []
  }
  //....
]

这个文件里面定义了 debugVariantAllApiPublicationprofileVariantAllApiPublicationreleaseVariantAllApiPublication 三个 variant,

里面分别定义了自己依赖的其他 aar 以及当前文件的名称、url、大小和签名。

到这里我们大概能明白依赖的时候 :release 的含义了,它会帮我们选择需要的 aar 文件。而上面的编译错误,就是因为我们的 APP 里面定义了 buildType 为 releaseTest ,所以导致编译失败。

警告不断努力的 Google 和 文档翻阅,找到了 2 个解决方案。

添加 matchingFallbacks

在 gradle 的配置里,我们可以通过 matchingFallbacks 来处理应用包含依赖项不包含的 build 类型。

在我们应用的 build.gradle 里面都需要在 releaseTest 下面添加:

代码语言:javascript
复制
releaseTest {
  matchingFallbacks = ['debug', 'release']
}

经过实践,我们需要把所有的业务 module 的 build.gradle 都添加上这个配置,否则就会不生效,这个对一个业务 module 比较多的 APP 来说还是比较麻烦的。

自定义 ComponentMetadataRule

通过阅读 gradle 文档,可以发现一种解决方案:https://docs.gradle.org/current/userguide/component_metadata_rules.html

我们可以定义我们自己的 ComponentMetadataRule 修改元数据。给对应的依赖项添加我们自己的 variant。

代码语言:javascript
复制
@CacheableRule
class FlutterRule implements ComponentMetadataRule {
  @Override
  void execute(ComponentMetadataContext componentMetadataContext) {
    componentMetadataContext.details.addVariant("releaseTestVariantAllApiPublication", "debugVariantAllRuntimePublication") {
            attributes {
                def ret = it.keySet().find {
                    it.name == "com.android.build.api.attributes.BuildTypeAttr"
                }
                if (ret != null) {
                    attribute(ret, "releaseTest")
                }
            }
        }
  }
}

代码如上图所示,通过 ComponentMetadataContext#addVariant ,我们可以以现有的 variant 为基础,定义并添加一个新的 variant。

这里我们根据 debugVariantAllRuntimePublication 创建了 releaseTestVariantAllApiPublication,并且把 BuildTypeAttr 属性设置为当前的 buildType。

接下来就是让这个规则全局对 Flutter 相关的依赖生效,我们可以使用 dependencyResolutionManagementsetting.gradle 里面定义。

代码语言:javascript
复制
dependencyResolutionManagement {
    rulesMode.set(RulesMode.PREFER_SETTINGS)
    components {
        withModule("com.netease.bae.flutter.baeflutter:flutter", FlutterRule)
    }
}

withModule 里面添加依赖项的 group:module 即可。因为项目内的 gradle 设置默认情况下覆盖这里的设置,使用需要添加 RulesMode.PREFER_SETTINGS ,否则不会生效。

需要注意的是,网上很多文档说 dependencyResolutionManagement 是 AGP7 开始的 api, 其实这里是有点误解的。Gralde api 文档里面这个方法标记的是 since 6.8,所以即使你使用的 AGP 版本是4.x,也只是需要修改 gradle-wrapper.properties 里面的 gradle 版本即可:

代码语言:javascript
复制
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip

通过自定义 ComponentMetadataRule,此问题可以完美解

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-12-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 半行代码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述
    • 添加 matchingFallbacks
      • 自定义 ComponentMetadataRule
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档