现在 AI 时代,我觉得很多技术博客没必要写了,但最近将一个七年前的 Android 项目兼容 Android15,花了不少时间,累麻了,而且一些问题 AI 也没帮到我,所以做个记录,希望帮到有需要的人。
Google Play 政策要求(2025 年 8 月 31 日前必须使用目标 API ≥ 35),App 更新必须以 Android 15(API 级别 35),否则不能发布 App。之前发布的以后不能更新,只能下载。国内这些应用市场还没这个要求,可能将来也会有。当然,国内市场也有很多屁事,比如近期小作文,要发布鸿蒙版本,否则不给通过软著,而没软著就不能发布市场。。。
扯远了,总之,如果你也有这个需求,可以接着看。
这是我目前的环境
Android Studio Iguana 2023
JDK 17
AGP 8.3.2
我之前使用使用 targetSdkVersion 33,AGP 是 7.x,项目打包运行都没问题,在这个基础上修改兼容 35。
建议不要尝试在 AGP 7.x 情况下编译 targetSdkVersion 35,我也不想升级 Gradle 版本,但我试过两天都没搞定,报错如下
android-35 java.lang.NullPointerException
网上有帖子貌似可以突破解决这问题,在 gradle.properties 配置如下:
android.aapt2FromMavenOverride=/Users/guozh/Library/Android/sdk/build-tools/35.0.0/aapt2
反正上面方案对我没用,总是会报 D8 错误,然后我又尝试了各种禁用方案,也尝试在混淆文件中排除,反正都试了,都没解决,没辙,只能升级到 AGP 8.x。
AGPBI: {“kind”:”error”,”text”:”java.lang.NullPointerException”,”sources”:[{“file”:”/Users/xxx/Library/Android/sdk/platforms/android-35/android.jar”}],”tool”:”D8″}
这是我目前使用的 AGP 版本
classpath ‘com.android.tools.build:gradle:8.3.2’
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
修改 targetSdkVersion 和 compileSdkVersion 到 35,先不要同步,把以下内容一起改了。
工程下所有模块都要使用 namespace,不止 app,其他模块都添加,namespace 的值是 AndroidManifest.xml 的包名 package。
android {
namespace ‘com.guozh.xxx’
…
defaultConfig {
}
}
然后在每个模块下添加 buildConfig = true,一样,每个模块的 gradle 都要加,这是 AGP8.0 的新特性。
buildFeatures {
// aidl true // 如果模块没用AIDL,这里不用管,可注释
buildConfig = true
}
再处理根目录 build.gradle,将 repositories 迁移到 settings.gradle,这也是新特性,不改也是可以,但我总感觉有几个编译报错与这里有关,索性一起改了。
根目录 build.gradle
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.3.2'
}
}
根目录 settings.gradle
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal() // 这是 Gradle 官方插件仓库
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// 其他远程仓库,根据你原项目添加和修改
// maven { url 'https://jitpack.io' }
// maven { url 'https://maven.aliyun.com/repository/google' } // 兼容旧版 google
// maven { url 'https://maven.aliyun.com/repository/jcenter' } // 兼容旧版 jcenter
// 集中声明 flatDir,让所有模块都能访问 app/libs
flatDir {
dirs 'app/libs'
}
}
}
rootProject.name=‘xxxx'
include ':app'
include ‘:xxxx'
出现元素值必须为常量表达式,这是因为 R 文件字段不再是常量,Gradle8.0+ 和 ButterKnife 的不兼容导致,这个问题我也是在官方issues找到解决方案的。现在推荐 viewBinding ,但这是之前老项目,替换成本太高了,只能想办法突破。
修改 app/build.gradle (或者其他使用 ButterKnife 的模块的 build.gradle),在 app 模块的 build.gradle 文件中,在文件的最底部,添加以下代码块:
tasks.withType(JavaCompile).configureEach {
options.fork = true
options.forkOptions.jvmArgs += [
'--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',
'--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED',
]
}
修改 gradle.properties (根目录)
# 解决 @BindView 报错 "元素值必须为常量表达式"
# 这个属性告诉 AGP 不要使用非 final 的资源 ID
android.nonFinalResIds=false
顺便把 gradle.properties 里的 JDK 版本也固定了,这一步做不做无所谓,因为 JDK 的版本一般在 Android Studio 的设置了。如果没有,在 Gradle JDK 选项中,从下拉菜单里选择一个 版本为 17 或更高 的 JDK。通常 Android Studio 会自带一个,名字可能类似于 jbr-17 或 Android Studio java home version 17,选择它即可。
Build, Execution, Deployment -> Build Tools -> Gradle
如果存在多模块引用资源,比如在 app 引用其他模块 basic_res 的颜色、文本,也会出现元素值必须为常量表达式的报错。因为新版 AGP 默认将 R 文件的字段设置为了非 final 。解决这个问题很简单,要么拷贝一份资源到 app 模块,要么使用用完整的包名来引用。
比如修改前是这样的
ResUtils.getColor(context, R.color.main);
修改后
ResUtils.getColor(context, com.guozh.basic.res.R.color.main);
ok,希望以上能帮到你。
本文由老郭种树原创,转载请注明:https://guozh.net/app-compatible-with-android-15/