前言
历经几个月的拖延,我终于在今天下午决定将自己的项目从 AGP 7.1.2 & Gradle 7.3.3
迁移至 AGP 8.0+ & Gradle 8.0+
。整体过程还算顺利,但也遇到了一点问题,结果也比较有意思。本文就记录下迁移的过程。
开始
基本迁移
关于提升 AGP 版本,AS 内置了 AGP Upgrade Assistant,可以快速处理一些必要的变更。因此先拿它跑一下。
打开后选择目标版本,上面会清晰地列出将作出的变更。如果你发现 “Run selecyed steps” 按钮为灰色,那么可以查看左侧列表中是否有警告项,有的话可以按上面的提示先修复。之后点击按钮,开始跑
运行的过程还算顺利,在下载了一波相关依赖后,我们的项目终于……同步失败了~ 好吧,这也正常,看看报了啥错
compileDebugJavaWithJavac' task (current target is 1.8) and 'kspDebugKotlin' task (current target is 17) jvm target compatibility
顺带附了个链接:Configure a Gradle project | Kotlin Documentation ,打开一看,嚯,原来是 Java 版本不一样的问题
AGP 8.0 要求 JDK 17,这也是 Android Studio F 版本自带的 JDK 版本。
上面写到的解决方法有两种,一是升级 AGP,二是手动改。作为懒人,先试试第一条路?
尝试再次升级 AGP
打开 Maven 仓库搜一搜(Maven Repository),发现竟然都出到 8.2.0-alpha 了。不敢用不敢用,还是换个 8.1.0-beta 试试吧
更改版本,重新 sync …… 然后,有意思的事情来了,AS F 还不支持这个 AGP 版本,必须得 G 及以上才行
鉴于我的项目是开源的,要是再要求 AS 必须得是预览版的,这运行要求也太高了。所以还是换第二条路吧
手动指定
手动设置一下 Java 语言版本和 Kotlin 编译的目标版本
我直接一个全局替换,把两项都指定为 Java 17
compileOption | jvmTarget |
---|---|
至此,应用终于可以正常编译了。到这里的所有变化可以看 这个 Commit,其中大部分为 AGP Upgrade Assistant 自动完成的。
当然,迁移到这里还没有结束,如果查看 gradle.properties
的内容,会发现它为了平滑过渡,其实很多设置仍然保留的与之前相同,这里或许我们还可以改进一下
修改 Gradle.properties
先看看 AGP Upgrade Assistant 帮我们改了哪些内容
接下来我们一条一条看
buildconfig
如果你调用模块代码中的
BuildConfig
类,你需要在你的模块的build.gradle.kts
文件中,在android {}
块中启用buildConfig
。否则,BuildConfig
文件不再自动生成。
BuildConfig
文件是一个 Java 文件,包含关于当前构建的静态信息,例如命名空间名称、flavor 名称、调试标志等等。以前 AGP 总是为所有 Android 模块生成BuildConfig
文件。如果你开发一个多模块应用程序,你可能会得到许多 AGP 需要处理的BuildConfig
文件,这会影响你的构建速度。然而,大多数模块不需要从BuildConfig
类中获取任何信息。
此外,
BuildConfig
是一个 Java 文件。假设你的应用程序是用 Kotlin 编写的,在同一模块中混合 Java 和 Kotlin 会进一步影响构建性能。为了缓解这个问题,我们引入了设置在gradle.properties
中的android.enableBuildConfigAsBytecode
标志。当android.enableBuildConfigAsBytecode=true
时,BuildConfig
文件不再生成为 Java 文件,而是生成为编译文件。这避免了 Java 编译步骤!
我看了下我的代码,确实只有很少的模块用到了 BuildConfig
。因此将其值改回 false,并在需要 BuildConfig
的模块中添加:
nonFinalResIds
这个主要影响 Java 代码,具体来说,如果设置为 true,那你的 switch-case 里就不能写 id 了,因为它不是 final 的值。如下:
但我这个项目是 Kotlin + Jetpack Compose 的,完全不存在这个问题,因此设为 true 也没问题
nonTransitiveRClass
非传递R类,启用后,主工程不再合并 lib
库的 R
文件了,有助于加速编译。如果主工程用了子工程的资源,那引用 R
的写法都要变更下,需要加上完整的类名
AS 提供了一键迁移的按钮,点击后可以预览变更,一键处理
具体来说,处理后会变成这样:
至此,上面新增的三项配置项都可以使用默认值了。
到现在,debug 包可以正常运行了。然而,当我尝试 release
包时,它不出意外的报错了……
适配 Release 包
报的什么错呢?如下:
Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in D:\projects\AppProjects\Mine\FunnyTranslation\translate\build\outputs\mapping\release\missing_rules.txt.
打开这个文件看一下,内容如下:
# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-dontwarn java.awt.AWTEvent
-dontwarn java.awt.ActiveEvent
-dontwarn java.awt.BorderLayout
-dontwarn java.awt.Color
-dontwarn java.awt.Component
-dontwarn java.awt.Container
-dontwarn java.awt.Dimension
...
按第一行的提示,把里面的内容加入 proguard-rules
,重新打包,一切 OK
顺带一提,我关闭了 AGP 8.0 默认的 R8 full
模式,也就是
android.enableR8.fullMode=false
如果开启了 fullMode,则 R8 将更加激进,具体可以参考:R8 FAQ
到此的变更可以见 这里
变化
折腾了一通,最后效果是啥呢?
编译速度方面,按理说应该能提高一定的编译效率,更高地命中缓存。但这个忘记测量之前的数据了,就先不谈。
至于体积方面……一顿操作猛如虎,一看体积涨了五??!
当时我啪的一声站起来了,很快啊,这个 AGP,啊~,不讲武德,来骗,来偷袭,我 20 岁的小同志,这好吗?这不好。我去!我劝,好好反思,不要再耍这样的聪明,小聪明啊……
参考
- 5 ways to prepare your app build for Android Studio Flamingo release
- Android 更新后跑不起来?快来适配 AGP8 和 Flamingo/JDK 17
- Flamingo 和 AGP 8 来了,升吗?
本文源代码见:此处