Android 15(V)的功能与适配

前言:

在移动操作系统不断演进的过程中,Android 15 正携带着一系列令人兴奋的新功能和改进登场。作为全球最受欢迎的移动操作系统之一,Android 每一代的升级都在提升用户体验、增强安全性和推动设备性能方面做出了重大贡献。而 Android 15 也不例外,带来了丰富的功能革新和优化,使开发者和用户们能够更好地享受科技带来的便利。

在这篇博客中,我们将深入探讨 Android 15 的新功能和其带来的变化,并分享如何高效适配这一全新系统。无论您是开发者、技术爱好者,还是普通用户,我们都会带您了解这些变化如何影响您的日常使用和开发工作。从全新的用户界面设计,到更智能的AI功能,再到加强的隐私保护,Android 15 的每一个细节都值得我们去挖掘和体验。

一、功能和变更列表

类别类型详情
1安全性变更(以 Android 15 及更高版本为目标平台的应用)安全的后台 activity 启动
对于以 Android 15 为目标平台的应用,我们添加了进一步的更改,以防止恶意后台应用将其他应用带到前台、提升其权限和滥用用户互动
2安全性变更(以 Android 15 及更高版本为目标平台的应用)更安全的 intent
对于以 Android 15 为目标平台的应用,以特定组件为目标的 intent 必须准确匹配目标的 intent 过滤器规范,没有操作的 intent 不再匹配任何 intent 过滤器。
3安全性新功能和API适用于端到端加密的密钥管理
新增了 E2eeContactKeysManager 类,可简化 Android 应用中的端到端加密 (E2EE)。
4安全性新功能和API对内容 URI 的权限检查
Android 15 引入了一组新的 API,用于对Content URI 执行权限检查。
5畅联热享新功能和API卫星支持
Android 15 继续扩展对卫星连接的平台支持,并添加了一些界面元素,以确保在整个卫星连接环境中提供一致的用户体验。
6畅联热享新功能和API更顺畅的 NFC 体验
Android 15 正努力让感应式付款体验更加顺畅和可靠,同时继续支持 Android 强大的 NFC 应用生态系统。
7畅联热享新功能和API钱包角色
Android 15 引入了一个新的钱包角色,可让您与用户首选的钱包应用更紧密地集成。
8大屏设备和外形规格新功能和API改进了大屏幕多任务处理功能
Android 15 为用户提供了在大屏设备上以更好的方式进行多任务处理。
9大屏设备和外形规格新功能和API封面屏幕支持
您的应用可以声明一项属性,Android 15 会使用该属性让您的 Application 或 Activity 显示在支持的可翻转设备的小屏幕设备上。
10国际化新功能和APICJK 可变字体
从 Android 15 开始,中文、日语和韩语 (CJK) 语言的字体文件 NotoSansCJK 现已成为可变字体。
11国际化新功能和API字符间对齐
从 Android 15 开始,可以使用 JUSTIFICATION_MODE_INTER_CHARACTER 利用字母间距将文本两端对齐。
12国际化新功能和API自动换行配置
在 Android 15 中,应用现在可以使用 LINE_BREAK_WORD_STYLE_AUTO 选项,仅针对短文本行应用基于短语的换行符。
13国际化新功能和API新的日语 Hentaigana 字体
在 Android 15 中,默认情况下,捆绑了旧版日语平假名(称为 Hentaigana)的新字体文件。
14核心功能变更(所有应用)软件包停止状态变更
在 Android 15 中,只能通过直接或间接用户操作将应用从 FLAG_STOPPED 状态中移除。除现有限制之外,当应用在 Android 15 上进入停止状态时,系统还会取消所有待处理 intent
15核心功能变更(所有应用)支持 16 KB 页面大小
从 Android 15 开始,Android 系统支持配置为使用 16 KB 页面大小的开发设备。如果您在应用中使用原生代码,则应重新构建支持 16 KB 设备的应用,并且所有开发者都应使用 16 KB 环境测试其应用,以验证应用行为是否存在意外回归问题。
16核心功能变更(所有应用)某些应用支持私密空间的必要变更
私密空间是 Android 15 中的一项新功能,可让用户在设备上创建一个单独的空间,并通过额外的身份验证层保护敏感应用免遭窥探。由于私密空间中的应用公开范围受限,因此某些类型的应用需要执行额外的步骤,才能在用户的私密空间中查看应用并与其互动。
17核心功能变更(所有应用)最低可安装目标 API 级别
用户无法安装 targetSdkVersion 低于 24 的应用。
18核心功能变更(以 Android 15 及更高版本为目标平台的应用)新的媒体处理前台服务类型
Android 15 引入了新的前台服务类型 mediaProcessing。此服务类型适用于对媒体文件进行转码等操作。
19核心功能变更(以 Android 15 及更高版本为目标平台的应用)对启动前台服务的 BOOT_COMPLETED 广播接收器的限制
对于以 Android 15 为目标平台的应用,BOOT_COMPLETED 接收器不得启动某些类型的前台服务。
20核心功能变更(以 Android 15 及更高版本为目标平台的应用)有关应用何时可以修改“勿扰”模式全局状态的变更
以 Android 15 为目标平台的应用无法再更改设备的全局状态或勿扰 (DND) 政策(通过修改用户设置或关闭 DND 模式)。
21核心功能变更(以 Android 15 及更高版本为目标平台的应用)OpenJDK 17 变更
在 OpenJDK 17 更新中,一些变更可能会影响应用兼容性,例如对某些字符串格式 API、语言代码处理和随机 int 序列的更改。
22开发者工作效率和工具新功能和 APIOpenJDK 17 更新
Android 15 会继续更新 Android 的核心库,以与最新 OpenJDK LTS 版本中的功能保持一致。
23开发者工作效率和工具新功能和 APIPDF 改进
Android 15 开发者预览版 2 包含对 PdfRenderer API 的重大改进的早期预览版。
24开发者工作效率和工具新功能和 API自动语言切换优化
Android 15 添加了额外的控件,以帮助应用根据其用例调整自动语言切换功能。
25开发者工作效率和工具新功能和 API改进了 OpenType Variable Font API
Android 15 提高了 OpenType 变量字体的易用性。
26开发者工作效率和工具新功能和 API细化的换行符控件
从 Android 15 开始,TextView 和底层换行符可以将文本的给定部分保留在同一行中,以提高可读性。
27开发者工作效率和工具新功能和 API应用归档
Android 15 现在包含对应用归档和取消归档的操作系统级支持,因此所有应用商店都可以更轻松地实现此功能。
28摄像头和媒体变更(所有应用)在达到资源限制时,直接和分流音频播放会使之前打开的直接或分流音轨失效
从 Android 15 开始,当应用请求直接播放时,系统会使当前打开的所有直接 AudioTrack 对象失效,这会阻止执行新的音轨请求。
29摄像头和媒体变更(以 Android 15 及更高版本为目标平台的应用)对请求音频焦点的限制
以 Android 15 为目标平台的应用必须是最靠前的应用或运行与音频相关的前台服务,才能请求音频焦点。
30摄像头和媒体不推荐使用使用空间化程序代替虚拟化器
在 Android 15 中,我们废弃了 Virtualizer 类。
31摄像头和媒体新功能和 API弱光增强
Android 15 引入了“弱光提升”,这是一种新的自动曝光模式,可供相机 2夜间模式相机扩展使用。
32摄像头和媒体新功能和 API应用内相机控件
Android 15 添加了新的扩展,以便在受支持的设备上更好地控制相机硬件及其算法。
33摄像头和媒体新功能和 APIHDR 余量控制
在 Android 15 中,您可以使用 setDesiredHdrHeadroom 控制 HDR 余量,以便在 SDR 和 HDR 内容之间取得平衡。
34摄像头和媒体新功能和 API音量控制
Android 15 根据 CTA-2075 音量标准引入了 LoudnessCodecController API。此 API 可帮助您管理音量不一致性,确保用户在内容或应用之间切换时无需不断调整音量。
35摄像头和媒体新功能和 API虚拟 MIDI 2.0 设备
Android 15 扩展了对虚拟 MIDI 应用的 UMP 支持,让合成器应用能够像对待 USB MIDI 2.0 设备一样将合成器应用作为虚拟 MIDI 2.0 设备进行控制。
36摄像头和媒体新功能和 API更高效的 AV1 软件解码
VideoLAN 中的热门 AV1 软件解码器 dav1d 现已可用于在硬件中不支持 AV1 解码的 Android 设备。
37图形新功能和 API对 Android 的 GPU 访问进行现代化改造
Android 15 包含 ANGLE,作为在 Vulkan 上运行 OpenGL® ES 的可选层;ANGLE 已作为一些新设备上的 GL 系统驱动程序提供,新的 Android 设备将改为仅通过 ANGLE 支持 OpenGL。
38图形新功能和 API改进了 Canvas
Android 15 通过新功能继续对 Android 的 Canvas 图形系统进行了现代化改造。
39无障碍功能新功能和 API改进盲文功能
在 Android 15 中,TalkBack 可以支持通过 USB 和安全蓝牙使用 HID 标准的盲文显示屏。
40限制非SDK接口变更(以 Android 15 及更高版本为目标平台的应用)更新了非 SDK 接口限制
Android 15 包含更新后的受限制非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。
41性能和电池新功能和 APIApplicationStartInfo API
Android 15 上的 ApplicationStartInfo API 有助于深入了解应用启动,包括启动状态、在启动阶段花费的时间、在 Application 类实例化时应用的启动方式等。
42性能和电池新功能和 API详细的应用大小信息
Android 15 增加了 StorageStats.getAppBytesByDataType([type]) API,可让您深入了解应用如何使用所有空间,包括 APK 文件拆分、AOT 和加速相关代码、dex 元数据、库和引导式配置文件。
43性能和电池新功能和 API应用管理的性能剖析
Android 15 包含全新的 ProfilingManager 类,可让您从应用中收集性能剖析信息。
44性能和电池新功能和 APISQLite 数据库改进
Android 15 引入了新的 SQLite API,提供底层 SQLite 引擎的高级功能,这些功能旨在解决应用中可能表现出的具体性能问题。
45性能和电池新功能和 APIAndroid 动态性能框架更新
Android 15 继续投资开发 Android 动态性能框架 (ADPF)。ADPF 是一组 API,可让游戏和性能密集型应用更直接地与 Android 设备的电源和散热系统进行互动。
46隐私权新功能和 API屏幕录制检测
Android 15 增加了对应用的支持,以便检测是否正在录制应用。
47隐私权新功能和 API扩展了 IntentFilter 功能
Android 15 build 支持通过 UriRelativeFilterGroup 进行更精确的 Intent 解析,其中包含一组 UriRelativeFilter 对象,这些对象构成了一组必须满足的 Intent 匹配规则,其中包括网址查询参数、网址片段以及屏蔽或排除规则。
48隐私权新功能和 API私密空间
私密空间可让用户在设备上创建一个单独的空间,并通过额外的身份验证机制来防止敏感应用被窥探。私密空间中的应用会显示在启动器中的单独容器中;当私密空间处于锁定状态时,私密空间中的应用不会出现在“最近使用的应用”视图、通知、设置和其他应用中。
49隐私权新功能和 API查询所选照片访问权限的最近用户选择
现在,授予媒体访问权限的部分访问权限后,应用可以仅突出显示最近选择的照片和视频。
50隐私权新功能和 APIPrivacy Sandbox on Android
Android 15 包含最新的 Android 广告服务扩展程序,以及最新版本的 Privacy Sandbox on Android。我们致力于开发新技术,以便更好地保护用户隐私,并为移动应用打造高效的个性化广告体验。
51隐私权新功能和 APIHealth Connect
Android 15 集成了 Health Connect by Android 的最新扩展程序,Health Connect by Android 是一个安全的集中式平台,用于管理和分享应用收集的健康与健身数据。本次更新增加了对健身、营养、体表温度、训练计划等新数据类型的支持。
52隐私权新功能和 API局部屏幕共享
Android 15 支持部分屏幕共享,因此用户可以仅共享或录制应用窗口,而不是整个设备屏幕。此功能在 Android 14 QPR2 中首次启用,包含 MediaProjection 回调,可让您的应用自定义局部屏幕共享体验。
53用户体验和系统界面变更(所有应用)为已选择启用的应用启用预测性返回动画
移除了预测性返回动画的开发者选项。现在,对于完全或在 activity 级别选择启用预测性返回手势的应用,系统会显示“返回主屏幕”“跨任务”和“跨 activity”等系统动画。
54用户体验和系统界面变更(以 Android 15 及更高版本为目标平台的应用)无边框强制执行
对于以 Android 15 为目标平台的应用,我们添加了一些与无边框相关变更。如果应用的界面元素靠近屏幕顶部或底部,并且不处理边衬区,那么应用的用户体验可能会受到这些变化的负面影响。
55用户体验和系统界面变更(以 Android 15 及更高版本为目标平台的应用)稳定的配置
如果应用以 Android 15 或更高版本为目标平台,Configuration 不再排除系统栏。
56用户体验和系统界面变更(以 Android 15 及更高版本为目标平台的应用)legateTextHeight 属性默认为 true
对于以 Android 15 为目标平台的应用,elegantTextHeight TextView 属性默认变为 true,将默认使用的紧凑字体替换为一些具有较大垂直指标的脚本,这些脚本更易于阅读。
57用户体验和系统界面变更(以 Android 15 及更高版本为目标平台的应用)针对复杂字母形状的 TextView 宽度变化
在以前的 Android 版本中,一些形状复杂的草体字体或语言可能会在上一个或下一个字符区域中绘制字母。在某些情况下,此类字母会在开始或结束位置被截断。从 Android 15 开始,TextView 会分配宽度来为此类字母绘制足够的空间,并允许应用请求左侧添加额外的内边距以防止被裁剪。
58用户体验和系统界面变更(以 Android 15 及更高版本为目标平台的应用)EditText 的语言区域感知默认行高
对于以 Android 15 为目标平台的应用,系统现在会为 EditText 预留最小行高,以与指定语言区域的参考字体匹配。
59用户体验和系统界面新功能和 API使用 Generated Previews API 提供更丰富的 widget 预览
从 Android 15 开始,我们将添加对生成的预览的支持。这意味着,应用 widget 提供程序可以生成 RemoteViews(而不是静态资源)用作选择器预览。
60用户体验和系统界面新功能和 API画中画
从 Android 15 开始,现在,只要画中画动画开始播放,就会触发 Activity#onPictureInPictureUiStateChanged 回调。
61用户体验和系统界面新功能和 API改进了“勿扰”规则
AutomaticZenRule 允许应用自定义注意力管理(勿扰)规则,并决定何时启用或停用这些规则。Android 15 大幅增强了这些规则,以改善用户体验。
62用户体验和系统界面新功能和 API为通知渠道设置振动效果
Android 15 支持按渠道为传入的通知设置丰富的振动。

二、重点功能变更介绍

1.限制侧载应用获取敏感权限

安卓 15 Beta 1.1 更新,在代码中发现了“增强确认模式”(Enhanced Confirmation Mode),进一步限制侧载应用的敏感权限。
在这里插入图片描述在这里插入图片描述
“增强确认模式”(ECM)对话框和现有的“受限设置”(Restricted Settings)类似,通过侧载方式安装的应用程序如果想要启用辅助功能或者通知侦听器服务时,ECM 对话框会显示:“为了您的安全,此设置当前不可用”。
安卓 15 系统中“增强确认模式”和安卓 13 系统中引入的“受限设置”的关键区别在于执行方式。安卓 15 系统中“增强确认模式”并不是根据使用的安装 API 方式区分,而是通过检查工厂镜像中预加载的白名单区分。此白名单是位于 安卓 15 的 /system/ etc / sysconfig 路径中的 XML 文件,它确定哪些软件包和安装程序不受任何限制,而没有在该白名单上的应用程序会默认阻止其运行。
XML 文件中明确列入允许列表的任何包都被视为“受信任的包”,并且不受 ECM 限制。同样,XML 文件中列出的任何安装程序都被视为“受信任的安装程序”,这意味着它们随后安装的应用程序有资格免受 ECM 限制。由“可信安装程序”安装的应用程序如果被标记为来自“可信”软件包源(即未标记为 PACKAGE_SOURCE_DOWNLOADED_FILE 或 PACKAGE_SOURCE_LOCAL_FILE ),则不受 ECM 限制。用户尝试启用应用程序的辅助功能或通知侦听器服务,并且该应用程序来自不受信任的安装程序或不受信任的来源,则他们将被迫看到“增强确认模式”对话框。这种方式有效弥补安卓 13“受限设置”功能中存在的漏洞,使恶意第三方应用程序更难获得高特权权限。

2.前台服务变化

Android 15 对于以 Android 15 或更高版本为目标平台的应用,在 dataSync 中引入了新的超时行为。此行为也适用于新的mediaProcessing 前台服务类型
系统允许应用的 dataSync 服务在 24 小时内运行总共 6 小时,之后系统会调用正在运行的服务的 Service.onTimeout(int, int) 方法(在 Android 15 中引入)。此时,服务只有几秒钟的时间来调用 Service.stopSelf()。当调用 Service.onTimeout() 时,该服务不再被视为前台服务。如果服务未调用 Service.stopSelf(),则会发生故障,并显示以下错误消息:“A for 前台服务 (<fgs_type> does not stop in their timeout: <component_name>)”。在 Beta 版 2 中,失败消息显示为 ANR,但在未来的 Beta 版中,此失败消息将抛出自定义异常。
注意 :6 小时的时间限制由应用的所有 dataSync 前台服务共享。例如,如果某个应用运行了一项 dataSync 服务 4 小时,然后启动了另一项 dataSync 服务,则第二项服务只能运行 2 小时。不过,如果用户将应用调到前台,计时器会重置,并且应用有 6 小时的剩余时间。
为避免此行为变更出现问题,您可以执行以下一项或多项操作:

  1. 让您的服务实现新的 Service.onTimeout(int, int) 方法。当应用收到回调时,请确保在几秒钟内调用 stopSelf()。(如果您没有立即停止应用,系统会生成故障。)
  2. 确保应用的 dataSync 服务在任何 24 小时内的运行时间总共不超过 6 小时(除非用户与应用互动,请重置计时器)。
  3. 仅因直接用户互动而启动 dataSync 前台服务;由于您的应用在服务启动时正处于前台,因此在它进入后台后,您的服务有整整六个小时的时间。
  4. 请使用替代 API,而不要使用 dataSync 前台服务。

如果应用的 dataSync 前台服务在过去 24 小时内运行了 6 小时,那么除非用户已将您的应用带到前台(这会重置计时器),否则您无法启动其他 dataSync 前台服务。如果您尝试启动另一个 dataSync 前台服务,系统会抛出ForegroundServiceStartNotAllowedException,并显示“时间限制已用完前台服务类型 dataSync 的时间限制”这样的错误消息。

3.支持 16 KB 页面

Android 15 增加了对使用较大页面大小的设备的支持,除了标准 4 KB 页面之外,还支持 16 KB 页面,如果你的应用直接或通过 SDK 间接使用任何 NDK 库,那么可能需要重构应用才可以在 16 KB 页面大小的设备上运行
PS:页面大小指的是虚拟内存中的页面(也称为页)的大小,通常是 2 的整数次幂,比如2KB、4KB、8KB等
配置有 16KB 页面大小的设备,对于 App 的启动性能有着不错的提升 ,并且在明年 Google Play 也将支持应用上传到 Play 商店时支持 16 KB 页面兼容性

4.Android 的 GPU 访问

从 Android 7.0(API 级别 24)以来,Vulkan API 已经在 NDK 里提供,使用 Vulkan API 可以更好接触到 GPU 的底层能力。
Vulkan 现在是 Android 的首选 GPU 接口,而 Android 15 将 ANGLE 作为可选层,用于在 Vulkan 之上运行 OpenGL ES,转向 ANGLE 将使 Android OpenGL 实现标准化以提高兼容性,并在某些情况下可以提高性能。
对于开发者,可以使用 Android 15 中的 “开发者选项 → Experimental: Enable ANGL” 设置来测试 OpenGL ES 应用的稳定性和性能。
在这里插入图片描述
作为简化 GPU 堆栈的一部分,今后将会在更多新设备上将 ANGLE 作为 GL 系统的驱动程序,未来预计 OpenGL/ES 将仅通过 ANGLE 提供。

5.现代图形

Android 15 继续对 Android Canvas 图形系统进行新的改造:

  • Matrix44 提供了一个 4x4 矩阵用于转换坐标,当开发者想要以 3D 方式操作画布时可以使用该矩阵。
  • ClipShader 将当前剪辑与指定着色器相交,而 clipOutShader 将剪辑设置为当前剪辑与着色器的差值,将每个着色器视为 alpha 遮罩,这个支持可以有效地绘制复杂形状。
  • Android U开始,View的onDraw方法Canvas参数已经被声明成不可空的。
protected void onDraw(@NonNull Canvas canvas)

6.AV1软件解码

dav1d 是 VideoLAN 的 AV1 软件解码器,现在可以用于不支持 AV1 硬件解码的 Android 设备,它的性能比传统 AV1 软件解码器高出 3 倍,可为更多用户(包括一些中低端设备)提供高清 AV1 播放。
目前应用需要通过 “c2.android.av1-dav1d.decoder ” 调用来选择使用 dav1d ,在后续更新中dav1d将成为默认的 AV1 软件解码器,另外这个支持已标准化并向后移植到接收 Google Play 系统更新的 Android 11 设备。

7.照片选择改进

当 App 得到部分媒体权限时,应用可以仅突出显示最近选择的照片和视频,这可以改善频繁请求访问照片和视频的用户体验,详细可以通过 ContentResolver 在 MediaStore 启用时查询 QUERY_ARG_LATEST_SELECTION_ONLY 参数来实现。

val externalContentUri = MediaStore.Files.getContentUri("external")

val mediaColumns = arrayOf(
   FileColumns._ID,
   FileColumns.DISPLAY_NAME,
   FileColumns.MIME_TYPE,
)

val queryArgs = bundleOf(
   // Return only items from the last selection (selected photos access)
   QUERY_ARG_LATEST_SELECTION_ONLY to true,
   // Sort returned items chronologically based on when they were added to the device's storage
   QUERY_ARG_SQL_SORT_ORDER to "${FileColumns.DATE_ADDED} DESC",
   QUERY_ARG_SQL_SELECTION to "${FileColumns.MEDIA_TYPE} = ? OR ${FileColumns.MEDIA_TYPE} = ?",
   QUERY_ARG_SQL_SELECTION_ARGS to arrayOf(
       FileColumns.MEDIA_TYPE_IMAGE.toString(),
       FileColumns.MEDIA_TYPE_VIDEO.toString()
   )
)

val cursor = contentResolver.query(externalContentUri, mediaColumns, queryArgs, null)

8.对 content URI 的权限检查

Android 15 引入了一组新的 API,用于对 content URI 执行权限检查:

  • Context.checkContentUriPermissionFull :它对内容 URI 执行完整的权限检查。
private boolean checkContentUriPermissionFullUnlocked(GrantUri grantUri, int uid,
        int modeFlags) {
    if (uid < 0) {
        throw new IllegalArgumentException("Uid must be positive for the content URI "
                + "permission check of " + grantUri.uri.toSafeString());
    }

    if (!isContentUriWithAccessModeFlags(grantUri, modeFlags,
            /* logAction */ "check content URI permission")) {
        throw new IllegalArgumentException("The URI must be a content URI and the mode "
                + "flags must be at least read and/or write for the content URI permission "
                + "check of " + grantUri.uri.toSafeString());
    }

    final int appId = UserHandle.getAppId(uid);
    if ((appId == SYSTEM_UID) || (appId == ROOT_UID)) {
        return true;
    }

    // Retrieve the URI's content provider
    final String authority = grantUri.uri.getAuthority();
    ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId, MATCH_DIRECT_BOOT_AUTO,
            uid);

    if (pi == null) {
        Slog.w(TAG, "No content provider found for content URI permission check: "
                + grantUri.uri.toSafeString());
        return false;
    }

    // Check if it has general permission to the URI's content provider
    if (checkHoldingPermissionsUnlocked(pi, grantUri, uid, modeFlags)) {
        return true;
    }

    // Check if it has explicitly granted permissions to the URI
    synchronized (mLock) {
        return checkUriPermissionLocked(grantUri, uid, modeFlags);
    }
}
  • Activity manifest attribute requireContentUriPermissionFromCaller:它在 activity 启动时对提供的 content URI 强制执行指定的权限。
  • Activity 调用者的 ComponentCaller :它代表启动该 Activity 的应用。

9.安全的后台 activity 启动

从 Android 10 起后台 activity 启动就受到限制,而 Android 15 通过添加其他控制,来防止恶意后台应用将其他应用带到前台。
在此之前,同一任务中的恶意应用可以启动另一个应用的 activity ,然后将自己叠加在上面,从而造成是该应用的错觉,这种“任务劫持”(task hijacking) 攻击绕过了当前的后台启动限制,因为它全部发生在同一个可见 task 中,为了减轻这种风险, Android 15 添加了一个标志,阻止与堆栈上顶部 UID 不匹配的应用启动 activity。
可以通过在 AndroidManifest.xml 文件中配置 allowCrossUidActivitySwitchFromBelow 属性,指定任务的 activity 是否可以启动其他 activity 或结束 task :

<application android:allowCrossUidActivitySwitchFromBelow="false" >

一旦应用全局配置了新的保护模式,一些特殊的 activity 也使用下面这个 API 来选择退出:

public void onCreate(Bundle bundle) {
  super.onCreate(bundle);
  setAllowCrossUidActivitySwitchFromBelow(true);
  ...
}

10.更安全的 Intents

Android 15 引入了新的安全措施,使 intents 更安全和强大,这些更改旨在防止恶意应用利用潜在的漏洞,Android 15 中对 Intent 安全性的主要改进有两个:

  • 匹配目标 intent-filters:针对特定组件的 intent 必须准确匹配目标的 intent-filters 规范,如果发送 intent 来启动另一个应用的 activity ,则目标 intent 组件需要与接收 activity 声明的 intent-filters 保持一致。
  • intent 必须有 action:没有 action 的 intent 将不再匹配任何 intent-filters ,这意味着用于启动 activity 或 service 的 intent 必须具有明确定义的 action。

11.将最低 target SDK 版本从 23 增加到 24

Android 15 将安装应用所需的最低 targetSdkVersion 从 23 增加到 24,如果尝试安装 target API 级别低于 24 的应用,会在 Logcat 中看到错误:INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 24, but found 7.

12.改进大屏幕多任务处理

Android 15 beta 2 为用户提供了在大屏幕设备上处理多任务的更好方法,例如用户可以将任务栏固定在屏幕上,然后在应用之间快速切换,当然,这也代表了你的 App 需要具不同的屏幕适应能力。
在这里插入图片描述

13.Window Insets

除了边缘到边缘的强制执行外,当针对Android 15配置中的SDK 35+时。screenWidthDp和screenHeightDp,现在包括系统条的深度。虽然这些值仍然可以用于资源选择(例如res/layout-h500dp),但不鼓励将它们用于布局计算。

14.画中画

Android 15 引入了画中画 (PiP) 的新变化,确保进入 PiP 模式时的过渡更加平滑,这对于 UI 元素覆盖在其主 UI 之上(进入画中画)的应用可以看到对应的效果。
目前 onPictureInPictureModeChanged 用于定义切换重叠 UI 元素的可见性的逻辑,当画中画进入或退出动画完成时会触发此回调。
从 Android 15 开始,我们在 PictureInPictureUiState 类中引入了一个新状态,一旦 PiP enter animation 开始,并且应用可以隐藏覆盖的 UI 元素, 就会使用 isTransitioningToPip() 调用 onPictureInPictureUiStateChanged 回调。

override fun onPictureInPictureUiStateChanged(pipState: PictureInPictureUiState) {
    if (pipState.isTransitioningToPip()) {
       // Hide UI elements        }
    }

override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
    if (isInPictureInPictureMode) {
       // Unhide UI elements        }
    }

这种 UI 不相关(对于画中画窗口)的快速可见能力,可以让画中画动画切换更平滑且不闪烁。

15.通过生成的预览提供更丰富的 Widget 预览

通过显示个性化预览让 Widget 脱颖而出,针对 Android 15 的应用可以向 Widget Picker 提供 Remote Views,从而让它们可以更新 picker 中的内容,让用户将看到他们更想看到的内容。
应用可以使用 AppWidgetManager setWidgetPreview、getWidgetPreview和 removeWidgetPreview 方法来使用最新的个性化信息更新 Widget 的外观。
在这里插入图片描述

16.Predictive Back

Predictive back 在使用手势导航的同时提供了更流畅、更直观的导航体验,利用内置动画告知用户他们的操作将把他们带到哪里,以减少意外结果。
在 Android 15 中,Predictive Back 将不再是开发者选项,对于已正确迁移的应用,将出现返回主页、跨任务和跨活动等系统动画。
在这里插入图片描述

17.为通知通道设置 VibrationEffect

Android 15 beta 2 现在支持使用 NotificationChannel.setVibrationEffect ,按通道为传入通知设置丰富的振动,这样用户就无需查看设备即可区分不同类型的通知。

18.CJK 可变字体

从 Android 15 开始,中文、日文和韩文的字体文件 NotoSansCJK 会是可变字体,可变字体为 CJK 语言的创意排版开辟了新的可能性。
在这里插入图片描述

19.避免剪切文本

某些具有复杂形状的草书字体或语言字符可能会在上一个或下一个字符的区域中绘制字母,这些字母可能会在开始或结束位置被剪裁,从 Android 15 开始,TextView 为此类字母分配额外的宽度,并在左侧添加额外的填充。
由于这会改变 TextView 决定宽度的方式,因此如果应用面向 Android 15 或更高版本,则默认情况下 TextView 会分配更多宽度,可以通过在 TextView 上调用 setUseBoundsForWidth API来启用或禁用它。
由于添加左内边距可能会导致现有布局错位,因此即使面向 Android 15 或更高版本,默认情况下也不会添加内边距。
要添加额外的填充以防止剪切,请调用 setShiftDrawingOffsetForStartOverhang。

<TextView
    android:fontFamily="cursive"
    android:text="java" />

在这里插入图片描述

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />

在这里插入图片描述
参考原文:https://android-developers.googleblog.com/2024/05/the-second-beta-of-android-15.html

20.文件完整性

Android 15 的 FileIntegrityManager 包含新的 API,可利用 Linux 内核中 fs-verity 功能的强大功能。借助 fs-verity,文件可以通过自定义加密签名进行保护,帮助您确保它们没有被篡改或损坏。这可以增强安全性,防止潜在的恶意软件或未经授权的文件修改,从而损害您的应用程序的功能或数据。
FileIntegrityManager的API可参考:https://developer.android.com/reference/android/security/FileIntegrityManager

21.通知冷却

“通知冷却”功能默认开启,用户可以选择将其应用于所有通知或仅限于对话通知。对于经常被热闹的群聊消息轰炸的用户来说,这项功能无疑是非常实用的。
具体来说,当同一应用或对话首次发送通知时,手机声音音量仍会保持正常,但随后来自同一来源的后续通知音量将会逐渐降低。值得注意的是,这些重复通知并不会完全静音,而是通过音量变化提醒用户它们来自同一来源。这意味着,即使你选择忽略一个通知,当新的通知到来时,你也能通过声音区分。
需要注意的是,“通知冷却”功能存在一个未知的冷却计时器,将在一段时间后重置。一旦重置,即使来自先前通知的同一应用或对话,新通知也会以全音量发出,目前无法自定义冷却计时器。
谷歌官方对“通知冷却”的描述是,“当您收到来自同一应用的许多连续通知时,会逐渐降低通知音量”。“通知冷却”功能的加入无疑将为 Android 15 带来越来越人性化的体验.

22.Android Manaifest TAG限制

Android 15 对AndroidManifest Tag数量/attr 长度/属性值限制特殊字符做了先关的限制。

  • 限制AndroidManifest.xml字段的tag数量,具体规则如下图。(解释示例:如在Application 下只能有不超过3000个的Activity)
private void init(String tag) {
    this.mTag = tag;
    mChildTagMask = 0;
    mTotalComponentMetadataSize = 0;
    switch (tag) {
        case TAG_ACTIVITY:
            initializeCounter(TAG_LAYOUT, 1000);
            initializeCounter(TAG_META_DATA, 1000);
            initializeCounter(TAG_INTENT_FILTER, 20000);
            break;
        case TAG_ACTIVITY_ALIAS:
        case TAG_RECEIVER:
        case TAG_SERVICE:
            initializeCounter(TAG_META_DATA, 1000);
            initializeCounter(TAG_INTENT_FILTER, 20000);
            break;
        case TAG_APPLICATION:
            initializeCounter(TAG_PROFILEABLE, 100);
            initializeCounter(TAG_USES_NATIVE_LIBRARY, 100);
            initializeCounter(TAG_RECEIVER, 1000);
            initializeCounter(TAG_SERVICE, 1000);
            initializeCounter(TAG_META_DATA, 1000);
            initializeCounter(TAG_USES_LIBRARY, 1000);
            initializeCounter(TAG_ACTIVITY_ALIAS, 4000);
            initializeCounter(TAG_PROVIDER, 8000);
            initializeCounter(TAG_ACTIVITY, 30000);
            break;
        case TAG_COMPATIBLE_SCREENS:
            initializeCounter(TAG_SCREEN, 4000);
            break;
        case TAG_INTENT:
        case TAG_INTENT_FILTER:
            initializeCounter(TAG_URI_RELATIVE_FILTER_GROUP, 100);
            initializeCounter(TAG_ACTION, 20000);
            initializeCounter(TAG_CATEGORY, 40000);
            initializeCounter(TAG_DATA, 40000);
            break;
        case TAG_MANIFEST:
            initializeCounter(TAG_APPLICATION, 100);
            initializeCounter(TAG_OVERLAY, 100);
            initializeCounter(TAG_INSTRUMENTATION, 100);
            initializeCounter(TAG_PERMISSION_GROUP, 100);
            initializeCounter(TAG_PERMISSION_TREE, 100);
            initializeCounter(TAG_SUPPORTS_GL_TEXTURE, 100);
            initializeCounter(TAG_SUPPORTS_SCREENS, 100);
            initializeCounter(TAG_USES_CONFIGURATION, 100);
            initializeCounter(TAG_USES_SDK, 100);
            initializeCounter(TAG_COMPATIBLE_SCREENS, 200);
            initializeCounter(TAG_QUERIES, 200);
            initializeCounter(TAG_ATTRIBUTION, 400);
            initializeCounter(TAG_USES_FEATURE, 400);
            initializeCounter(TAG_PERMISSION, 2000);
            initializeCounter(TAG_USES_PERMISSION, 20000);
            break;
        case TAG_PROVIDER:
            initializeCounter(TAG_GRANT_URI_PERMISSION, 100);
            initializeCounter(TAG_PATH_PERMISSION, 100);
            initializeCounter(TAG_META_DATA, 1000);
            initializeCounter(TAG_INTENT_FILTER, 20000);
            break;
        case TAG_QUERIES:
            initializeCounter(TAG_PACKAGE, 1000);
            initializeCounter(TAG_INTENT, 2000);
            initializeCounter(TAG_PROVIDER, 8000);
            break;
        case TAG_URI_RELATIVE_FILTER_GROUP:
            initializeCounter(TAG_DATA, 100);
            break;
    }
}
  • 限制attr string的长度
private static final int MAX_ATTR_LEN_URL_COMPONENT = 256;
private static final int MAX_ATTR_LEN_PERMISSION_GROUP = 256;
private static final int MAX_ATTR_LEN_PACKAGE = 256;
private static final int MAX_ATTR_LEN_MIMETYPE = 255;
private static final int MAX_ATTR_LEN_NAME = 1024;
private static final int MAX_ATTR_LEN_PATH = 4000;
private static final int MAX_ATTR_LEN_VALUE = 32_768;
  • 对于attr属性值限制特殊字符
private static final String BAD_COMPONENT_NAME_CHARS = ";,[](){}:?%^*|/\\";
  • 校验应用包名是否合法,包名只能包含如下字符:a-z, A-Z, 0-9,“.”和"_"

23.启动前台服务的限制

target sdK 35+ 应用,BOOT_COMPLETED对广播接收方启动前台服务有新的限制,接收方不允许启动以下类型的前台服务:

  • dataSync
  • Camera
  • mediaPlayback
  • phoneCall
  • mediaProjection
  • microphone microphone(此限制自 Android 14 起生效)
    如果BOOT_COMPLETED接收者尝试启动任何这些类型的前台服务,系统将抛出ForegroundServiceStartNotAllowedException。

24.应用已停止状态变更

当应用在 Android 15 上进入停止状态时,系统还会取消所有待处理 intent。当用户的操作将应用从停止状态中移除时,系统将向应用传递 ACTION_BOOT_COMPLETED /LOCKED_BOOT_COMPLETED广播,使用户有机会重新注册任何待处理的intent

  • 取消所有待处理 intent:系统在应用forceStop 时 会清除mIntentSenderRecords里的pendingintent.影响设置FLAG为FLAG_NO_CREATE的PendingIntent。
  • 应用从停止状态中移除时,系统将向应用传递 ACTION_BOOT_COMPLETED /LOCKED_BOOT_COMPLETED广播。

25.Jobscheduler检查

规范三方应用对Job的使用,应用在设置Job的时候,如果最早触发时间和最晚触发时间相距小于15min,则会直接触发exception导致应用崩溃(目前是关闭状态,只会打印出log)。

private static final long MIN_PERIOD_MILLIS = 15 * 60 * 1000L;   // 15 minutes
private static final long MIN_ALLOWED_TIME_WINDOW_MILLIS = MIN_PERIOD_MILLIS;

if (maxExecutionDelayMillis - windowStart < MIN_ALLOWED_TIME_WINDOW_MILLIS) {
    if (enforceMinimumTimeWindows
            && Flags.enforceMinimumTimeWindows()) {
        throw new IllegalArgumentException("Time window too short. Constraints"
                + " unlikely to be satisfied. Increase deadline to a reasonable"
                + " duration."
                + " Job '" + service.flattenToShortString() + "#" + jobId + "'"
                + " has delay=" + windowStart
                + ", deadline=" + maxExecutionDelayMillis);
    } else {
        Log.w(TAG, "Job '" + service.flattenToShortString() + "#" + jobId + "'"
                + " has a deadline with functional constraints and an extremely"
                + " short time window of "
                + (maxExecutionDelayMillis - windowStart) + " ms"
                + " (delay=" + windowStart
                + ", deadline=" + maxExecutionDelayMillis + ")."
                + " The functional constraints are not likely to be satisfied when"
                + " the job runs.");
    }
}

26.细化的换行符控件

从 Android 15 开始,TextView 和底层换行符可以将文本的给定部分保留在同一行中,以提高可读性。您可以通过在字符串资源或 createNoBreakSpan 中使用 标记来利用此换行符自定义功能。同样,您可以使用 标记或 createNoHyphenationSpan 避免断字的情况。
例如,以下字符串资源不包含换行符,而是在不希望的位置显示文本“Pixel 8 Pro”进行渲染:

<resources>
    <string name="pixel8pro">The power and brains behind Pixel 8 Pro.</string>
</resources>

相比之下,此字符串资源包含 标记,该标记会封装短语“Pixel 8 Pro.”并防止换行符:

<resources>
    <string name="pixel8pro">The power and brains behind <nobreak>Pixel 8 Pro.</nobreak></string>
</resources>

这些字符串的呈现方式差异如下图所示:
用于设置一行文本的布局,其中词组“Pixel 8 Pro”未使用 标记进行换行:
在这里插入图片描述
同一行文本的布局,其中词组“Pixel 8 Pro”用 标记封装:
在这里插入图片描述

27.应用归档

Android 和 Google Play 去年宣布支持应用归档,这让用户可以通过从 Google Play 上使用 Android App Bundle 发布的部分不常用的应用来释放空间。Android 15 现在包含对应用归档和取消归档的操作系统级支持,因此所有应用商店都可以更轻松地实现此功能。
具有 REQUEST_DELETE_PACKAGES 权限的应用可以调用 PackageInstaller requestArchive 方法来请求归档已安装的应用软件包,此操作会移除 APK 和所有缓存的文件,但会保留用户数据。已归档的应用会通过 LauncherApps API 作为可显示的应用返回;用户会看到界面处理方式,以突出显示这些应用已归档。如果用户点按已归档的应用,相关安装程序将收到将其取消归档的请求,并且可以通过 ACTION_PACKAGE_ADDED 广播监控恢复过程。

28.ApplicationStartInfo API

在以前的 Android 版本中,应用启动有点神秘。在应用中确定应用是从冷状态、温状态还是热状态开始的过程很难确定。此外,我们也很难知道您的应用在不同发布阶段所用的时间:创建进程分支、调用 onCreate、绘制第一帧等。在实例化 Application 类时,您无法得知应用是从广播、content provider、作业、备份、启动完成、闹钟还是 Activity 启动的。

Android 15 上的 ApplicationStartInfo API 可提供所有这些功能以及更多其他功能。您甚至可以选择将自己的时间戳添加到流程中,以便在一个位置收集时间数据。除了收集指标之外,您还可以使用 ApplicationStartInfo 直接优化应用启动;例如,当应用因广播而启动时,您可以避免在 Application 类中实例化界面相关库的高成本。

private @StartupState int mStartupState;
private int mPid;
private int mRealUid;
private int mPackageUid;
private int mDefiningUid;
private String mPackageName;
private String mProcessName;
private @StartReason int mReason;
private ArrayMap<Integer, Long> mStartupTimestampsNs;
private @StartType int mStartType;
private Intent mStartIntent;
private @LaunchMode int mLaunchMode;
private boolean mWasForceStopped;

29.屏幕录制检测

Android 15 增加了对应用检测功能的支持,以检测其是否被录制。每当应用在屏幕录制中处于可见或不可见状态之间转换时,系统都会调用回调。如果系统正在记录注册进程的 UID 拥有的 activity,则应用会被视为可见。这样,如果您的应用正在执行敏感操作,您就可以告知用户系统正在记录这些操作。

val mCallback = Consumer<Int> { state ->
  if (state == SCREEN_RECORDING_STATE_VISIBLE) {
    // We're being recorded
  } else {
    // We're not being recorded
  }
}

override fun onStart() {
   super.onStart()
   val initialState =
      windowManager.addScreenRecordingCallback(mainExecutor, mCallback)
   mCallback.accept(initialState)
}

override fun onStop() {
    super.onStop()
    windowManager.removeScreenRecordingCallback(mCallback)
}

30.扩展的 IntentFilter 功能

Android 15 构建了通过 UriRelativeFilterGroup 支持更精确的 Intent 解析,其中包含一组 UriRelativeFilter 对象,这些对象构成了一组必须满足的 Intent 匹配规则,其中包括网址查询参数、网址片段以及屏蔽或排除规则。
您可以使用新的 标记在 AndroidManifest XML 文件中定义这些规则,也可以选择包含 android:allow 标记。这些标记可以包含使用现有数据标记属性以及新的 android:query 和 android:fragment 属性的 标记。
下面是 AndroidManifest 语法的示例:

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="http" />
  <data android:scheme="https" />
  <data android:domain="astore.com" />
  <uri-relative-filter-group>
    <data android:pathPrefix="/auth" />
    <data android:query="region=na" />
  </uri-relative-filter-group>
  <uri-relative-filter-group android:allow="false">
    <data android:pathPrefix="/auth" />
    <data android:query="mobileoptout=true" />
  </uri-relative-filter-group>
  <uri-relative-filter-group android:allow="false">
    <data android:pathPrefix="/auth" />
    <data android:fragmentPrefix="faq" />
  </uri-relative-filter-group>
</intent-filter>

31.私密空间

私人空间允许用户在设备上创建一个单独的空间,在那里他们可以通过额外的身份验证保护敏感应用程序免受窥探。私人空间使用单独的用户配置文件。当用户锁定私人空间时,配置文件将暂停,并且私人空间中的任何应用程序都不再处于活动状态。用户可以选择对专用空间使用设备锁定或单独的锁定因子。
私人空间中的应用程序显示在启动器中的一个单独容器中,当私人空间被锁定时,它们被隐藏在最近视图、通知、设置和其他应用程序中。用户生成和下载的内容(如媒体或文件)和帐户在私人空间和主空间之间是分开的。当私人空间解锁时,系统共享表和照片选择器可用于让应用程序跨空间访问内容。

32.隐私沙盒

Android 15 包含最新的 Android 广告服务扩展程序,以及最新版 Privacy Sandbox on Android。我们致力于开发新的技术,以便更好地保护用户隐私,并为移动应用打造有效的个性化广告体验。这项新功能是我们的工作的一部分。我们的隐私沙盒页面详细介绍了 Privacy Sandbox on Android 开发者预览版和 Beta 版计划,以帮助您开始使用。

总结:

作为开发者,适配这些新功能不仅能提升应用的竞争力,更能为用户提供更加流畅和安全的使用体验。我们希望通过这篇博客,能够帮助您更好地理解和利用 Android 15 所带来的新机遇,为您的开发工作提供一些实用的指导和灵感。

感谢您的阅读,期待与您在技术的世界中共同进步和成长。如果您有任何问题或想法,欢迎在评论区与我们分享。让我们共同迎接 Android 15 带来的全新可能性!制作不易还请动动发财的小手点点赞。

  • 45
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值