Android15适配和Google上架问题

1.前言:
最近在把项目版本升级到35,并且上架的时候遇到一些问题,不过由于之前有很多这方面的经验,而且我的gradle版本一直是使用最新的,KSP和Kotlin版本也一直在更新,所以适配起来很快,花了1天就解决了所有问题,有蓝牙权限适配、文件读写权限适配、databingd修改、gms和ads版本升级、gralde版本升级、gms混淆等等,这里总结一下,记录适配的过程,直接上代码.
2.对于Android15的变更:
官网链接如下:
developer.android.google.cn/about/versi...
类别 | 类型 | |
---|---|---|
安全 | 变更(以 Android 15 及更高版本为目标平台的应用) | 安全的后台 activity 启动 对于以 Android 15 为目标平台的应用,我们进行了进一步的更改,以防止恶意后台应用将其他应用置于前台、提升其权限并滥用用户互动。 |
隐私设置 | 新功能和 API | 查询用户针对"已选照片访问权限"的最新选择 当授予对媒体权限的部分访问权限后,应用只能突出显示最近选择的照片和视频。 |
摄像头和媒体 | 变更(所有应用) | 当达到资源限制时,直接和分流音频播放会使之前打开的直接或分流音轨失效 从 Android 15 开始,当应用请求直接播放时,系统会使任何当前打开的直接 AudioTrack 对象失效,这些对象会阻止执行新轨道请求。 |
安全 | 新功能和 API | 端到端加密的密钥管理 使用 E2eeContactKeysManager 类可在 Android 应用中实现端到端加密 (E2EE)。 |
图形 | 新功能和 API | 对 Canvas 的改进 Android 15 继续通过新功能改进 Android 的 Canvas 图形系统。 |
安全 | 新功能和 API | 对内容 URI 执行权限检查 Android 15 引入了一组用于对内容 URI 执行权限检查的 API。 |
核心功能 | 变更(以 Android 15 及更高版本为目标平台的应用) | 对启动前台服务的 BOOT_COMPLETED 广播接收器的限制 对于以 Android 15 为目标平台的应用,BOOT_COMPLETED 接收器不得启动某些类型的前台服务。 |
核心功能 | 变更(所有应用) | 对软件包停止状态的更改 在 Android 15 中,应用只能通过直接或间接的用户操作从 FLAG_STOPPED 状态移除。除了现有限制之外,在 Android 15 上,当应用进入停止状态时,系统还会取消所有待处理 intent。 |
国际化 | 新功能和 API | 额外的日语变体假名字体 在 Android 15 中,系统默认捆绑了旧日语平假名(称为变体假名)的字体文件。 |
大屏设备和外形规格 | 新功能和 API | 封面屏幕支持 您的应用可以声明一个属性,Android 15 会使用该属性来允许您的 Application 或 Activity 显示在受支持的可翻转设备的小封面屏幕上。 |
图形 | 新功能和 API | 改进 Android 的 GPU 访问方式 Android 15 包含 ANGLE 作为可选层,用于在 Vulkan 基础上运行 OpenGL® ES;ANGLE 已在某些新设备上作为 GL 系统驱动程序提供,并且新 Android 设备将改为仅通过 ANGLE 支持 OpenGL。 |
开发者工作效率和工具 | 新功能和 API | 改进了 OpenType 可变字体 API Android 15 提高了 OpenType 可变字体的易用性。 |
大屏设备和外形规格 | 新功能和 API | 改进了大屏幕多任务处理 Android 15 为用户提供了更好的方式在大屏设备上进行多任务处理。 |
无障碍 | 新功能和 API | 改进了盲文 在 Android 15 中,我们让 TalkBack 能够支持通过 USB 和安全蓝牙使用 HID 标准的盲文显示屏。 |
用户体验和系统界面 | 新功能和 API | 改进了勿扰规则 借助 AutomaticZenRule ,应用可以自定义注意力管理(勿扰)规则,并决定何时启用或停用这些规则。Android 15 大大增强了这些规则,旨在提升用户体验。 |
安全 | 变更(以 Android 15 及更高版本为目标平台的应用) | 更安全的 intent 对于以 Android 15 为目标平台的应用,以特定组件为目标的 intent 必须与目标的 intent 过滤器规范完全匹配,并且没有操作的 intent 不再与任何 intent 过滤器匹配。 |
摄像头和媒体 | 新功能和 API | 更高效的 AV1 软件解码 VideoLAN 的热门 AV1 软件解码器 dav1d 现已面向不支持硬件 AV1 解码的 Android 设备推出。 |
连接 | 新功能和 API | 更顺畅的 NFC 体验 Android 15 正在努力让感应式付款体验更加顺畅可靠,同时继续支持 Android 强大的 NFC 应用生态系统。 |
限制非 SDK 接口 | 变更(以 Android 15 及更高版本为目标平台的应用) | 更新了非 SDK 接口限制 Android 15 包含更新后的受限制非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。 |
摄像头和媒体 | 变更(以 Android 15 及更高版本为目标平台的应用) | 关于请求音频焦点的限制 以 Android 15 为目标平台的应用必须是顶部应用或正在运行与音频相关的前台服务,才能请求音频焦点。 |
核心功能 | 变更(以 Android 15 及更高版本为目标平台的应用) | 关于应用何时可以修改勿扰模式全局状态的变更 以 Android 15 为目标平台的应用无法再更改设备上的勿扰 (DND) 全局状态或政策(无论是通过修改用户设置还是关闭勿扰模式)。 |
用户体验和系统界面 | 新功能和 API | 画中画 从 Android 15 开始,画中画动画开始后,Activity#onPictureInPictureUiStateChanged 回调会立即触发。 |
隐私设置 | 新功能和 API | 健康数据共享 Android 15 集成了与 Android Health Connect 相关的最新扩展程序。Health Connect 是一个安全的集中式平台,可用于管理和分享应用收集的健康与健身数据。此更新增加了对健身、营养、体表温度、训练计划等数据类型的支持。 |
安全 | 新功能和 API | 将 Credential Manager 与自动填充功能集成 从 Android 15 开始,开发者可以将用户名或密码字段等特定视图与 Credential Manager 请求相关联,从而更轻松地在登录过程中提供量身定制的用户体验。 |
安全 | 新功能和 API | 将一键式注册和登录与生物识别提示集成 Credential Manager 会将生物识别提示集成到凭据创建和登录流程中,这样提供程序就无需管理生物识别提示。 |
开发者工作效率和工具 | 新功能和 API | 精细的换行控制 从 Android 15 开始,TextView 和底层换行符可以将给定部分文本保留在同一行中,以提高可读性。 |
隐私设置 | 新功能和 API | 局部屏幕共享 Android 15 支持局部屏幕共享,因此用户可以仅共享或录制应用窗口,而不是整个设备屏幕。此功能首次在 Android 14 QPR2 中启用,包含 MediaProjection 回调,可让您的应用自定义部分屏幕共享体验。 |
隐私设置 | 新功能和 API | 扩展了 IntentFilter 功能 Android 15 内置了通过 UriRelativeFilterGroup 支持更精确的 Intent 解析功能,其中包含一组 UriRelativeFilter 对象,这些对象构成了一组必须满足的 Intent 匹配规则,包括网址查询参数、网址片段以及屏蔽或排除规则。 |
核心功能 | 变更(以 Android 15 及更高版本为目标平台的应用) | 媒体处理前台服务类型 Android 15 引入了一种新的前台服务类型 mediaProcessing 。此服务类型适用于转码媒体文件等操作。 |
用户体验和系统界面 | 新功能和 API | 媒体投屏状态栏条状标签和自动停止 Android 15 QPR1 为媒体投屏(屏幕共享、投放和录制)添加了醒目的状态栏指示器,以确保用户了解正在进行的媒体投屏,并提供用于停止投屏的易于访问的控件。此外,当设备屏幕锁定时,正在进行的媒体投影会自动停止。 |
核心功能 | 变更(所有应用) | 某些应用若要支持私密空间,需要进行哪些必要更改 私密空间是 Android 15 的一项功能,可让用户在设备上创建一个单独的空间,在额外的身份验证层保护下,将敏感应用隐藏起来,不让外人窥探。由于私密空间中的应用具有受限的可见性,因此某些类型的应用需要执行额外的步骤才能查看和与用户私密空间中的应用互动。 |
隐私设置 | 新功能和 API | 屏幕录制检测 Android 15 添加了对应用的支持,以检测是否正在录制应用。 |
连接 | 新功能和 API | 钱包角色 Android 15 引入了钱包角色,可与用户首选的钱包应用进行更紧密的集成。 |
摄像头和媒体 | 新功能和 API | 弱光增强 Android 15 引入了弱光增强功能,这是一种可同时用于 Camera 2 和夜间模式相机扩展程序的自动曝光模式。 |
用户体验和系统界面 | 新功能和 API | 使用 Generated Previews API 实现更丰富的 widget 预览 从 Android 15 开始,我们将添加对生成的预览的支持。这意味着,应用微件提供程序可以生成 RemoteViews 来用作选择器预览,而不是静态资源。 |
摄像头和媒体 | 废弃 | 使用 Spatializer 而非 Virtualizer 在 Android 15 中,我们将废弃 Virtualizer 类。 |
安全 | 变更(以 Android 15 及更高版本为目标平台的应用) | 受限的 TLS 版本 Android 15 限制了 TLS 1.0 和 1.1 版本的使用。 这些版本之前已在 Android 中废弃,但现在不允许面向 Android 15 的应用使用。 |
隐私设置 | 新功能和 API | 私密空间 借助私密空间,用户可以在设备上创建一个单独的空间,在额外的身份验证层保护下,将敏感应用隐藏起来,不让好奇的他人看到。私密空间中的应用会显示在启动器的单独容器中,并且在私密空间处于锁定状态时,这些应用会从最近用过的应用列表、通知、设置和其他应用中隐藏。 |
连接 | 新功能和 API | 卫星连接支持 Android 15 继续扩展了平台对卫星连接的支持,并包含了一些界面元素,以确保在卫星连接领域提供一致的用户体验。 |
用户体验和系统界面 | 新功能和 API | 为通知渠道设置 VibrationEffect Android 15 支持按渠道为传入通知设置丰富的振动。 |
用户体验和系统界面 | 变更(所有应用) | 为选择启用的应用启用了预测性返回动画 移除了预测性返回动画的开发者选项。相反,如果应用已选择完全或在 activity 级别启用预测性返回手势,则系统会为其显示"返回主屏幕""跨任务"和"跨 activity"等系统动画。 |
用户体验和系统界面 | 变更(以 Android 15 及更高版本为目标平台的应用) | 稳定配置 如果您的应用以 Android 15 或更高版本为目标平台,Configuration 将不再排除系统栏。 |
用户体验和系统界面 | 变更(以 Android 15 及更高版本为目标平台的应用) | 无边框强制执行 对于以 Android 15 为目标平台的应用,我们将纳入与无边框相关的几项更改。如果您的应用在屏幕顶部或底部附近有界面元素,并且您的应用不处理内嵌,这些更改可能会对应用的用户体验产生负面影响。 |
性能和电池 | 新功能和 API | 详细的应用大小信息 Android 15 添加了 StorageStats.getAppBytesByDataType([type]) API,可让您深入了解应用如何使用所有这些空间,包括 APK 文件分块、AOT 和加速相关代码、dex 元数据、库和引导式配置文件。 |
摄像头和媒体 | 新功能和 API | 虚拟 MIDI 2.0 设备 Android 15 将 UMP 支持扩展到了虚拟 MIDI 应用,使作曲应用能够像使用 USB MIDI 2.0 设备一样,将合成器应用作为虚拟 MIDI 2.0 设备进行控制。 |
核心功能 | 变更(所有应用) | 移除了基于 PNG 的表情符号字体 已移除基于 PNG 的旧版表情符号字体文件 (NotoColorEmojiLegacy.ttf ),仅保留了基于矢量的文件。 |
摄像头和媒体 | 新功能和 API | 音量控制 Android 15 引入了基于 CTA-2075 音量标准的 LoudnessCodecController API。此 API 可帮助您管理音量不一致问题,确保用户在内容或应用之间切换时无需不断调节音量。 |
性能和电池 | 新功能和 API | 应用管理的性能分析 Android 15 包含 ProfilingManager 类,可让您从应用中收集性能分析信息。 |
开发者工作效率和工具 | 新功能和 API | 应用归档 Android 15 包含对应用归档和解压缩的操作系统级支持,可让所有应用商店更轻松地实现这些操作。 |
摄像头和媒体 | 新功能和 API | 应用内相机控件 Android 15 添加了扩展程序,以便更好地控制受支持设备上的相机硬件及其算法。 |
核心功能 | 废弃 | 在 Android WebView 中废弃了 WebSQL WebSettings 中与 WebSQL 相关的方法已废弃。 |
核心功能 | 变更(所有应用) | 支持 16 KB 页面大小 从 Android 15 开始,Android 系统支持配置为使用 16 KB 页面大小的开发设备。如果您的应用中使用了原生代码,则应重新构建应用以支持 16 KB 设备,并且所有开发者都应使用 16 KB 环境测试其应用,以验证应用行为是否没有意外回归。 |
国际化 | 新功能和 API | 字符间对齐 从 Android 15 开始,您可以使用 JUSTIFICATION_MODE_INTER_CHARACTER 利用字母间距对齐文本。 |
国际化 | 新功能和 API | 自动换行配置 在 Android 15 中,应用只能使用 LINE_BREAK_WORD_STYLE_AUTO 选项为短文本行应用基于短语的换行。 |
开发者工作效率和工具 | 新功能和 API | 自动切换语言的优化 Android 15 添加了其他控件,以帮助应用根据其用例调整自动切换语言。 |
核心功能 | 变更(所有应用) | 最低可安装目标 API 级别 用户无法安装 targetSdkVersion 低于 24 的应用。 |
性能和电池 | 新功能和 API | Android 动态性能框架更新 Android 15 继续投资于 Android 动态性能框架 (ADPF),这组 API 可让游戏和性能密集型应用更直接地与 Android 设备的电源和散热系统互动。 |
性能和电池 | 新功能和 API | ApplicationStartInfo API Android 15 上的 ApplicationStartInfo API 有助于深入了解应用启动,包括启动状态、在启动阶段所花的时间、在实例化 Application 类时应用的启动方式等。 |
国际化 | 新功能和 API | CJK 可变字体 从 Android 15 开始,面向中文、日文和韩文 (CJK) 的字体文件 NotoSansCJK 是一种可变字体。 |
用户体验和系统界面 | 变更(以 Android 15 及更高版本为目标平台的应用) | EditText 的语言区域感知型默认行高 对于以 Android 15 为目标平台的应用,系统会为 EditText 预留最小行高,以匹配指定 Locale 的参考字体。 |
用户体验和系统界面 | 变更(以 Android 15 及更高版本为目标平台的应用) | elegantTextHeight 属性默认为 true 对于以 Android 15 为目标平台的应用,elegantTextHeight TextView 属性默认为 true ,将默认使用的紧凑字体替换为一些具有较大垂直测量值的脚本,使其更易于阅读。 |
摄像头和媒体 | 新功能和 API | HDR 余量控制 借助 Android 15,您可以使用 setDesiredHdrHeadroom 控制 HDR 余量,以便在 SDR 和 HDR 内容之间取得平衡。 |
开发者工作效率和工具 | 新功能和 API | OpenJDK 17 更新 Android 15 将继续更新 Android 的核心库,以与最新 OpenJDK LTS 版本中的功能保持一致。 |
核心功能 | 变更(以 Android 15 及更高版本为目标平台的应用) | OpenJDK API 变更 在 OpenJDK API 更新中,有一些变更可能会影响应用兼容性,例如对某些字符串格式设置 API、语言代码处理和随机 int 序列的更改。 |
开发者工作效率和工具 | 新功能和 API | PDF 改进 Android 15 对 PdfRenderer API 进行了大幅改进。 |
隐私设置 | 新功能和 API | Privacy Sandbox on Android Android 15 包含最新的 Android 广告服务扩展程序,其中包含最新版本的 Privacy Sandbox on Android。我们一直致力于开发可保护用户隐私并为移动应用打造有效的个性化广告体验的技术,此次添加新功能就是这项工作的一部分。 |
性能和电池 | 新功能和 API | SQLite 数据库改进 Android 15 引入了 SQLite API,这些 API 可公开底层 SQLite 引擎的高级功能,以解决可能在应用中出现的特定性能问题。 |
用户体验和系统界面 | 变更(以 Android 15 及更高版本为目标平台的应用) | TextView 更改了复杂字母形状的宽度 在旧版 Android 中,一些具有复杂形状的草书字体或语言可能会在前一个或下一个字符的区域中绘制字母。在某些情况下,此类字母会在开头或结尾处被截断。从 Android 15 开始,TextView 会分配宽度,以便为此类字母绘制足够的空间,并允许应用请求向左额外添加内边距以防止剪裁。 |
3.上架被拒:

4.dexOptions 过时:
出现的错误:
ini
dexOptions {
jumboMode = true
}


修改后运行没有此警告发现提示gradle plugin版本不对.

5.gradle版本修改:
这个警告说明你正在使用的 Android Gradle 插件版本 (7.2.0) 与你指定的 compileSdk 版本 (35) 不匹配。
Android Gradle 插件 7.2.0 最高只支持到 compileSdk 32,而你现在使用的是 compileSdk 35,这会导致不兼容问题。
vbnet
We recommend using a newer Android Gradle plugin to use compileSdk = 35
This Android Gradle plugin (7.2.0) was tested up to compileSdk = 32
This warning can be suppressed by adding
android.suppressUnsupportedCompileSdk=35
to this project's gradle.properties
The build will continue, but you are strongly encouraged to update your project to
use a newer Android Gradle Plugin that has been tested with compileSdk = 35
没改前的gradle版本:


修改后的gradle版本:
scss
ext {
agp_version = '8.10.0'
}
repositories {
google()
jcenter()
mavenCentral()
ini
#Tue Sep 20 09:56:16 CST 2022
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-bin.zip

再次运行发现项目编译成功.

6.关于databinding的修改:
在Android15中databinding的使用方式变了,绑定view从R.id.xx变成R2.id.xx


修改完之后再次运行发现不报错了,项目也能跑起来。


7.文件读写权限适配:
由于之前适配过,很快就找到解决方法了,这里直接上连接和代码.
官网参考链接地址:developer.android.google.cn/about/versi...

没改之前的代码:
kotlin
private boolean checkAndRequestStoragePermissions() {
{
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
RequestPermissionManager.instance().with(this).requestReadWritePermission(this);
return false;
}
}
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.READ_PHONE_STATE)) {
RequestPermissionManager.instance().with(this).request(this, Manifest.permission.READ_PHONE_STATE);
return false;
}
return true;
}
修改之后的代码:区分Android版本大于等于13和小于13,由于项目中没有使用图片和拍照后面把这2个权限去掉了,因为Google上架的时候审核很严格,项目中没有的功能是不允许申请权限的.
kotlin
private boolean checkAndRequestStoragePermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.READ_MEDIA_IMAGES) ||
!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.READ_MEDIA_VIDEO) ||
!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.READ_MEDIA_AUDIO)) {
RequestPermissionManager.instance().with(this).request(
this,
Manifest.permission.READ_MEDIA_IMAGES,
Manifest.permission.READ_MEDIA_VIDEO,
Manifest.permission.READ_MEDIA_AUDIO);
return false;
}
} else {
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
RequestPermissionManager.instance().with(this).requestReadWritePermission(this);
return false;
}
}
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.READ_PHONE_STATE)) {
RequestPermissionManager.instance().with(this).request(this, Manifest.permission.READ_PHONE_STATE);
return false;
}
return true;
}
8.Manifest文件权限修改:
没改之前的代码:
ini
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
修改之后的的代码:
ini
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
9.蓝牙权限适配:
在Android12和Android13蓝牙权限分别有2次改变,具体的可以参考官网变化:
官网链接地址:developer.android.google.cn/develop/con...

- 新增蓝牙扫描权限适配
- 新增蓝牙连接权限适配
- 新增蓝牙可被其他设备检测到适配
修改前的代码:
kotlin
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) {
RequestPermissionManager.instance().with(this).request(this,
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION);
return false;
}
修改后的代码:
kotlin
//如果是Android12+检查新增的蓝牙权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.BLUETOOTH_CONNECT)) {
RequestPermissionManager.instance().with(this).request(this, Manifest.permission.BLUETOOTH_CONNECT);
return false;
}
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.BLUETOOTH_SCAN)) {
RequestPermissionManager.instance().with(this).request(this, Manifest.permission.BLUETOOTH_SCAN);
return false;
}
if (!RequestPermissionManager.instance().with(this).hasPermission(Manifest.permission.BLUETOOTH_ADVERTISE)) {
RequestPermissionManager.instance().with(this).request(this, Manifest.permission.BLUETOOTH_ADVERTISE);
return false;
}
}
10.Mainifest文件修改:
修改前的代码:
ini
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
修改后的代码:
ini
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" tools:targetApi="s"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
11.gms服务插件升级:
升级前的版本:
kotlin
dependencies {
classpath "com.android.tools.build:gradle:$agp_version"
// classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0'
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.1'//添加butterknife插件的引用
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.google.gms:google-services:3.3.0'
}

升级后的版本:
kotlin
dependencies {
classpath "com.android.tools.build:gradle:$agp_version"
// classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0'
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.1'//添加butterknife插件的引用
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.google.gms:google-services:3.3.0'
}
12.gms和ads相关依赖升级:
升级前代码:
java
//firebase
implementation platform ("com.google.firebase:firebase-bom:29.1.0")
implementation "com.google.firebase:firebase-analytics"
implementation "com.google.firebase:firebase-auth"
implementation "com.google.firebase:firebase-firestore"
//google ads
implementation 'com.google.android.gms:play-services-ads:22.1.0'//20.6.0' //The minCompileSdk (31)
implementation 'com.google.android.ads:mediation-test-suite:2.0.0' //test tools

升级后的代码:
java
//firebase
implementation platform ('com.google.firebase:firebase-bom:32.3.1')
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-firestore-ktx'
//google ads
implementation 'com.google.android.gms:play-services-ads:24.4.0'//20.6.0'
implementation 'com.google.android.ads:mediation-test-suite:3.0.0'
implementation 'com.google.android.gms:play-services-basement'
implementation 'com.google.android.gms:play-services-tasks'
13.protobuf混淆:
diff
# ===== 核心 protobuf 保留规则 =====
-keep class com.google.protobuf.** { *; }
-dontwarn com.google.protobuf.**
# ===== GeneratedMessageLite 及其子类 =====
-keep class com.google.protobuf.GeneratedMessageLite { *; }
-keep class com.google.protobuf.GeneratedMessageLite$* { *; }
-keep class com.google.protobuf.AbstractMessageLite { *; }
-keep class com.google.protobuf.AbstractMessageLite$* { *; }
# ===== Extendable 相关类 =====
-keep class com.google.protobuf.GeneratedMessageLite$ExtendableBuilder { *; }
-keep class com.google.protobuf.GeneratedMessageLite$ExtendableMessage { *; }
-keep interface com.google.protobuf.GeneratedMessageLite$ExtendableMessageOrBuilder { *; }
# ===== 方法调用相关 =====
-keep class com.google.protobuf.GeneratedMessageLite$MethodToInvoke { *; }
-keep class com.google.protobuf.GeneratedMessageLite$DefaultInstanceBasedParser { *; }
# ===== 保留所有构建器 =====
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
public static ** newBuilder();
public ** toBuilder();
public ** build();
public ** buildPartial();
public ** getDefaultInstanceForType();
public ** getParserForType();
}
# ===== 保留所有枚举 =====
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# ===== 保留所有内部类 =====
-keep class *$* { *; }
-keep class com.google.protobuf.** { *; }
-keep interface com.google.protobuf.** { *; }
-dontwarn android.os.ServiceManager*
-dontwarn com.bun.miitmdid.core.MdidSdkHelper*
-dontwarn com.bun.miitmdid.interfaces.IIdentifierListener*
-dontwarn com.bun.miitmdid.interfaces.IdSupplier*
-dontwarn com.google.firebase.iid.FirebaseInstanceId*
-dontwarn com.google.firebase.iid.InstanceIdResult*
-dontwarn com.google.protobuf.ByteString
-dontwarn com.google.protobuf.CodedInputStream
-dontwarn com.google.protobuf.CodedOutputStream
-dontwarn com.google.protobuf.ExtensionRegistryLite
-dontwarn com.google.protobuf.GeneratedMessageLite
-dontwarn com.google.protobuf.GeneratedMessageLite$Builder
-dontwarn com.google.protobuf.Int32Value
-dontwarn com.google.protobuf.Int32Value$Builder
-dontwarn com.google.protobuf.Internal**
-dontwarn com.google.protobuf.InvalidProtocolBufferException
-dontwarn com.google.protobuf.MapFieldLite
-dontwarn com.google.protobuf.MessageLite
-dontwarn com.google.protobuf.MessageLiteOrBuilder
-dontwarn com.google.protobuf.NullValue
-dontwarn com.google.protobuf.Parser
-dontwarn com.google.protobuf.Timestamp
-dontwarn com.google.protobuf.Timestamp$Builder
-dontwarn com.google.protobuf.DescriptorProtos
-keep class com.google.protobuf.DescriptorProtos$* { *; }
-keep class com.google.protobuf.DescriptorProtos$DescriptorProto { *; }
-keep class com.google.protobuf.DescriptorProtos$EnumOptions { *; }
-keep class com.google.protobuf.DescriptorProtos$ExtensionRangeOptions { *; }
-keep class com.google.protobuf.DescriptorProtos$EnumOptions$Builder { *; }
# 忽略org.jspecify.nullness包下的类缺失
-dontwarn org.jspecify.nullness.**
-keep class org.jspecify.nullness.Nullable { *; }
14.gms和ads混淆:
kotlin
-keep class com.tradplus.ads.** { *; }
# Firebase 通用保留规则
-keepattributes Signature
-keepattributes *Annotation*
-keepattributes EnclosingMethod
-keepclassmembers class * {
@com.google.firebase.database.annotations.NotNull public *;
@com.google.firebase.database.annotations.Nullable public *;
}
# Google Play Services
-keep class com.google.android.gms.** { *; }
-keep class com.google.ads.** { *; }
-keep class com.google.firebase.** { *; }
# Dynamite 模块
-keep class com.google.android.gms.dynamite.** { *; }
-keep class * extends com.google.android.gms.dynamite.DynamiteModule$DynamiteLoaderClassLoader
# 测量相关
-keep class com.google.android.gms.ads.measurement.** { *; }
-keep class com.google.android.gms.measurement.** { *; }
# Firebase Analytics 保留规则
-keep class com.google.firebase.provider.** { *; }
-keep class com.google.android.gms.measurement.AppMeasurement { *; }
-keep class com.google.android.gms.measurement.AppMeasurement$** { *; }
-keep class com.google.android.gms.measurement.internal.zzhx { *; }
-keep class com.google.firebase.analytics.FirebaseAnalytics { *; }
-keep class com.google.android.gms.analytics.** { *; }
-keep interface com.google.android.gms.analytics.** { *; }
# 通用 Firebase 保留规则
-keep class com.google.firebase.** { *; }
-keepnames class com.google.firebase.** { *; }
-dontwarn com.google.firebase.**
15.总结:
以上就是在项目升级到35和上架Google遇到的问题,由于之前都遇到过,所以花了不到一天全部解决,不过由于自己项目不熟悉和没测试全面所以后面又发了新包重新上架,基本上经过以上修改和多次自测后又重新打包上架,通过了Google审核.如果有遇到类似问题的同学可以参考一下,当然还有其他的适配我们由于项目问题不需要,大家需要根据自己的项目进行适配,希望本文对你有用,开发路漫漫,需要不断学习成长.
- gradle版本升级.
- databinding使用方式修改.
- 文件读写权限细化适配.
- 没有使用拍照和图片不允许申请权限,后面把这2个去掉了.
- 蓝牙权限适配.
- protobuf混淆.
- gms和ads混淆,如果没有使用Google广告就不需要申请权限和混淆.
- 由于项目使用的是纯Java,没有Kotlin和KSP这些,所以不需要升级kotlin版本和ksp插件.
- 当然Android15还有其他的适配,只是我们由于项目原因我只讲解核心的,因为有些东西我们项目不需要,所以这里没有讲解其他的.基本上这些修改完之后满足了上架规则和需求.