android AGP配置对Java版本支持的梳理
本文目标
很多时候业务开发者想用一些比较便捷的api实现功能, 发现要改工程配置, 而如果对工程配置的概念不理解,很可能会牵一发动全身.
本文就是对配置AGP中涉及的Java版本做了一下整理, 就是单纯的厘清概念, 没有高深的源码分析. 因为没有自己的干货,全是网络搜索的结果, 所以外链会比较多.
compileSdkVersion
每次升级compileSdkVersion, 我们都会下载相应的android SDK, 获得相应的android 特性开发能力, 这里面也包含对应的Java SDK, 也就是说我们能使用什么Java Api 是由compileSdkVersion 对应的Java 版本决定的, 和我们电脑本地的Java SDK版本没关系
毕竟如果我们想要在android 6上使用Java 19的特性, 也要android 6支持才可以.
By default, the Java language version used to compile your project is based on your project's
compileSdkVersion
根据Android各版本对应的SDK及JDK版本要求 我们可以看到在android12上我们可以使用JDK11进行开发, 而在即将发布的android14,我们可以使用JDK17.
Gradle
适用于android和Java工程的构建工具, 基于JVM. 构建是在我们电脑上或者远程服务器构建, 而不是用户的手机上,所以需要在构建机器上具备JRE环境. 是的,因为我们不是开发Gradle, 仅仅是使用现成的Gradle工具构建Android代码,所以只需要JRE即可。而Android Studio会内置JRE,所以我们就选择内置JRE就好, 如果有需要可以选择我们电脑上已安装的其他版本JRE.(可以通过删除JDK环境变量配置,来判断是需要JDK还是JRE)
不同版本的Gradle对JRE有不同要求, 比如Gradle7.0以前要求是JRE1.8, 7.X版本要求是JRE11, 8.X版本则是要求JRE17.
AGP
Android Gradle Plugin(简称AGP) 是用于在Android Studio中对项目工程代码构建的插件. 其作用是在我们项目代码和Gradle之间架起一座桥梁, 方便我们在Android Studio中直接构建, 而不需要借助命令行或其他工具. 既然是起到桥梁作用,那就需要和两边的Java的环境相匹配.
适配Gradle JDK版本
在AGP7.X之后的大版本都和Gradle大版本要求的JDK版本保持一致, 为JDK11, JDK17, 在AGP7.0之前则为JDK1.8
When using Android Gradle plugin 7.0 to build your app, JDK 11 is now required to run Gradle. Android Studio Arctic Fox bundles JDK 11 and configures Gradle to use it by default, which means that most Android Studio users do not need to make any configuration changes to their projects.
When using Android Gradle Plugin 8.0 to build your app, JDK 17 is now required to run Gradle. Android Studio Flamingo bundles JDK 17 and configures Gradle to use it by default, which means that most Android Studio users don't need to make any configuration changes to their projects.
具体可参见: developer.android.google.cn/build/relea…
developer.android.google.cn/build/relea…
需要注意的是,在我们升级Android Studio后, 如果当前AS还兼容工程配置的AGP版本, 那么AGP和Gradle不升级也可以,否则就需要升级. 开发者需要自行注意AS与AGP的兼容情况和相关api改动
适配项目工程 JDK版本
AGP 默认构建JDK 版本
首先说一下,AGP其实是有自己默认的构建JDK版本的, 即不管我们用指定什么JDK版本开发(compileSdkVersion), AGP都会用它默认的JDK版本编译.在AGP4.2.0以前的版本, AGP采用Java1.7编译,而在AGP4.2.0之后的版本采用的是Java1.8编译
Starting in version 4.2, AGP will use the Java 8 language level by default.
那么问题来了, 用一个JDK版本开发,用另一个JDK编译, 那么编译肯定会出问题, 我们开发者岂不是要等到编译时才会注意到出现了 JDK版本问题? 那IDE给出的解决方案是采用lint.
不同版本的Android Studio对应不同版本AGP, 也同时对应着不同的lint规则. 这样当我们用不同的compileSdkVersion开发时, lint工具就会发现我们开发使用的JDK Api与编译JDK Api的不同, 并给出警告或者错误.
但是如果始终要保持与编译JDK版本一致,不是意味着我们只能一直使用JDK1.8或者JDK1.7的特性?
AGP 适配构建JDK 版本
// build.gradle
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
通过上述配置,我们可以更改AGP的构建版本为指定的JDK版本, 注意,只要需要的编译版本和默认版本不一致就需要这样处理, 无论我们需要的是JDK1.8,还是JDK11, JDK17, 当然最高的JDK版本约束还是compileSdkVersion的JDK版本.
而这个适配配置和上面的Gradle JDK版本没有关系, 即使Gradle已经要求了JDK 17, 这里我们依然可以使用JDK1.8版本进行编译.
而这个适配配置的更改实际上就是在编译执行javac命令时,配置的参数,比如:
path/to/jdk9/bin/javac Compile8Test.java -source 8 -target 8
如果没有-source选项,编译器将根据所使用的 Java 版本使用源代码进行编译。
target 选项指定要生成的类文件的 Java 版本。target版本必须等于或高于source版本
参考A Guide to Java Source and Target Options
验证
- 随便使用某个版本的AS创建一个android示例工程,可以采用最新版本
- 在相关配置都同步好,可以运行时,clean工程,再次build
- 在app/build/intermediates/javac/debug/classes/包名文件夹下可以找到刚才编译的MainActivity.class字节码文件
- 把这个字节码文件路径复制下,或者文件挪到其他位置, 在终端运行:
javap -v 文件夹路径/MainActivity.class
可以看到终端输出很多东西, 而在其中就有编译所使用的JDK 版本:
version55对应Java11 (参考维基) , 之后可以删除/更改适配配置, 再次clean,build 查看版本变化
Kotlin的JVM版本
Kotlin在1.5版本以前还是JDK1.6但在1.5版本之后就是1.8, 我们也可以同样在APG中进行配置, 只不过配置Kotlin的同时需要配置相同版本的Java:
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
官方也提供了AGP对Kotlin的兼容版本说明:
D8 and R8 compiler versions required for Kotlin versions
低版本系统适配:D8
我们用了JDK11, 17开发, android高版本系统支持, 可是低版本系统呢? 怎么处理这些新特性呢, 答案就是脱糖
d8
通过一个叫做“脱糖”的编译过程,使您能够在代码中使用 Java 8 语言功能。脱糖会将这些实用的语言功能转换为可以在 Android 平台上运行的字节码。 Android Studio 和 Android Gradle 插件包含了d8
为您启用脱糖所需的类路径资源。
在Androd Studio 3.0.0版本就开始支持了D8, 不过3.X版本仅仅支持Java8, 而如果想使用更高版本JDK Api并运行在低版本系统上, 则需要使用Android Studio 4.X以上版本, 同时为了使用更加广泛的支持脱糖的Api, 我们可以在APG里配置:
android {
defaultConfig {
// Required when setting minSdkVersion to 20 or lower
multiDexEnabled true
}
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
}
具体可参见:
Android 的 Java 9、10、11 和 12 支持
本文参考
转载自:https://juejin.cn/post/7224341322612867129