Android 15适配方案及常见问题

谷歌发布Android 15后,国内的手机厂商迅速行动,开始了新系统的适配工作。小米、OPPO、vivo和联想等金标联盟成员联合发布了适配公告,督促APP开发者在2024年8月31日前完成适配工作,否则将面临搜索标签提示、应用降级、分机型屏蔽以及应用下架等处罚措施。

1.准备工作

Android 15 SDK 包含一些与一些较低版本不兼容的变更 Android Studio 版本。为了获得最佳的 Android 开发体验, 15 SDK,使用 Android Studio Koala 功能更新 |2024.1.2 或更高版本。
下载最新版编译器

安装 SDK

在 Android Studio 中,您可以按如下方式安装 Android 15 SDK:

  1. 点击工具 >SDK 管理器 ,然后点击 Show Package Details
  2. SDK Platforms 标签页中,展开 Android API 35 。 部分,然后选择 Android SDK Platform 35 软件包。
  3. SDK Tools 标签页中,展开 Android SDK Build-Tools 35 部分 然后选择最新的35.x.x版本。
  4. 点击 OK 安装 SDK
更新应用的 build 配置

如需访问 Android 15 API 并测试应用与 Android 15 的兼容性,请执行以下操作: 打开模块级 build.gradlebuild.gradle.kts 文件,并更新 将其替换为 Android 15 所对应的值。如何设置这些值的格式取决于 版本的 Android Gradle 插件 (AGP)

AGP 7.0.0 或更高版本

plain 复制代码
android {
    compileSdk 35
    ...
    defaultConfig {
        targetSdk 35
    }
}

下图是AGP版本所要求的Gradle、JDK、SDK Build Tools 最小版本,按需适配

2.可能存在的影响面有哪些

UI相关:主要页面状态栏是否正常和底部是否有遮挡。包括:原生页面;h5页面 ;flutter页面。(沉浸式和非沉浸式)

通知栏样式:极光推送是否通知栏样式是否正常。

存储相关:文件下载功能:版本更新功能是否正常。图库选择图片和视频是否正常。图片资源保持功能是否正常。

权限相关:机型测试权限是否有异常。

机型覆盖:安卓15 需要兼容 OPPO、VIVO、小米等。(登录官网-找云真机测试)\

对软件包停止状态的更改

软件包 FLAG_STOPPED 状态(用户可以通过长按应用图标并选择"强行停止"来参与 AOSP build)一直是为了让应用保持此状态,直到用户通过直接启动应用或间接与应用互动(通过 Sharesheet 或 widget、选择应用作为动态壁纸等)将应用从此状态明确移除。在 Android 15 中,将更新系统的行为,以符合这一预期行为。只能通过用户直接或间接操作将应用从停止状态中移除。

为了支持预期行为,除了现有限制之外,当应用在搭载 Android 15 的设备上进入停止状态时,系统还会取消所有待处理。当用户的操作将应用从停止状态中移除时,系统会向应用传递 ACTION_BOOT_COMPLETED 广播,让用户有机会重新注册任何待处理的 intent。

可以调用新的 ApplicationStartInfo.wasForceStopped() 方法来确认应用是否已置于停止状态

让部分应用支持私密空间所需的更改

私密空间是 Android 15 中的一项新功能,可让用户 在设备上创建一个单独的空间,以便将敏感应用拒之门外 增加了一层额外的身份验证。因为 由于私密空间的公开范围有限,因此某些类型的应用需要 需要完成一些额外步骤才能查看用户私有中的应用并与之互动 空间。

最低可安装TargetSDK级别为24

如果尝试安装一个针对较低API级别的应用程序会导致安装失败,并在Logcat中出现以下消息:

plain 复制代码
INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 24, but found 7

应用 STOPPED 状态的变化

当应用进入 STOPPED 状态时,系统会自动取消应用的所有 PendingIntent。这意味着任何未决的操作,包括但不限于定时任务和远程服务调用,都将被中断。

在此状态下,应用的小部件(widgets)也会被禁用,表现为灰色不可交互状态,直到应用再次启动。

用户通过直接或间接操作将应用从 STOPPED 状态唤醒时,系统会发送 ACTION_BOOT_COMPLETED 广播给应用。这允许应用重新注册其 PendingIntent 和恢复其他必要的后台活动。

应用可以通过 ApplicationStartInfo.wasForceStopped() 接口来检测自身是否曾处于 STOPPED 状态,以便采取相应的恢复措施。

PendingIntent

PendingIntent 则是对 Intent 的一种封装,它提供了在未来的某个不确定时间点执行 Intent 的能力,并且可以在不同的进程之间安全地传递。PendingIntent 主要有以下用途:

异步执行:允许在未来的某个时刻执行 Intent,即使是在应用不处于前台的情况下。

跨进程调用:可以安全地将 Intent 传递给其他应用或进程,因为 PendingIntent 保证了 Intent 的执行上下文和权限。

延迟绑定:在创建 PendingIntent 时不需要立即知道所有参数,可以在稍后的某个时间点再进行绑定和执行。

新的媒体处理前台服务类型

Android 15引入了一种新的前台服务类型,即mediaProcessing。

该系统允许一个应用的媒体处理服务在24小时内运行总共6个小时,之后系统会调用正在运行的服务的Service.onTimeout(int, int)方法(在Android 15中引入)。

要使用这种前台服务类型,需要在manifest中申明相关权限和foregroundServiceType属性:

plain 复制代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
        <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROCESSING" />
    .....
            <service
                android:name=".MyService"
                android:enabled="true"
                android:exported="true"
                android:foregroundServiceType="mediaProcessing"
                >
        </service>

    ......

Receiver 启动前台服务的限制

BOOT_COMPLETED 广播接收器启动前台服务有了新的限制,不得启动以下类型的前台服务:dataSync、camera、mediaPlayback、phoneCall、mediaProjection、microphonemicrophone(此限制自 Android 14 起生效)

如果BOOT_COMPLETED接收器尝试启动任何类型的前台服务,系统将抛出异常:ForegroundServiceStartNotAllowedException

plain 复制代码
fun onCreate(){ 
    StrictMode.setVmPolicy(VmPolicy.Builder() .detectUnsafeIntentLaunch() .build() ) 
}

IntentFilter

在 Android 15 中,系统对 Intent 的安全性和精确性进行了显著增强,主要体现在两个关键方面:

a.精确匹配 Intent-Filters:当一个应用尝试通过 Intent 启动另一个应用中的组件(如 Activity)时,发送的 Intent 必须严格符合接收组件声明的 intent-filters。这意味着,Intent 中的属性(如 category、data 和 action)必须与接收方在清单文件(AndroidManifest.xml)中定义的 intent-filters 完全匹配,才能成功启动目标组件。这一改变确保了组件只能被预期的 Intent 所激活,增强了跨应用交互的安全性。

b.强制 Intent 包含 Action:所有用于启动 Activity 或 Service 的 Intent 现在都必须包含一个明确的 action 字段。如果没有指定 action,该 Intent 将不会匹配到任何 intent-filters,从而无法启动任何组件。这一要求进一步提高了 Intent 的意图清晰度和安全性,防止了因缺少行动指令而可能引发的意外行为或安全漏洞。

Edge-to-edge 模式

Edge-to-edge模式是Android 15引入的一种布局策略,旨在使应用界面充分利用整个屏幕空间,包括状态栏和导航栏区域。在该模式下,应用界面将扩展至屏幕边缘,且无法自定义状态栏背景颜色,导航栏的背景透明度默认设为80%。

特性

默认启用:针对Android 15设备,所有targetSdkVersion为35或更高的应用将默认启用Edge-to-edge模式。

布局影响:启用该模式可能会影响应用的布局设计,需要开发者进行相应的适配工作。

限制条件:在Edge-to-edge模式下,非浮动窗口的layoutInDisplayCutoutMode属性必须设置为LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS,否则会抛出IllegalArgumentException。

API弃用:在Android 15平台上,之前用于设置系统栏颜色的API如setStatusBarColor和setNavigationBarColor将被弃用,即使调用,系统也会保持默认的沉浸式体验。

16K Page Size

Android 过去仅支持 4 KB 内存页面大小, 优化了系统内存性能,以针对 Android 设备通常具备的功能,页面大小以优化设备的性能。正在添加 支持 16 KB 页面大小的设备,可使您的应用在这些设备上运行 并有助于您的应用从相关的广告效果中获益 改进。如果不重新编译,应用可能无法在 16KB 设备上运行 在未来的 Android 版本中正式推出,CPU 运行时页面大小是全局设置,要么是 4K,要么是 16K,无法混用

  • 优点: 提升系统内存性能,缩短应用启动时间,降低功耗,加快相机启动速度等。
  • 缺点: 使用了 .so 动态库的应用需重新编译才能兼容,否则大概率崩溃。

升级 NDK 至 r27 或以上版本,并在 Application.mk 中配置

plain 复制代码
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

对于 NDK r26 及以下版本,需在 Android.mk 中添加

plain 复制代码
LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384"

升级 AGP 至 8.3 或以上版本。

在 16 KB 的环境中测试您的应用

1.设置 Android 15 SDK(上文已提到升级方案)
2.设置以下测试环境:

使用基于 16 KB 的 Android 15 系统设置 Android 模拟器 图片

  1. 基于 16 KB 的 Android 15 模拟器系统映像 Android Studio Jellyfish |2023.3.1 或更高版本。不过,为了最好 使用 Android 15 Beta 版时的体验,请下载最新的 预览版。请注意,您可以保留现有的 Android Studio 版本 因为您可以同时安装多个版本
  2. 在 Android Studio 中,依次点击 Tools > SDK Manager
  3. SDK Platforms 标签页中,选中 Show Package Details ,然后展开 Android VanillaIceCream Preview 部分,然后选择 以下模拟器系统映像,具体取决于您要创建的虚拟设备 创建:
3.启动测试设备,然后运行以下命令来验证 它使用的是 16 KB 的环境:
plain 复制代码
adb shell getconf PAGE_SIZE

该命令应返回值 16384

4.对于任何共享库,请确认共享库的ELF 细分 使用 16 KB ELF 对齐进行正确对齐。可以使用此脚本 有关此流程的帮助:
plain 复制代码
#!/bin/bash

# usage: alignment.sh path to search for *.so files

dir="$1"

RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"

matches="$(find $dir -name "*.so" -type f)"
IFS=$'\n'
for match in $matches; do
  res="$(objdump -p ${match} | grep LOAD | awk '{ print $NF }' | head -1)"
  if [[ $res =~ "2**14" ]] || [[ $res =~ "2**16" ]]; then
    echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
  else
    echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
  fi
done
a. 将脚本保存到一个文件中,例如 alignment.sh
b. 解压缩应用的 APK 文件:
plain 复制代码

unzip APK_NAME.apk -d /tmp/my_apk_out

复制代码
c. 在 /tmp/my_apk_out 中的提取文件上运行脚本 目录:
plain 复制代码

alignment.sh /tmp/my_apk_out | grep "arm64-v8a"

go 复制代码
该脚本会针对所有参数输出 `ALIGNED` 或 `UNALIGNED`, `arm64-v8a` 个共享库。
d. 如果任何 arm64-v8a 共享库为 UNALIGNED,您需要 更新这些库的包装,然后重新编译您的 应用,然后按照本部分中的步骤重新测试。
5.运行以下 zipalign命令,其中 APK_NAME 是 应用的 APK 文件
plain 复制代码
zipalign -c -P 16 -v 4 APK_NAME.apk
6. 全面测试您的应用,重点关注可能会受到 更改引用特定页面大小的代码实例。

即使您的应用是 16 KB 对齐的,如果将 会假定设备使用的是特定的页面大小。为了避免这种情况 请完成以下步骤:

  1. 移除所有引用 PAGE_SIZE的硬编码依赖项 常量或实例,它假定设备的页面 大小为 4 KB (4096)。请改用 getpagesize()sysconf(_SC_PAGESIZE)
  2. 查看是否使用了 mmap() 和其他需要页面对齐的 API 参数,并在必要时替换为替代参数。

在某些情况下,如果您的应用将 PAGE_SIZE 作为一个不方便使用的值, 与底层页面大小相关联,那么这不会导致应用中断 当在 16 KB 模式下使用时。不过,如果将该值传递给内核, 对于不带 MAP_FIXEDmmap,内核仍会使用整个页面, 会浪费一些内存因此,当大小为 16 KB 时,未定义 PAGE_SIZE。 模式在 NDK r27 及更高版本中启用。

如果您的应用以这种方式使用 PAGE_SIZE,并且从未将此值直接传递给 则不使用 PAGE_SIZE,而是创建一个具有新变量的新变量 表明相应信息已用于其他用途,并不反映真实情况 内存页。

作者:洞窝-王有为

相关推荐
断墨先生8 分钟前
uniapp—android原生插件开发(3Android真机调试)
android·uni-app
无极程序员2 小时前
PHP常量
android·ide·android studio
萌面小侠Plus3 小时前
Android笔记(三十三):封装设备性能级别判断工具——低端机还是高端机
android·性能优化·kotlin·工具类·低端机
慢慢成长的码农3 小时前
Android Profiler 内存分析
android
大风起兮云飞扬丶3 小时前
Android——多线程、线程通信、handler机制
android
L72563 小时前
Android的Handler
android
清风徐来辽3 小时前
Android HandlerThread 基础
android
HerayChen4 小时前
HbuildderX运行到手机或模拟器的Android App基座识别不到设备 mac
android·macos·智能手机
顾北川_野4 小时前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
hairenjing11234 小时前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机