太长不看版
从 AGP8.0 开始,开发者必须在 build.gradle 中增加 namespace 字段。有人为此提了 issue,flutter 团队响应很快,表示马上兼容 AGP8.0。
在 AGP 的发布日志中看到,7.3 版本开始支持 namespace 字段。flutter团队为了保证兼容性,(毕竟要更新很多库),最低测试到了 AGP4.2,发现编译没有问题,于是在4.27日更新了这些库的 android 版本。
然而本人的AGP版本是 4.1.2,直接编译不了。这个事情发生在2023.4.27 。flutter 团队在10个小时后已经修复了这个问题。本文仅做记录,如果你能得到收获那就更好了。
背景介绍
本人所在的项目是一个 Android项目,混编了一些flutter代码。
遇到问题
打包过程中遇到以下报错,无法打出apk包。
Build file '/opt/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider_a
- ndroid-2.0.26/android/build.gradle' line: 24
[org.gradle.internal.buildevents.BuildExceptionReporter] A problem occurred ev
- aluating project ':path_provider_android'.
- 2023-04-28T10:45:20.867+0800 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] > No signature of met
- hod: build_3zcwdyxxtj69qg8p1nbrm7336.android() is applicable for argument types: (build_3zcwdyxxtj69qg8p1nbrm7336$_
- run_closure2) values: [build_3zcwdyxxtj69qg8p1nbrm7336$_run_closure2@3a15dc22]
分析问题
从报错信息中可以发现,是 path_provider 这个库导致的编译失败。具体报错为path_provider_android-2.0.26/android/build.gradle这个文件。
对版本号的困惑
本人项目中的 path_provider 版本为 指定为 2.0.9。并没有指定 path_provider_android的版本,报错信息中的版本为2.0.26。这个版本是怎么指定的呢。
从 dart pubspec文档 中可以查询到,如果版本号写为^x.y.z的话,会取flutter pub 仓库里的x.max(y).max(z)版本作为版本号。
对^x.y.z这种形式的版本号不理解的话,请看下面两个例子。
举例子:
场景一:本地 path_provider 版本号写为 ^2.0.9。如果 path_provider 在 flutter pub 上的最高版本号为 2.3.0。那么最终自己项目使用的 path_provider 版本号为 2.3.0。
场景二:本地 path_provider 版本号写为 ^2.0.9 。如果 path_provider 在 path_provider flutter pub 上的最高版本号为 3.3.0。以2开头的最大版本号为 2.9.9 。那么最终自己项目使用的 path_provider 版本号为 2.9.9。
从这两个场景中总结, ^ 的作用为,在版本号为 ^x.y.z 的情况下,保持 x 不变,y,z 会取 path_provider flutter pub 上的最大值。
看到这里也许你会问,我没指定 path_provider_android的版本号,怎么就取最大值了?
因为
path_provider自己指定了
从上面图片中看到,五个不同的版本,都使用了 ^ 的方式指定版本号。因此会取各个平台的最大版本。
path_provider 支持五个平台。本地使用 flutter pub get 命令后,在自己项目的pubspec.lock 中也可以发现,即便 path_provider 版本固定为 2.0.9 ,这五个平台的版本号都会取 path_provider flutter pub 上的最大版本号。见下图。
。
查看 path_provider_android_2.0.26 的改动。
Adds a namespace for compatibility with WGP 8.0
path_provider_android github 提交记录
具体提交内容
寻找解决方案
更改 path_provider_android 的版本号
既然 flutter 团队增加了这个兼容性的 namespace 。我将 path_provider_android 版本号固定为 2.0.25 就行了。
在 pubspec.yaml 中增加一行即可。再运行 flutter get,就能正常编译了。
在 flutter 团队解决这个问题后,删除了这个固定版本号
flutter 团队在发现 agp4.1.2 无法兼容 namespace 字段后,及时做出响应。更新了 2.0.27 版本来解决问题。 所以我这里删除了这个固定版本号。
总结:我能做什么?
实际上我应该将 AGP 版本升高,至少升级到 4.2.0。本人前一篇文章就有过这样的兼容性问题,影响编译了。
花絮,从时间线看这个兼容性的问题是怎么发生的
4.20号有人反应 flutter 3.7.12 和 AGP 8.0 不兼容
4.21号 flutter 团队表示我们做了很多测试,很快兼容
我们最低测到了 AGP 4.2,4.2 版本还没有支持 namespace 字段,兼容都没问题。
从这里可以推测,namespace 在低版本的 AGP 中肯定可以用的。
后续他发现 AGP 4.1 不支持。
4.27号 有人陆续提 issue 表示 编译报错
#125607, #125605。 这两个 issue 都提示了 namsepace 导致编译问题。
当天 Flutter 团队确定了问题原因
他只测到了 AGP 4.2,没有测试到 AGP 4.1。
那些使用 Flutter 2.X 的人,创建出来的项目,AGP 版本会是 4.1.X。 并且还有一些类似我这样的项目,一直保持 AGP 版本不变。
那么他为什么没有测试到 AGP 4.1? 我觉得原因是他的 Flutter 版本是 3.X这个级别。
让开发者更新 AGP 版本比较困难,所以 Flutter plugin 做一次更新,兼容 namespace
#3836 解决了这个问题。我们看看代码,具体怎么兼容 AGP 4.1.X 甚至更早的版本。
检查是否存在 namespace 字段即可。