├── Android 05
├── Android_5.0_API_21_L.md
└── Android_5.1_API_22_L_MR1.md
├── Android 06
└── Android_6_API_23_M.md
├── Android 07
├── Android_7.0_API_24_N.md
└── Android_7.1_API_25_N_MR1.md
├── Android 08
├── Android_8.0_API_26_O.md
└── Android_8.1_API_27_O_MR1.md
├── Android 09
└── Android_9_API_28_P.md
├── Android 10
└── Android_10_API_29_Q.md
├── Android 11
└── Android_11_API_30_R.md
├── Android 12
└── Android_12_API_31_S.md
├── Android 13
├── Android_13_DP2.md
└── images
│ ├── Android 13 计划时间轴.svg
│ └── tmp
├── LICENSE
├── README.md
└── platforms
├── Android_12_API_31_S
└── Android_13_API_32_T
/Android 05/Android_5.0_API_21_L.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 05/Android_5.1_API_22_L_MR1.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 06/Android_6_API_23_M.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 07/Android_7.0_API_24_N.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 07/Android_7.1_API_25_N_MR1.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 08/Android_8.0_API_26_O.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 08/Android_8.1_API_27_O_MR1.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 09/Android_9_API_28_P.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 10/Android_10_API_29_Q.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 11/Android_11_API_30_R.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Android 12/Android_12_API_31_S.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ## 前言
6 |
7 | Android 12 是 2021 年 10 月发布的最新正式版本,然而很多同学表示还没有适配。针对开发者在进行版本适配过程中遇到的问题,我们建立了 [GitHub · AndroidPlatformWiki](https://github.com/pengxurui/AndroidPlatformWiki "GitHub · AndroidPlatformWiki")。我们希望站在开发者的视角,全面且深刻地解读每个 Android 版本更新,以此建立起一个体系化的 Android 系统适配手册。具体包括:
8 |
9 | ### 两个维度
10 |
11 | 根据内容相关度,我们将从 2 个维度解读:
12 |
13 | - **基于时间线:** 现阶段官方每年会发布一个新的版本,因此有必要以一个 Android 版本为单位,解读该版本涉及的新功能与行为变更。这样可以帮助开发同学了解新版本的更新内容,例如我们会通过一个文档解读 Android 13 版本的更新内容与适配自查表;
14 | - **基于内容线:** 通常一个系统功能模块会历经多个系统版本更新才会趋于稳定,因此有必要以一个功能为单位,解读该功能的主要能力以及不同版本的变更和差异。这样可以帮助开发同学了解该功能在不同版本上的差异,例如我们会通过一个文档单独解读系统通知。
15 |
16 | ### 三个等级
17 |
18 | 根据故障敏感性分级,我们将系统变更的兼容性划分为 3 个等级:
19 |
20 | - **强制适配 ❗:** 所有应用必须适配,否则会出现编译不通过、功能不可用或者用户体验受损等问题;
21 | - **推荐适配 ⭐:** 不强制要求适配,但适配的应用将获得更出色的用户体验或更安全的隐私保护等收益;
22 | - **已适配:** 应用不需要任何改动就已经兼容。
23 |
24 | ### 两类行为变更
25 |
26 | 系统行为变更通常属于以下两种类别之一:
27 |
28 | - **面对所有应用的行为变更:** 运行在该系统版本上的所有应用都会影响,而无论应用的 targetSDKVersion 为何。通常应该先针对这些变更进行适配和测试,这有助于用户在新版本系统上运行你的应用时,用户体验不会受损;
29 | - **以特定 targetSDKVersion 为目标版本的行为变更:** 只有 targetSDKVersion 高于或等于系统版本的应用会影响,通常是影响较大或适配工作量较大的变更,我们可以理解为一个 Google 留给开发者的适配缓冲。
30 |
31 | ---
32 |
33 | ## Android 12 适配自查表
34 |
35 | 根据故障敏感性分级,我们将 Android 12 系统变更的兼容性划分为 3 个等级:
36 |
37 | - **强制适配❗:** 涉及该功能的所有应用必须适配的变更,不适配的应用会出现编译不通过、功能不可用,或者用户体验出现一定受损等问题;
38 | - **推荐适配⭐:** 不强制要求适配的变更,适配的应用具有更出色的用户体验或更安全的隐私保护等;
39 | - **已适配:** 应用不需要任何改动就可以兼容的变更。
40 |
41 | ### 以 Android 12 为目标版本的应用
42 |
43 | | 类别 | 变更 | 兼容性 | 摘要 |
44 | | :---------------- | :---------------------------- | :------ | :----------------------------------------------------------------------------------- |
45 | | 1. 用户体验 | 自定义通知外观模板统一 | 强制 ❗ | 自定义通知的内容区域缩小为自定义通知模板内的一块区域,不再完整覆盖通知区域 |
46 | | | 画中画 (PiP) 交互改进 | 推荐 ⭐ | 优化画中画 (PiP) 模式的用户交互 |
47 | | | Toast 视图改进 | 已适配 | 系统 Toast 视图文本最多可以显示两行,并且始终在文本旁边显示应用图标 |
48 | | 2. 安全和隐私设置 | 新蓝牙运行时权限(新) | 推荐 ⭐ | 引入一些新运行时权限,用于更好地管理应用于附近蓝牙设备的连接,而无需请求位置信息权限 |
49 | | | 传感器采样率限制 | 已适配 | 系统会限制某些移动传感器和位置传感器的数据的刷新率 |
50 | | | 应用休眠改进 | 已适配 | 扩展应用休眠机制 |
51 | | | 数据访问审核中的归因标记改进 | 强制 ❗ | 归因标记必须在 Manifest 文件中声明 |
52 | | | ADB 备份限制 | 已适配 | adb backup 导出的数据不再默认包含应用数据 |
53 | | | 显式指定组件 exported 属性 | 强制 ❗ | 声明了 过滤器的组件必须显式设置 android:exported 属性 |
54 | | | 显式指定 PendingIntent 可变性 | 强制 ❗ | PendingIntent 必须显式声明一个可变性标志 |
55 | | | 检测不安全的嵌套 Intent 启动 | 已适配 | StrictMode 会检测不安全的嵌套 Intent 启动 |
56 | | 3. 性能和电池 | 精确的闹钟权限(新) | 强制 ❗ | 设置 AlarmManager 精准闹钟的应用必须在 Manifest 中声明权限 |
57 | | | 前台服务启动限制 | 强制 ❗ | 除了少数情况外,禁止应用从后台启动前台服务 |
58 | | | 通知 trampoline 限制 | 强制 ❗ | 禁止从通知 trampoline 间接启动目标 Activity |
59 |
60 | ### 所有应用
61 |
62 | | 类别 | 变更 | 兼容性 | 摘要 |
63 | | :---------------- | :---------------------------------- | :------ | :------------------------------------------------------------------------- |
64 | | 4. 用户体验 | Material You 设计语言(新) | 已适配 | 新的设计语言 |
65 | | | 富媒体内容插入(新) | 推荐 ⭐ | 应用可以从统一的位置接受任何来源(剪贴板粘贴、键盘输入或拖放操作)的内容 |
66 | | | 支持 AVIF 图片(新) | 推荐 ⭐ | 支持 AVIF 格式图片 |
67 | | | 应用启动动画 API SplashScreen(新) | 强制 ❗ | 支持定制应用启动转场动画 |
68 | | | Widget 桌面小部件改进 | 推荐 ⭐ | 改进 Widgets 外观和行为 |
69 | | | 图形 API 改进 | 推荐 ⭐ | 新增图形效果 |
70 | | | OverScroll 过度滑动动画改进 | 已适配 | 过度滑动动画改为拉伸和反弹效果 |
71 | | | 通知改进 | 推荐 ⭐ | 增加新的通知样式和安全保障 |
72 | | | HTTP 深度链接解析改进 | 已适配 | 调整了 HTTP Intent 的默认解析行为 |
73 | | | 全屏模式的手势导航改进 | 推荐 ⭐ | 增加了一次交互即可执行手势导航的模式 |
74 | | | 屏幕尺寸 API 变更 | 强制 ❗ | 针对适配每种设配上获取屏幕尺寸的需求,系统引入了新 API |
75 | | | 多窗口模式标准化 | 强制 ❗ | 在大屏设备中,系统会为所有 Activity 启用多窗口模式 |
76 | | | 延迟展示前台服务通知 | 已适配 | 除了特殊情况外,前台服务通知会延迟 10 s 显示 |
77 | | | activity 生命周期改进 | 已适配 | 修改根 Activity 的返回行为 |
78 | | | Surface 帧率切换改进 | 推荐 ⭐ | 引入强制切换帧率的 API |
79 | | 5. 安全和隐私设置 | 隐私信息中心(新功能) | 推荐 ⭐ | 隐私信息中心以一个时间轴的方式显示过去时间内所有应用对于敏感信息的访问情况 |
80 | | | 支持只授予粗略位置权限(新) | 强制 ❗ | 用户可以只授予应用模糊位置权限 |
81 | | | 麦克风和摄像头切换开关(新) | 已适配 | 用户可以通过全局切换开关停用整台设备上的摄像头或麦克风权限 |
82 | | | 麦克风和摄像头指示标示(新) | 已适配 | 应用使用麦克风或相机时,状态栏会有图标标记。 |
83 | | | 剪贴板访问提示(新) | 已适配 | 应用首次从另一个应用访问剪辑数据时,会弹出一个消息框消息 |
84 | | | 隐藏应用叠加窗口(新) | 推荐 ⭐ | 应用的窗口可见时可以隐藏所有可见的系统级悬浮窗口 |
85 | | | 应用无法关闭系统对话框 | 强制 ❗ | 除了特殊情况外,禁止应用尝试关闭系统对话框 |
86 | | | 屏蔽不信任的触摸事件 | 强制 ❗ | 屏蔽从不同应用的窗口传递的事件 |
87 | | 6. 性能和电池 | 应用待机分区改进 | 已适配 | 引入了一个新的受限待机分区 |
88 |
89 | ---
90 |
91 | 第 1~3 节介绍的是以 Android 12 为目标版本的应用行为变更和新功能更新,我将这部分更新总结为 3 部分:
92 |
93 | - 1、用户体验(以 Android 12 为目标版本)
94 |
95 | - 2、安全和隐私设置(以 Android 12 为目标版本)
96 |
97 | - 3、性能和电池(以 Android 12 为目标版本)
98 |
99 | ---
100 |
101 | ## 1. 用户体验(以 Android 12 为目标版本)
102 |
103 | ### 1.1 自定义通知外观模板统一
104 |
105 | Android 系统通知可以分为两类样式:标准通知 + 自定义通知
106 |
107 | - **标准通知:** 标准通知是指基于 `NotificationCompat.Builder#setContentTitle()` 等模板 API 构建通知,最终会按照系统预置的视图模板展示。例如:
108 |
109 | 
110 |
111 | - **自定义通知:** 自定义通知是指基于 `NotificationCompat.Builder#setCustomContentView()` 等 API 构建的通知,最终会按照开发者自定义的的布局展示,而不会按照标准通知模板展示。
112 |
113 | 从 Android 12 系统开始,系统规范了自定义通知的外观和行为,自定义通知的内容区域缩小为自定义通知模板内的一块区域,不再完整覆盖通知区域。因此,如果你的应用使用了自定义通知,则需要进行必要的测试和调整:
114 |
115 | - **布局调整:** 由于内容区域缩小了,需要调整并测试通知布局;
116 | - **设置展开式通知:** 由于所有通知都是可展开的,所以需要调用 `NotificationCompat.Builder#setCustomBigContentView()` 设置展开后布局,确保展开和收起状态一致。
117 |
118 | 下图是统一的自定义通知模板:
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | **可以看出,这次改动是 Google 希望自定义通知能够呈现相对一致的感观体验,以及减少不同设备上产生的兼容性问题。**
129 |
130 | ### 1.2 画中画 (PiP) 交互改进
131 |
132 | 画中画模式是 Android 8.0 中引入的一种多窗口模式,最常用于视频播放 Activity,能够实现在视频播放过程中打开其他应用,而不退出中断当前视频。目前主流的音视频 App 都支持画中画模式,你可以在系统设置中搜索 “画中画” 查看。**这次改动是 Google 对画中画模式的用户交互进行优化**,具体参考资料:
133 |
134 | - [对画中画的支持](https://developer.android.com/guide/topics/ui/picture-in-picture.html "对画中画的支持") —— 官方文档
135 | - [Android 12 画中画改进](https://developer.android.google.cn/about/versions/12/features/pip-improvements "Android 12 画中画改进") —— 官方文档
136 |
137 | ### 1.3 Toast 视图改进
138 |
139 | 在 Android 12 中,系统 Toast 视图文本最多可以显示两行,并且始终在文本旁边显示应用图标。相关资料:[消息框概览](https://developer.android.google.cn/guide/topics/ui/notifiers/toasts "消息框概览")
140 |
141 |
142 |
143 |
144 |
145 | ---
146 |
147 | ## 2. 安全和隐私设置(以 Android 12 为目标版本)
148 |
149 | ### 2.1 新蓝牙运行时权限(新功能)
150 |
151 | Android 12 系统引入了新的运行时权限 [BLUETOOTH_SCAN](https://developer.android.google.cn/reference/android/Manifest.permission#BLUETOOTH_SCAN "BLUETOOTH_SCAN")、[BLUETOOTH_ADVERTISE](https://developer.android.google.cn/reference/android/Manifest.permission#BLUETOOTH_ADVERTISE "BLUETOOTH_ADVERTISE") 和 [BLUETOOTH_CONNECT](https://developer.android.google.cn/reference/android/Manifest.permission#BLUETOOTH_CONNECT "BLUETOOTH_CONNECT") 权限,用于更好地管理应用于附近蓝牙设备的连接。
152 |
153 | 在低版本中,应用与附近蓝牙设备连接需要用户授予 `ACCESS_FINE_LOCATION` 精确位置权限,这其实是不合理的设计,因为用户很难理解为什么蓝牙连接会跟位置信息有关。从 Android 12 系统开始,ACCESS_FINE_LOCATION 精确位置权限是可选项,只要应用不会通过蓝牙推导物理位置信息,就不再需要请求。如果不会,你需要在 Manifest 中显式做出 `usesPermissionFlags` 声明:
154 |
155 | ```kotlin
156 |
157 |
159 |
161 | ...
162 |
163 | ```
164 |
165 | - **新蓝牙权限体系(以 Android 12 为目标版本):**
166 | - BLUETOOTH_SCAN:允许搜索附近蓝牙设备;
167 | - BLUETOOTH_ADVERTISE:允许当前设备暴露给其他蓝牙设备;
168 | - BLUETOOTH_CONNECT:允许当前设备连接其他蓝牙设备;
169 | - ACCESS_FINE_LOCATION(可选):允许由蓝牙信息推导设备位置信息。
170 | - **旧蓝牙权限体系:**
171 | - BLUETOOTH:允许与蓝牙相关的交互;
172 | - ACCESS_FINE_LOCATION(必选):允许由蓝牙信息推导设备位置信息,在 Android 9 或以下版本,可以用 ACCESS_COARSE_LOCATION 替代。
173 |
174 | 另外,BLUETOOTH_SCAN 等权限是 NEARBY_DEVICES 附近设备权限组的一部分。请求该权限组的权限,权限授予对话框会提示用户批准访问附近的设备。
175 |
176 |
177 |
178 |
179 |
180 | **可以看出,这次的改动 Google 是希望连接蓝牙设备的权限授予能够给用户更精准的权限功能描述。**
181 |
182 | 相关资料:
183 |
184 | - [蓝牙概览](https://developer.android.google.cn/guide/topics/connectivity/bluetooth "蓝牙概览") —— 官方文档
185 | - [蓝牙权限](https://developer.android.google.cn/guide/topics/connectivity/bluetooth/permissions#declare-android11-or-lower "蓝牙权限") —— 官方文档
186 |
187 | ### 2.2 传感器采样率限制
188 |
189 | 大多数 Android 设备都有内置传感器,用来测量运动、屏幕方向和各种环境条件,这些传感器能够提供高度精确的原始数据。为了保护有关用户的潜在敏感信息,Android 12 系统会限制某些移动传感器和位置传感器的数据的刷新率。
190 |
191 | 相关资料:[传感器概览](https://developer.android.google.cn/guide/topics/sensors/sensors_overview#sensors-rate-limiting "传感器概览") —— 官方文档
192 |
193 | ### 2.3 应用休眠改进
194 |
195 | Android 11 引入了应用休眠机制,如果用户有几个月没有与应用交互,那么系统会将应用置于休眠 / 冬眠状态,Android 12 扩展了应用休眠机制:
196 |
197 | - Android 11:重置已授予的运行时敏感权限;
198 | - Android 12:重置已授予的运行时敏感权限;无法从后台运行任务;无法接收推送通知;应用缓存文件会被删除。
199 |
200 | 相关资料:[应用休眠](https://developer.android.google.cn/topic/performance/app-hibernation "应用休眠") —— 官方文档
201 |
202 | ### 2.4 数据访问审核中的归因标记改进
203 |
204 | Android 11 引入了数据访问审核 API,开发者可以在应用访问用户隐私数据的代码位置增加归因标记,并通过注册 `AppOpsManager.OnOpNotedCallback` 监听。这个功能提供了对调用隐私数据的监听,无论是应用层还是依赖库中的代码,只要访问到私密数据(危险权限)都会回调。从 Android 12 系统开始,归因标记必须在 Manifest 文件中声明,例如:
205 |
206 | ```kotlin
207 |
208 |
211 |
213 | ...
214 |
215 | ```
216 |
217 | 相关资料:[数据访问审核](https://developer.android.google.cn/guide/topics/data/audit-access#declare-attribution-tags "数据访问审核") —— 官方文档
218 |
219 | ### 2.5 ADB 备份限制
220 |
221 | 为了保护私有应用数据,Android 12 变更了 `adb backup` 命令的默认行为,adb backup 导出的数据不再默认包含应用数据。如果开发阶段需要依赖于 adb backup 导出的应用数据,可以将 Manifest 文件中将 android:debuggable 设置为 true 来导出应用数据。
222 |
223 | ### 2.6 显式指定组件 exported 属性
224 |
225 | 组件属性 `android:exported` 用于设置该组件是否支持其他应用交互,exported 为 false 表示不允许该组件被其他应用启动。一般 exported 属性默认为 false,除非组件声明了 `` 过滤器(即支持隐式启动),则 exported 属性默认为 true。从 Android 12 系统开始,声明了 过滤器的组件必须显式设置 android:exported 属性。例如:
226 |
227 | ```kotlin
228 |
230 |
231 |
232 |
233 |
234 | ```
235 |
236 | 否则,在编译应用时就会有报错:
237 |
238 | ```kotlin
239 | Manifest merger failed : Apps targeting Android 12 and higher are required \
240 | to specify an explicit value for android:exported when the corresponding \
241 | component has an intent filter defined.
242 | ```
243 |
244 | 如果使用低版本的 Android Gradle 插件虽然可以编译成功,但安装时会报错:
245 |
246 | ```bash
247 | Installation did not succeed.
248 | The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
249 | ```
250 |
251 | **可以看出,这次改动背后的理念是 “不要相信默认值”,因为不符合预期的默认值会产生更严重的风险**。举个例子,由于开发者的疏忽,一个原本不允许外部应用启动的组件未显式声明 android:exported=“false”,而正好该组件声明了 过滤器,那么就因为默认值的影响的产生了一个安全风险。而强制开发者对声明 过滤器的组件显式声明 android:exported 的值,就可以避免了默认值的安全风险。同样的道理在对接外部系统时,也不要相信默认值,例如网络请求参数的默认值,能传的就传。
252 |
253 | ### 2.7 显式指定 PendingIntent 可变性
254 |
255 | 为了使 PendingIntent 的处理更加安全,Android 12 要求 PendingIntent 必须显式声明一个可变性标志即 [FLAG_MUTABLE](https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.android.google.cn%2Freference%2Fandroid%2Fapp%2FPendingIntent%23FLAG_MUTABLE "FLAG_MUTABLE") 或 [FLAG_IMMUTABLE](https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.android.google.cn%2Freference%2Fandroid%2Fapp%2FPendingIntent%23FLAG_IMMUTABLE "FLAG_IMMUTABLE")。在此之前,PendingIntent 默认是可变的。
256 |
257 | ### 2.8 检测不安全的嵌套 Intent 启动
258 |
259 | Android 12 引入了一项 `StrictMode` 检查规则,用于检测不安全的嵌套 Intent 启动。StrictMode 模式大家很熟悉了,这里解释下为什么嵌套 Intent 启动是不安全的。
260 |
261 | 举个例子,开发者的预期效果是 Client App 请求 Provider App 的一个服务,并且希望在请求结束后回调到 Client App 的 ClientCallbackActivity。那么,最直接的方法是将启动 ClientCallbackActivity 的 Intent 当作参数嵌套到启动 ApiService 的 Intent 里。例如:
262 |
263 |
264 |
265 |
266 |
267 | 乍看起来没有问题,但其实这种实现方式存在两个隐蔽的安全风险:
268 |
269 | - **Client App:** 由于 ClientCallbackActivity 是从另一个应用 Provider App 启动的,因此它必须暴露为 exported。这意味着除了 Provider App 外,设备上其他恶意的应用也可以启动 ClientCallbackActivity;
270 | - **Provider App:** 由于嵌套的 Intent 是在 Provider App 的上下文中启动的,因此恶意应用 Attacker App 可以将 Provider App 的任何一个 Activity 嵌套其中,即使启动的是私有的非 exported 的 Activity,这让 Provider App 防不胜防。
271 |
272 |
273 |
274 |
275 |
276 | 解决方法是使用 PendingIntent 替代嵌套 Intent,PendingIntent 是 Intent 的包装容器,也类似于一个嵌套 Intent。但是,**很多小伙伴简单地认为 PendingIntent 只是延迟待处理的 Intent,两者只有时间维度的区别,这是片面的。**
277 |
278 | **PendingIntent 的最主要的作用是授权外部应用以本应用的身份执行使用嵌套的 Intent**。有点拗口哈,在我们这个例子里,就是 Client App 将启动 ClientCallbackActivity 的 Intent 暴露给 Provider App 后,但 Provider App 在使用 PendingIntent 时,系统会以 Client App 的上下文身份来使用嵌套的 Intent。
279 |
280 | ```kotlin
281 | PendingIntent pendingIntent = PendingIntent.getActivity(application, 0, resultIntent, 0);
282 | ```
283 |
284 | 现在,我们再回顾下还有没有风险:
285 |
286 | - **Client App:** 由于 PendingIntent 使用 Client App 的身份使用嵌套的 Intent,那么 ClientCallbackActivity 不再需要暴露为 exported;
287 | - **Provider App:** 由于 PendingIntent 使用 Client App / Attacker App 的身份使用嵌套的 Intent,而它们是没有权限访问 Provider App 非 exported 的 ApiSensitiveActivity 的。
288 |
289 | 相关资料:[Android 嵌套 Intent](https://medium.com/androiddevelopers/android-nesting-intents-e472fafc1933 "Android 嵌套 Intent") —— 官方博客文章
290 |
291 | ---
292 |
293 | ## 3. 性能和电池(以 Android 12 为目标版本)
294 |
295 | ### 3.1 精确的闹钟权限(新功能)
296 |
297 | Android 12 系统引入了新的权限 `android.permission.SCHEDULE_EXACT_ALARM`,设置 AlarmManager 精准闹钟的应用必须在 Manifest 中请求 SCHEDULE_EXACT_ALARM 权限。此外,还新增了一个新的 API —— `canScheduleExactAlarms()`,用于检查应用的精准闹钟权限状态。
298 |
299 | 相关资料:[设置重复闹钟时间](https://developer.android.google.cn/training/scheduling/alarms#exact-acceptable-use-cases "设置重复闹钟时间")
300 |
301 | ### 3.2 前台服务启动限制
302 |
303 | Android 12 对应用从后台启动前台服务的行为做出限制,除了 [后台启动限制的豁免](https://developer.android.google.cn/guide/components/foreground-services#background-start-restriction-exemptions "后台启动限制的豁免") 等少数情况外,如果应用尝试在后台运行时启动前台服务,系统会抛出 `ForegroundServiceStartNotAllowedException` 异常。应用可以使用 JobScheduler 中新引入的 [加急作业]() (expedited job) 来代替之前的做法。
304 |
305 | > **提示:** 如果一个应用调用 `Context.startForegroundService()` 以启动另一个应用拥有的前台服务,则这些限制仅适用于两个应用都针对 Android 12 或更高版本的情况。
306 |
307 | ### 3.3 通知 trampoline 限制
308 |
309 | 通知 trampoline (蹦床) 是指利用广播接收器或服务间接启动目标 Activity(用户与通知交互后,应用先启动服务或广播接收器作为中介,再去启动 目标 Activity)。Android 12 系统对通知 trampoline 做出限制,当应用尝试从通知 trampoline 启动 Activity,系统会拦截该启动行为:
310 |
311 | ```kotlin
312 | Indirect notification activity start (trampoline) from PACKAGE_NAME, \
313 | this should be avoided for performance reasons.
314 | ```
315 |
316 | 如果你的应用使用了通知 trampoline,那么你需要切换为常规的 PendingIntent 方式。
317 |
318 | ---
319 |
320 | 第 4~6 节介绍的是针对所有应用的应用行为变更和新功能更新,我将这部分更新总结为 3 部分:
321 |
322 | - 4、用户体验(所有应用)
323 | - 5、安全和隐私设置(所有应用)
324 | - 6、性能和电池(所有应用)
325 |
326 | ---
327 |
328 | ## 4. 用户体验(所有应用)
329 |
330 | ### 4.1 Material You 设计语言(新功能)
331 |
332 | Android 12 引入了一种名为 [Material You](https://material.io/blog/announcing-material-you "Material You") 的新设计语言(对 Material Design 的再发展),可帮助构建更具个性化、更精美的应用。
333 |
334 | 
335 |
336 | ### 4.2 富媒体内容插入(新功能)
337 |
338 | Android 12 系统引入了一个统一 API,使得应用可以从统一的位置接受任何来源(剪贴板粘贴、键盘输入或拖放操作)的内容。例如:
339 |
340 |
341 |
342 |
343 |
344 | 相关资料:[接收富媒体内容](https://developer.android.google.cn/guide/topics/input/receive-rich-content "接收富媒体内容") —— 官方文档
345 |
346 | ### 4.3 支持 AVIF 图片(新功能)
347 |
348 | Android 12 引入了对使用 AV1 图片文件格式 (AVIF) 的图片的支持。AVIF 是一种使用 AV1 编码的图片和图片序列的容器格式。AVIF 利用了视频压缩的帧内编码内容。与以前的图片格式(例如 JPEG)相比,这种格式可显著提升相同文件大小下的图片质量。
349 |
350 | 
351 |
352 | 相关资料:[AVIF has landed](https://jakearchibald.com/2020/avif-has-landed/ "AVIF has landed") —— Jake Archibald 著
353 |
354 | ### 4.4 应用启动动画 API SplashScreen(新功能)
355 |
356 | 从 Android 12 系统开始,所有应用的冷启动和温启动期间,系统会使用新的 SplashScreen API 来启动应用启动动画。除了平台 API 外,Google 还提供了兼容库 API:[androidx.core.splashscreen](https://developer.android.google.cn/reference/kotlin/androidx/core/splashscreen/SplashScreen "androidx.core.splashscreen")。
357 |
358 | 
359 |
360 | 在 SplashScreen API 之前,我们通常是利用 SplashActivity 的背景图 `android:windowBackground` 来实现应用启动转场效果,这个大家都很熟悉了。如果你不做任何适配,那么根据你配置的 windowBackground 资源值,在 Android 12 上会有不同的效果:
361 |
362 | - windowBackground 采用 `@color/单色`,则系统会使用该单色和应用的启动图标来构成启动效果,这可能与预期效果不符;
363 | - windowBackground 采用 `@drawable/图片`,则系统会继续使用该图片来构成启动效果,这个体验与低版本系统一致。
364 |
365 | 因此,如果你的应用采用的是 windowBackground 为图片资源的方式,那么你不适配也没有问题。需要升级启动效果的话,推荐参考以下资料:
366 |
367 | - [启动画面](https://developer.android.google.cn/guide/topics/ui/splash-screen "启动画面") —— Android 官方文档
368 | - [Jetpack 新成员 SplashScreen:打造全新的 App 启动画面](https://juejin.cn/post/6997217571208445965 "Jetpack 新成员 SplashScreen:打造全新的 App 启动画面") —— TechMerger 著
369 |
370 | **可以看出,这次改动 Google 是希望提升下应用启动时的转场体验,同时也给予开发者更多自定义的想象空间。**
371 |
372 | ### 4.5 Widget 桌面小部件改进
373 |
374 | Android 12 改进了现有的 Widgets API,让它们更实用、更美观,且更易于发现。相关改动详见以下资料:
375 |
376 |
377 |
378 |
379 |
380 | 相关资料:
381 |
382 | - [应用 Widget 概览](https://developer.android.google.cn/guide/topics/appwidgets/overview "应用 Widget 概览") —— 官方文档
383 | - [Android 12 Widget 改进](https://developer.android.google.cn/about/versions/12/features/widgets "Android 12 Widget 改进") —— 官方文档
384 | - [创造无限可能 | 在 Android 12 中使用 widget](https://juejin.cn/post/7012815676641378317 "创造无限可能 | 在 Android 12 中使用 widget") —— 官方博客文章
385 | - [更新您的 widget 以适配 Android 12](https://juejin.cn/post/7004660915538755615 "更新您的 widget 以适配 Android 12") —— 官方博客文章
386 |
387 | ### 4.6 图形 API 改进
388 |
389 | - 圆角:Android 12 引入了新的圆角 API [RoundedCorner](https://developer.android.google.cn/reference/android/view/RoundedCorner "RoundedCorner")
390 | 和 [WindowInsets.getRoundedCorner(int position)](),可以提供给 View 实现圆角效果;
391 | - 滤镜:Android 12 添加了新的滤镜 API [RenderEffect](https://developer.android.google.cn/reference/android/graphics/RenderEffect "RenderEffect") 可以给 View 实现常见的图片效果(如毛玻璃、颜色滤镜、Android 着色器效果及更多效果)。
392 |
393 | ```kotlin
394 | view.setRenderEffect(RenderEffect.createBlurEffect(radiusX, radiusY, SHADER_TILE_MODE))
395 | ```
396 |
397 |
398 |
399 |
400 |
401 | ### 4.7 OverScroll 过度滑动动画改进
402 |
403 | Android 12 修改了可滚动控件在边缘过度滑动(OverScroll)的动画效果,从低版本的边缘发光效果修改为拉伸和反弹效果。这个边缘过度滑动效果是可以关闭的,有两种方法:
404 |
405 | - 设置 `android:overScrollMode=”never”`
406 | - 设置 `View#setOverScrollMode(View.OVER_SCROLL_NEVER)`
407 |
408 | ### 4.8 通知改进
409 |
410 | - 电话通知:从 Android 12 系统开始,新增了新的电话通知样式 [Notification.CallStyle](https://developer.android.google.cn/reference/android/app/Notification.CallStyle "Notification.CallStyle");
411 | - 丰富图片支持:从 Android 12 系统开始,应用可以在 [MessagingStyle()]() 和 [BigPictureStyle()]() 通知中提供动画图片,来丰富应用的通知体验。此外,应用现在还可以让用户在从通知栏回复消息时发送图片消息;
412 | - 设备解锁保障:从 Android 12 系统开始,应用可以通过 [setAuthenticationRequired(true)](),要求系统在执行通知的 PendingIntent 前先要求用户解锁设备,这对于敏感操作增加了一层安全保障。
413 |
414 | ### 4.9 HTTP 深度链接解析改进
415 |
416 | Android 系统支持通过 Deep Link 或 Android App Link 将深度链接与应用行为关联,实践中采用的链接基于 URI 格式,例如:
417 |
418 | 
419 |
420 | 从 Android 12 系统开始,系统调整了 HTTP Intent 的默认解析行为。在低版本中,如果 HTTP 链接未命中任何 Deep Link / App Link 的匹配规则,那么系统会打开应用选择对话框;而现在系统会直接通过默认浏览器打开链接(因为该链接本身是一个可访问的网址)
421 |
422 |
423 |
424 |
425 |
426 | 相关资料:
427 |
428 | - [Android Deep Link 深度链接,看看你在第几层?](https://juejin.cn/post/7073731278612201509 "Android Deep Link 深度链接,看看你在第几层?")
429 | - [处理 Android 应用链接](https://developer.android.google.cn/training/app-links "处理 Android 应用链接") —— 官方文档
430 |
431 | ### 4.10 全屏模式下的手势导航改进
432 |
433 | 全屏模式是指应用最大限度地利用屏幕空间来展示内容,让用户获得最佳体验,常见场景例如视频、游戏、演示文稿等。
434 |
435 |
436 |
437 |
438 |
439 | 全屏模式会隐藏状态栏、导航栏等系统栏,意味着用户无法轻松与系统栏交互,因此系统定义了以下全屏模式下的系统栏行为,使用 [WindowInsetsControllerCompat.setSystemBarsBehavior](https://developer.android.google.cn/reference/androidx/core/view/WindowInsetsControllerCompatt "WindowInsetsControllerCompat.setSystemBarsBehavior") 设置:
440 |
441 | - [BEHAVIOR_SHOW_BARS_BY_TOUCH](https://developer.android.google.cn/reference/androidx/core/view/WindowInsetsControllerCompat#BEHAVIOR_SHOW_BARS_BY_TOUCH "BEHAVIOR_SHOW_BARS_BY_TOUCH") 模式,当用户点击屏幕任何位置后,会重新显示系统栏。这种模式适合于用户不会与屏幕进行大量互动的场景;
442 | - [BEHAVIOR_SHOW_BARS_BY_SWIPE](https://developer.android.google.cn/reference/androidx/core/view/WindowInsetsControllerCompat#BEHAVIOR_SHOW_BARS_BY_SWIPE "BEHAVIOR_SHOW_BARS_BY_SWIPE") 模式,当用户从隐藏系统栏的边缘滑动时,会显示系统栏。例如从屏幕底部边缘向上滑动,会重新显示系统导航栏。这种模式适合于用户需要与屏幕进行大量交互的场景,例如游戏、阅读等,使用这种意图更强的手势能够避免系统栏交互与应用交互冲突;
443 | - [BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE](https://developer.android.google.cn/reference/androidx/core/view/WindowInsetsControllerCompat#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE "BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE") 模式,当用户从隐藏系统栏的边缘滑动时,会暂时性地显示系统栏,并等待一小段时间后自动重新隐藏。系统栏会并不会挤压应用内容,而是以半透明的方式覆盖在应用上层。
444 |
445 | Android 12 系统整合了现有模式,BEHAVIOR_SHOW_BARS_BY_TOUCH 和 BEHAVIOR_SHOW_BARS_BY_SWIPE 这两种行为现已弃用,新增了 BEHAVIOR_DEFAULT 行为。
446 |
447 | - [BEHAVIOR_DEFAULT](https://developer.android.google.cn/reference/android/view/WindowInsetsController#BEHAVIOR_DEFAULT "BEHAVIOR_DEFAULT") 模式:当用户从隐藏系统栏的边缘滑动时,会显示系统栏,这一点与 BEHAVIOR_SHOW_BARS_BY_SWIPE 类似。最主要的是,全面屏导航手势可以直接生效,不管系统导航栏是否可见。换句话说,BEHAVIOR_DEFAULT 行为让用户只需滑动一次即可执行手势导航,而在 Android 11 上则需要滑动两次。
448 |
449 |
450 |
451 |
452 |
453 | 相关资料:[启用全屏模式](https://developer.android.google.cn/training/system-ui/immersive#immersive-consolidated-behavior "启用全屏模式")
454 |
455 | ### 4.11 屏幕尺寸 API 变更
456 |
457 | Android 11 系统废弃了 [Display.getSize](https://developer.android.google.cn/reference/android/view/Display#getSize "Display.getSize") & [Display.getMetrics](https://developer.android.google.cn/reference/android/view/Display#getMetrics "Display.getMetrics"),并在 Android 12 中继续废弃了 [Display.getRealSize](https://developer.android.google.cn/reference/android/view/Display#getRealSize "Display.getRealSize") & [Display.getRealMetrics](https://developer.android.google.cn/reference/android/view/Display#getRealMetrics "Display.getRealMetrics")。Android 设备有许多不同的外形(例如大屏设备、平板电脑和可折叠手机),为了针对适配每种设备上获取屏幕尺寸的需求,系统引入了 WindowMetrics API。
458 |
459 | - 平台 API: [WindowMetrics](https://developer.android.google.cn/reference/android/view/WindowMetrics "WindowMetrics")
460 | - 兼容库 API: [WindowManager](https://developer.android.google.cn/jetpack/androidx/releases/window "WindowManager")
461 |
462 | ### 4.12 多窗口模式标准化
463 |
464 | Android 7 系统引入了多窗口模式,允许同时在屏幕上显示多个应用,目前一共有 3 种多窗口模式:
465 |
466 | - **分屏模式:** 以左右并排或上下并排显示两个应用;
467 | - **画中画模式:** 以叠加的小窗口显示应用;
468 | - **自由窗口模式:** 以可移动且可调整显示尺寸的窗口显示应用;
469 |
470 |
471 |
472 |
473 |
474 | 从 Android 12 系统开始,多窗口模式将成为大屏设备上的标准行为,大屏设备下 Activity 的 `resizeableActivity` 配置将被忽略。具体如下:
475 |
476 | - **Android 7:** 手机设备支持分屏模式,电视设备支持画中画模式,更大尺寸的设备制造商可以选择启用自由窗口模式。开发者可以设置 android:resizeableActivity=”false” 禁用多窗口模式,确保 Activity 始终以独占屏幕的方式显示;
477 | - **Android 8:** 手机设备也支持画中画模式;
478 | - **Android 12:** 在小屏设备(sw < 600dp)设备中,系统根据 resizeableActivity 配置确定该 Activity 是否启用多窗口模式,在大屏设备中,系统会忽略 resizeableActivity 配置,为所有 Activity 启用多窗口模式。在此之前,用户要操作的 Activity 不支持多窗口的话,用户只能先退出窗口,再回来,体验就中断了。
479 |
480 | **可以看出,这次改动 Google 是希望大屏设备下的多窗口模式成为标准行为,实现多窗口模式下的体验闭环**。
481 |
482 | ### 4.13 延迟展示前台服务通知
483 |
484 | 前台服务(startForegroundService 启动的服务)会显示一个系统通知,以便让用户应用正在执行任务并且消耗系统资源,即使该应用已经退出到后台。从 Android 12 系统开始,前台服务通知会延迟 10 s 显示,除非一些需要立即显示通知的服务。
485 |
486 | 以下是立即显示通知的情况:
487 |
488 | - 1、前台服务通知调用 `NotificationCompat.Builder#setForegroundServiceBehavior(FOREGROUND_SERVICE_IMMEDIATE)` 修改了显示行为;
489 | - 2、前台服务通知调用 `NotificationCompat.Builder#addAction()` 配置了可操作按钮;
490 | - 3、前台服务通知调用 `NotificationCompat.Builder#setCategory()` 配置为 CATEGORY_CALL、CATEGORY_NAVIGATION 或 CATEGORY_TRANSPORT;
491 | - 4、前台服务的 [foregroundServiceType](https://developer.android.google.cn/guide/topics/manifest/service-element#foregroundservicetype "foregroundServiceType") 取值 mediaPlayback、mediaProjection 或 phoneCall。
492 |
493 | **可以看出,这次改动 Google 是希望简化短期运行的前台服务的用户感知,既然服务很快就停止了,就没有必要用通知让用户注意到。**
494 |
495 | 相关资料:
496 |
497 | - [前台服务](https://developer.android.google.cn/guide/components/foreground-services "前台服务") —— 官方文档
498 |
499 | ### 4.14 activity 生命周期改进
500 |
501 | 从 Android 12 开始,系统修改了 Activity Task 根 Activity 在处理 ”返回键“ 时的默认行为。在旧版本中,返回键会执行 finish Activity,而从 Android 12 开始会将 Task 任务栈切换到后台。此后,用户返回应用将执行热启动,应用的热启动简单得多,系统的工作只是将 Activity 恢复到前台。
502 |
503 | `Activity.java`
504 |
505 | ```kotlin
506 | public void onBackPressed() {
507 | if (mActionBar != null && mActionBar.collapseActionView()) {
508 | return;
509 | }
510 |
511 | FragmentManager fragmentManager = mFragments.getFragmentManager();
512 |
513 | if (!fragmentManager.isStateSaved() && fragmentManager.popBackStackImmediate()) {
514 | return;
515 | }
516 | if (!isTaskRoot()) {
517 | // If the activity is not the root of the task, allow finish to proceed normally.
518 | finishAfterTransition();
519 | return;
520 | }
521 | // 以上 Android 12 与旧版本相同,差别在下面这句:
522 | try {
523 | // Android 11
524 | // Inform activity task manager that the activity received a back press
525 | // while at the root of the task. This call allows ActivityTaskManager
526 | // to intercept or defer finishing.
527 | ActivityTaskManager.getService().onBackPressedOnTaskRoot(mToken,
528 | new IRequestFinishCallback.Stub() {
529 | public void requestFinish() {
530 | mHandler.post(() -> finishAfterTransition());
531 | }
532 | });
533 | // Android 12
534 | // Inform activity task manager that the activity received a back press while at the
535 | // root of the task. This call allows ActivityTaskManager to intercept or move the task
536 | // to the back.
537 | ActivityClient.getInstance().onBackPressedOnTaskRoot(mToken,
538 | new RequestFinishCallback(new WeakReference<>(this)));
539 | } catch (RemoteException e) {
540 | finishAfterTransition();
541 | }
542 | }
543 | ```
544 |
545 | **可以看出,这次的改动 Google 希望通过 ”返回**键**“ 退出的应用,能够更快地从热启动恢复应用,而不是从冷启动或温启动重启应用。**
546 |
547 | ### 4.15 Surface 帧率切换改进
548 |
549 | Android 11 系统引入了一个 Surface 帧率切换 API `setFrameRate()`,但这个 API 并不总是会生效。由于不支持无缝切换帧率的屏幕在切换帧率时会有一两秒的黑屏,所以系统会对这一行为做拦截。如果屏幕不支持无缝切换,即使应用调用 setFrameRate() 依然会继续使用原来的帧率。
550 |
551 | Android 12 系统引入了强制切换帧率的 API,这对于长视频内容的帧率切换更有优势,因为合适帧率带来的体验提升已经超过了不支持无缝切换带来的体验损失。
552 |
553 | ```kotlin
554 | // 检查是否支持无缝切换帧率
555 | val refreshRates = this.display?.mode?.alternativeRefreshRates
556 | val willBeSeamless = Arrays.asList(refreshRates).contains(newRefreshRate)
557 |
558 | // 切换帧率,即使屏幕不支持无缝过渡
559 | surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS)
560 | ```
561 |
562 | - **CHANGE_FRAME_RATE_ALWAYS:** 总是切换帧率,即使屏幕不支持无缝过渡;
563 | - **CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS:** 仅在屏幕支持无缝过渡时切换帧率(旧版本行为)。
564 |
565 | ---
566 |
567 | ## 5. 安全和隐私设置(所有应用)
568 |
569 | ### 5.1 隐私信息中心(新功能)
570 |
571 | Android 12 系统在系统设置中引入了隐私信息中心功能,可以让用户更好地了解应用正在访问数据的行为。隐私信息中心以一个时间轴的方式显示过去时间内所有应用对于麦克风、摄像头或位置等敏感信息的访问情况。
572 |
573 |
574 |
575 |
576 |
577 | 另外,系统定义了一个新的 Intent 操作 [ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD](https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.android.google.cn%2Freference%2Fandroid%2Fcontent%2FIntent.html%23ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD "ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD"),可以从隐私信息中心中向用户解释为什么应用需要访问这些隐私信息。要支持此功能,应用需要定义一个 Activity 并声明 IntentFilter 关联到此 Action 上,例如:
578 |
579 | ```kotlin
580 |
581 |
584 |
588 |
589 |
590 |
591 |
592 | ...
593 |
594 |
595 | ```
596 |
597 | 相关资料:[解释对比较敏感信息的访问权限](https://developer.android.google.cn/training/permissions/explaining-access#privacy-dashboard-show-rationale "解释对比较敏感信息的访问权限")
598 |
599 | ### 5.2 支持只授予粗略位置权限(新功能)
600 |
601 | Android 系统支持两个精度级别的位置信息,并且分别对应一个权限。虽然有两个精度级别的权限,但是因为它们处于同一个权限组中,所以应用只要请求授予其中一个权限,另一个权限就自动授予了。
602 |
603 | - **粗略位置:** 精确到 3 平方公里的位置值,请求 ACCESS_COARSE_LOCATION 权限可以获得;
604 | - **精确位置:** 精确到 50 米以内的位置值,请求 ACCESS_FINE_LOCATION 权限可以获得。
605 |
606 | 然而,从 Android 12 系统开始,这一规则不再成立了。从 Android 12 系统开始,用户可以只授予应用模糊位置 ACCESS_COARSE_LOCATION 权限,即使应用请求的是精确位置 ACCESS_FINE_LOCATION 权限。
607 |
608 | 举个例子,我们通过以下代码请求 ACCESS_FINE_LOCATION 权限,在 Android 12 系统上的权限请求弹窗会给用户两个选项:`Precise 精确位置` 和 `Approximate 粗略位置`。如果用户选择授予粗略位置,那么最终应用获得的权限反而是 ACCESS_COARSE_LOCATION 权限,而不是一开始请求的 ACCESS_FINE_LOCATION 权限,并且应用也只能获取粗略位置信息。
609 |
610 | ```kotlin
611 | val locationPermissionRequest = registerForActivityResult(
612 | ActivityResultContracts.RequestPermission()
613 | ) { isGrant ->
614 |
615 | Log.i("权限","isGrant: $isGrant")
616 | if (PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
617 | Log.i("权限", "ACCESS_COARSE_LOCATION is Grant")
618 | }
619 | if (PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
620 | Log.i("权限", "ACCESS_FINE_LOCATION is Grant")
621 | }
622 | }
623 |
624 | findViewById(R.id.tv).setOnClickListener {
625 | locationPermissionRequest.launch( Manifest.permission.ACCESS_FINE_LOCATION)
626 | }
627 | ```
628 |
629 | 输出日志:
630 |
631 | ```kotlin
632 | I/权限: isGrant: false
633 | I/权限: ACCESS_COARSE_LOCATION is Grant
634 | ```
635 |
636 |
637 |
638 |
639 |
640 | 那么从 Android 12 开始,你在请求位置权限时就要注意以下问题,稍不注意就出现兼容问题了:
641 |
642 | - 请求位置权限时要同时请求 ACCESS_FINE_LOCATION 权限和 ACCESS_COARSE_LOCATION 权限,如果应用只请求 ACCESS_FINE_LOCATION 权限,系统会直接忽略该请求。如果应用以 Android 12 或更高版本为目标版本,系统会在 logcat 中提示错误:
643 |
644 | ```kotlin
645 | ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.
646 | ```
647 |
648 | > 提示:我在 Pixel 模拟器上实测并没有出现文档描述的 ”忽略请求“ 和 ”报错提示“,不过最好还是按照官方文档处理吧。
649 |
650 | - 即使用户已经授予了精确位置权限,用户依然可以进入系统设置中直接修改到粗略位置权限,修改后系统会自动杀死进程。
651 | - 为了更好地尊重用户隐私,尽量只请求 ACCESS_COARSE_LOCATION 权限,因为粗略位置信息已经能满足大多数应用场景。仅请求 ACCESS_COARSE_LOCATION 权限时,授权弹窗只有一个选项:
652 |
653 |
654 |
655 |
656 |
657 | - 如果你的应用场景确实需要请求 ACCESS_FINE_LOCATION 权限,那么你可以再次同时请求 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 权限。由于之前用户已经授予过粗略位置权限,这次的系统弹窗会变成询问是否升级到精确位置权限:
658 |
659 |
660 |
661 |
662 |
663 | - 最后一个问题,怎么确定应用场景时需要精确位置还是粗略位置呢?其实并不是依靠纯主观判断,这块是有行业标准的。在我们之前讨论的 [还在见招拆招?先看懂 APP 个人信息保护治理机制](https://juejin.cn/post/7078940840009302052 "还在见招拆招?先看懂 APP 个人信息保护治理机制") 中,提到过一个标准 [团体标准《APP 收集使用个人信息最小必要评估规范》共 17 项](https://link.juejin.cn/?target=https%3A%2F%2Fwww.miit.gov.cn%2Fjgsj%2Fxgj%2FAPPqhyhqyzxzzxd%2Fzcbz%2Fart%2F2021%2Fart_f438a606b92e40ada9c611139f297300.html "团体标准《APP 收集使用个人信息最小必要评估规范》共 17 项")。其中对于位置信息的获取有明确的标准和案例,例如:
664 |
665 |
666 |
667 |
668 |
669 | > 有小伙伴发现部分 Android 12 系统的手机上,请求位置权限的行为跟低版本没有区别,这是因为有些厂商系统还没有完全实现这个功能。以小米 MIUI 13.0.5.0 为例,模糊定位功能需要打开 `系统设置 - 隐私保护实验室 - 模糊定位` 选项才能启用。而且我在该系统上实测后,发现即使用户只授予 ACCESS_COARSE_LOCATION 权限,另一个 ACCESS_FINE_LOCATION 权限也会同时授予,这个就离谱了,怪不得还在实验室。
670 |
671 | **可以看出,这次的改动是 Google 希望引导开发者尽量使用低精度的位置信息,提高对用户隐私的保护度。**
672 |
673 | 相关资料:
674 |
675 | - [请求位置权限](https://developer.android.google.cn/training/location/permissions "请求位置权限") —— 官方文档
676 | - [请求应用权限](https://developer.android.google.cn/training/permissions/requesting#explain "请求应用权限") —— 官方文档
677 | - [解释对比较敏感信息的访问权限](https://developer.android.google.cn/training/permissions/explaining-access#privacy-dashboard-show-rationale "解释对比较敏感信息的访问权限") —— 官方文档
678 |
679 | ### 5.3 麦克风和摄像头切换开关(新功能)
680 |
681 | 从 Android 12 系统开始,用户可以通过一个全局切换开关,停用整台设备上的摄像头或麦克风权限。当应用请求摄像头或麦克风权限时,系统有弹窗提示。这个切换开关在不同厂商系统上的体现不一样,比如小米系统是放在 `手机关机-隐身模式` 。
682 |
683 |
684 |
685 |
686 |
687 | ### 5.4 麦克风和摄像头指示标示(新功能)
688 |
689 | 从 Android 12 开始,当应用使用麦克风或相机时,在状态栏会有图标标记。
690 |
691 | ### 5.5 剪贴板访问提示(新功能)
692 |
693 | 在 Android 12 及更高版本中,当某个应用首次调用 [getPrimaryClip](https://developer.android.google.cn/reference/android/content/ClipboardManager#getPrimaryClip "getPrimaryClip") 以 [从另一个应用访问剪辑数据](https://developer.android.google.cn/guide/topics/text/copy-paste#Pasting "getPrimaryClip( "从另一个应用访问剪辑数据")") 时,会弹出一个消息框消息,提示用户应用存在访问剪贴板的行为。
694 |
695 | ### 5.6 隐藏应用叠加窗口(新功能)
696 |
697 | Android 12 系统引入了隐藏 TYPE_APPLICATION_OVERLAY 窗口的功能。声明 [HIDE_OVERLAY_WINDOWS](https://developer.android.google.cn/reference/android/Manifest.permission#HIDE_OVERLAY_WINDOWS "HIDE_OVERLAY_WINDOWS") 权限后,应用可以调用 [setHideOverlayWindows](https://developer.android.google.cn/reference/android/view/Window "setHideOverlayWindows") 指明当应用的窗口可见时隐藏所有可见的 TYPE_APPLICATION_OVERLAY 窗口。例如在显示敏感页面(如交易)时,应用可以选择隐藏其他悬浮窗。
698 |
699 | ### 5.7 应用无法关闭系统对话框
700 |
701 | 为了加强用户与应用和系统互动时的控制,从 Android 12 系统开始,弃用了 [ACTION_CLOSE_SYSTEM_DIALOGS](https://developer.android.google.cn/reference/android/content/Intent#ACTION_CLOSE_SYSTEM_DIALOGS "ACTION_CLOSE_SYSTEM_DIALOGS") Intent 操作,当应用使用尝试关闭系统对话框时,除了 [一些特殊情况](https://developer.android.google.cn/about/versions/12/behavior-changes-all#close-system-dialogs-exceptions "一些特殊情况") 之外,系统会进行拦截:
702 |
703 | - 以 Android 12 或更高版本为目标版本:系统会抛出 SecurityException;
704 | - 以 Android 11 或更低版本为目标版本:系统不会执行 Intent,并在 logcat 提示:
705 |
706 | ```kotlin
707 | E ActivityTaskManager Permission Denial: \
708 | android.intent.action.CLOSE_SYSTEM_DIALOGS broadcast from \
709 | com.package.name requires android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, \
710 | dropping broadcast.
711 | ```
712 |
713 | ### 5.8 屏蔽不信任的触摸事件
714 |
715 | 屏幕应用是用户与应用交互的主要方式,为了提高触摸交互的直观和安全性,Android 12 系统会屏蔽从不同应用的窗口传递的事件。因此,这次的改动主要影响 声明选择让触摸事件穿透窗口的应用,例如声明了 TYPE_APPLICATION_OVERLAY 和 FLAG_NOT_TOUCHABLE 的悬浮窗口。
716 |
717 | 详细分析见相关资料:[行为变更 | Android 12 中不受信任的触摸事件](https://juejin.cn/post/6998339177024602125 "行为变更 | Android 12 中不受信任的触摸事件") —— 官方博客文章
718 |
719 | ---
720 |
721 | ## 6. 性能和电池(所有应用)
722 |
723 | ### 6.1 应用待机分区改进
724 |
725 | App Standby Buckets 应用待机分区是 Android 9 引入的电池管理功能,系统会对应用的使用新近度和使用频率对应用进行排序,分别放置在不同的分区中。更活跃的应用会被分配到更高优先级的分区中,而低优先级的分区中应用的作业、闹钟或 FCM 会有一定限制。Android 12 系统引入了一个新的分区 —— “受限” 待机分区:
726 |
727 | - 活跃:目前正在使用,或者最近刚刚使用;
728 | - 工作集:定期使用;
729 | - 常用:经常使用,但不会每天使用;
730 | - 极少使用:不经常使用;
731 | - 受限:应用消耗大量资源,或表现出不良行为
732 | - 从未使用:已安装但从未运行过。
733 |
734 | 旧版本的待机分区只是根据应用的活跃度排序,而现在还有引入资源占用率的维度。**可以看出,这次改动是 Google 希望提高对消耗大量系统资源的应用的限制。**
735 |
736 | > 提示: 这些限制仅适用于设备使用电池供电的情况;在设备充电期间,系统不会对应用施加这些限制。
737 |
738 | 相关资料:[应用待机分区](https://developer.android.google.cn/topic/performance/appstandby#restricted-bucket "应用待机分区") —— 官方文档
739 |
740 | ---
741 |
742 | ## 7. 总结
743 |
744 | 关注我,带你了解更多,我们下次见。
745 |
746 | **以下变更相对冷门,实用价值较低,暂且按住不表:**
747 |
748 | - 行为变更 - Target 12 - 用户体验 - 大屏设备上的相机预览改进 & 富感反馈体验 & AppSearch & 游戏模式 & 近期网址共享(仅限 Pixel)
749 | - 行为变更:Target 12 - WebView 中的现代 SameSite Cookie & 备份和恢复 & 连接性 & 供应商 & 更新后的非 SDK 接口限制
750 | - 行为变更:所有应用 - 安全和隐私设置 - 权限软件包可见性 & 移除了 BouncyCastle 实现
751 | - 行为变更:所有应用 - 安全和隐私设置 -
752 | - 行为变更:所有应用 - 媒体 & 相机 & 图形和图片 & 连接性 & 更新后的非 SDK 接口限制
753 |
754 | ## 参考资料
755 |
756 | - [新版本系统适配: Android 12 中的兼容性变更](https://mp.weixin.qq.com/s/yk3FCuaU9LtmdM1uOQjOMQ) —— 官方文档
757 | - [Android 12 正式发布 | 开发者们的全新舞台](https://juejin.cn/post/7017745147345534983 "Android 12 正式发布 | 开发者们的全新舞台") —— 官方文档
758 | - [行为变更:所有应用](https://developer.android.google.cn/about/versions/12/behavior-changes-all#immersive-mode-improvements "行为变更:所有应用") —— 官方文档
759 | - [行为变更:以 Android 12 为目标平台的应用](https://developer.android.google.cn/about/versions/12/behavior-changes-12 "行为变更:以 Android 12 为目标平台的应用") —— 官方文档
760 | - [功能和 API 概览](https://developer.android.google.cn/about/versions/12/features "功能和 API 概览") —— 官方文档
761 |
762 | > 你的点赞对我意义重大!微信搜索公众号 [彭旭锐],希望大家可以一起讨论技术,找到志同道合的朋友,我们下次见!
763 |
764 |
--------------------------------------------------------------------------------
/Android 13/Android_13_DP2.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Android 13 开发者预览版从 2022 年 2 月正式启动,3 月份 Google 已经发布了第 2 个开发者预览版。目前更新的内容主要还是围绕隐私和安全这个主题,我们会持续跟进官方的 [发布计划表](https://developer.android.google.cn/about/versions/13/overview),最终版本预计在今年年底发布。
5 |
6 |
7 |
8 |
9 |
10 | ## Android 13 适配自查表(持续更新)
11 |
12 | 根据故障敏感性分级,我们将系统变更的兼容性划分为 3 个等级:
13 |
14 | - **强制适配❗:** 所有应用必须适配,否则会出现编译不通过、功能不可用或者用户体验受损等问题;
15 | - **推荐适配⭐:** 不强制要求适配,但适配的应用将获得更出色的用户体验或更安全的隐私保护等收益;
16 | - **已适配:** 应用不需要任何改动就已经兼容。
17 |
18 | ### **以 Android 13 为目标版本的应用**
19 |
20 | | 类别 | 变更 | 兼容性 | 摘要 |
21 | | --- | --- | :--- | --- |
22 | | 1. 用户体验 | 等待官方更新...... | / | / |
23 | | 2. 安全和隐私设置 | 附近 Wi-Fi 设备运行时权限(新) | 推荐⭐ | 引入了新运行时权限,可使应用扫描附近的 Wi-Fi 感知设备,而无需请求位置信息权限 |
24 | | | 后台访问身体传感器运行时权限(新) | 强制❗ | 引入了新的运行时权限, 用于更好地管理应用在后台时访问身体传感器的行为 |
25 | | | IntentFilter 会屏蔽不匹配的 Intent | 已适配 | 当该 Intent 与接收应用中的 匹配时,系统才会传送该 Intent |
26 | | | 更安全地动态注册广播接收器 | 强制❗ | 应用必须明确指出动态注册的广播接收器 是否接收其他应用的广播 |
27 | | 3. 性能和电池 | 等待更新... | / | / |
28 |
29 | ### **所有应用**
30 |
31 | | 类别 | 变更 | 兼容性 | 摘要 |
32 | | --- | --- | :--- | --- |
33 | | 4. 用户体验 | 多语言支持改进(新) | 推荐⭐ | 引入了一系列新的语言特性优化, 用于改善多语言用户体验 |
34 | | | 自适应主题的应用图标(新) | 推荐⭐ | 应用图标颜色可以自适应 Launcher 主题色调调整配色。 |
35 | | 5. 安全和隐私设置 | 通知运行时权限(新) | 强制❗ | 引入了新的运行时权限, 用于管理应用发送系统通知的能力 |
36 | | | 可降级权限(新) | 推荐⭐ | 应用可以主动撤销用户已授予的运行时权限 |
37 | | | 照片选择器(新) | 推荐⭐ | 用户可以只向应用提供特定选择的图片或视频, 而不是直接授予整个媒体库的访问权限 |
38 | | 6. 性能和电池 | 前台服务 FGS 管理器(新) | 已适配 | 引入了前台服务 FGS 管理器功能, 可以直接关闭服务和应用 |
39 | | | JobScheduler 预提取作业优化 | 已适配 | 系统会更智能地基于机器学习预测应用下次启动 的时间,并根据该估算值执行预提取作业 |
40 | | | 省电措施改进 | 已适配 | 引入了新的电池省电措施, 以便为系统提供更多方法来管理电池续航时间 |
41 |
42 | ---
43 |
44 | 第 1~3 节介绍的是以 Android 13 为目标版本的应用行为变更和新功能更新,我将这部分更新总结为 3 部分:
45 |
46 | - 1.用户体验(以 Android 13 为目标版本)
47 | - 2.安全和隐私设置(以 Android 13 为目标版本)
48 | - 3.性能和电池(以 Android 13 为目标版本)
49 |
50 | ## 1. 用户体验(以 Android 13 为目标版本)
51 |
52 | 等待官方更新......
53 |
54 | ## 2. 安全和隐私设置(以 Android 13 为目标版本)
55 |
56 | ### 2.1 附近 Wi-Fi 设备运行时权限(新功能)
57 |
58 | Android 13 系统引入了新的运行时权限 `android.permission.NEARBY_WIFI_DEVICES` 附近 Wi-Fi 设备权限,用于管理应用与附近 Wi-Fi 感知设备的连接。
59 |
60 | ```kotlin
61 |
62 |
63 |
64 | ...
65 |
66 |
67 | ```
68 |
69 | 在低版本中,应用与附近 Wi-Fi 设备连接需要用户授予 ACCESS_FINE_LOCATION 精确位置权限,这其实是不合理的设计,因为用户很难理解为什么 Wi-Fi 连接会跟位置信息有关。从 Android 13 系统开始,ACCESS_FINE_LOCATION 精确位置权限是可选项,只要应用不会通过 Wi-Fi 推导物理位置信息,就不需要再请求。如果不会,你需要在 Manifest 中显式做出 `usesPermissionFlags` 声明(这与声明蓝牙设备信息不会用于获取位置信息类似):
70 |
71 | ```kotlin
72 |
73 |
75 |
76 | ...
77 |
78 |
79 | ```
80 |
81 | 另外,NEARBY_WIFI_DEVICES 权限是 NEARBY_DEVICES 附近设备权限组的一部分。此权限组在 Android 12 中引入,还包含与蓝牙相关的权限。请求该权限组的权限,权限授予对话框会提示用户批准访问附近的设备。**可以看出,这次的改动 Google 是希望连接 Wi-Fi 设备的权限授予能够给用户更精准的权限功能描述。**
82 |
83 |
84 |
85 |
86 |
87 | 相关资料:[附近的 Wi-Fi 设备权限](https://developer.android.google.cn/about/versions/13/features/nearby-wifi-devices-permission)
88 |
89 | ### 2.2 后台访问身体传感器运行时权限(新功能)
90 |
91 | Android 13 系统引入了新的运行时权限 `android.permission.BODY_SENSORS_BACKGROUND` 后台身体传感器权限,用于更好地管理应用在后台时访问身体传感器(例如心率、体温和血氧饱和度等)的行为。现在应用在后台使用身体传感器,除了要请求现有的 BODY_SENSORS 权限外,还需要请求 BODY_SENSORS_BACKGROUND 权限(这与 ACCESS_FINE_LOCATION 和 ACCESS_BACKGROUND_LOCATION 的关系类似)。
92 |
93 | ### 2.3 IntentFilter 会屏蔽不匹配的 Intent
94 |
95 | 当您的应用向以 Android 13 或更高版本为目标平台的其他应用的导出组件发送 Intent 时,仅当该 Intent 与接收应用中的 `` 元素匹配时,系统才会传送该 intent。
96 |
97 | > **提示:** 因为我不理解这个特性的真正含义,所以这里直接复制粘贴了官方文档原话。你理解的话在评论里分享下。
98 | >
99 |
100 | ### 2.4 动态注册广播接收器改进
101 |
102 | 在旧版本中,应用动态注册的 BroadcastReceiver 广播接收器会接收到任何应用发送的广播(除非该接收器使用了应用签名权限保护),这会让动态注册的广播接收器存在安全风险。从 Android 13 系统开始,应用动态注册的广播接收器必须显式指出是否允许其他应用访问,即其他应用是否可以向其发送广播。否则,在动态注册时系统会抛出 SecurityException。
103 |
104 | ```kotlin
105 | // 这相当于静态注册 android:exported="true"
106 | context.registerReceiver(sharedBroadcastReceiver, intentFilter, RECEIVER_EXPORTED)
107 |
108 | // 这相当于静态注册 android:exported="false"
109 | context.registerReceiver(privateBroadcastReceiver, intentFilter, RECEIVER_NOT_EXPORTED)
110 | ```
111 |
112 | ## 3. 性能和电池(以 Android 13 为目标版本)
113 |
114 | 期待官方更新......
115 |
116 | ---
117 |
118 | 第 4~6 节介绍的是针对所有应用的应用行为变更和新功能更新,我将这部分更新总结为 3 部分:
119 |
120 | - 4.用户体验(所有应用)
121 | - 5.安全和隐私设置(所有应用)
122 | - 6.性能和电池(所有应用)
123 |
124 | ## 4. 用户体验(所有应用)
125 |
126 | ### 4.1 多语言支持改进(新功能)
127 |
128 | Android 13 系统引入了一系列新的语言特性优化,用以改进多语言用户的应用体验:
129 |
130 | - **应用级别语言偏好设置:** 在旧版本中,用户可以通过系统设置来全局切换语言。从 Android 13 开始,系统开始支持应用级别的语言偏好设置,可以在系统设置中针对每个应用设置,也可以在运行时使用以下 API 设置:
131 | - 平台 API:[LocaleManager#setApplicationLocales](https://developer.android.google.cn/reference/android/app/LocaleManager#setApplicationLocales(android.os.LocaleList))
132 | - 兼容库 API:[AppCompatDelegate#setApplicationLocales](https://developer.android.google.cn/reference/androidx/appcompat/app/AppCompatDelegate#setApplicationLocales(androidx.core.os.LocaleListCompat))
133 | - **改进日语文本换行:** 从 Android 13 系统开始,可以通过为 TextView 设置 [android:lineBreakWordStyle="phrase"](https://developer.android.google.cn/reference/android/R.attr#lineBreakWordStyle) 来改进日语文本的换行效果。TextView 会按照 Bunsetsu(最小自然语素单元)或短语,而不是单个字符来进行文本换行。例如,下图是启用了短语样式的日语文本换行(下方)和未启用短语样式的日语文本换行(上方)。
134 |
135 |
136 |
137 |
138 |
139 | - **改进非拉丁字母行高:** Android 13 通过使用适合每种语言的行高,改进了非拉丁文字(例如泰米尔语、缅甸语、泰卢固语和藏语)的显示,可防止字符被裁剪,这个改动需要以 Android 13 为目标版本。例如:
140 |
141 |
142 |
143 |
144 |
145 | ### 4.2 自适应主题的应用图标(新功能)
146 |
147 | Android 8 系统中引入了自适应图标,可以在不同厂商设备的 Launcher 上显示不同形状的应用图标。**如果说 Android 8 的图标是自适应形状的应用图标,那么 Android 13 就是在此基础上再推出了自适应主题的应用图标**。用户可以调节 Launcher 中的主题色调,应用图标颜色会自适应调整配色。要支持此功能,应用必须在原有的自适应图标 上增加一张单色图标,例如:
148 |
149 | `res/mipmap-anydpi-v26/ic_launcher.xml`
150 |
151 | ```kotlin
152 |
153 |
154 |
155 |
156 |
157 | ```
158 |
159 | 在 Manifest 文件中引用该图标,例如:
160 |
161 | ```kotlin
162 |
166 |
167 | ```
168 |
169 |
170 |
171 |
172 |
173 | ## 5. 安全和隐私设置(所有应用)
174 |
175 | ### 5.1 通知运行时权限(新功能)
176 |
177 | Android 13 系统引入了新的运行时权限 —— `android.permission.POST_NOTIFICATION` 通知权限,用于管理应用发送系统通知的能力。如果用户拒绝授予权限,则应用的所有通知渠道(Channel)都会别屏蔽,这类似于用户在系统设置中手动关闭应用通知后发生的行为。**可以看出,这次的改动 Google 是希望加强对应用通知行为的管理**,现在每个新安装的应用都会发一大堆通知,造成通知栏总是被一堆不重要的消息占满,用户只能一个个去关闭通知开关。
178 |
179 | ```kotlin
180 |
181 |
182 |
183 | ...
184 |
185 |
186 | ```
187 |
188 | 与其他运行时权限请求类似,请求通知权限也应该遵循最小必要原则。建议是在合适的业务流程节点或者用户体验峰值再请求,以便用户明确了解接收通知能带来的好处。例如:
189 |
190 |
191 |
192 |
193 |
194 | > **提示:** 通过调用 [areNotificationsEnabled()](https://developer.android.google.cn/reference/android/app/NotificationManager#areNotificationsEnabled()),可以判断用户是否已打开应用的通知开关。
195 | >
196 |
197 | 为了降低新权限的影响,从低版本升级到 Android 13 的设备上已安装的应用,系统会临时授予通知权限,前提是该应用本身是有通知的资格的:应用具有通知渠道,并且用户在低版本时并未关闭该应用的通知开关。
198 |
199 | - 以 Android 12 或更低版本为目标版本的应用:临时授权会一致有效,直到用户在通知权限授权对话框中明确关闭权限;
200 | - 以 Android 13 或更高版本为目标版本的应用:临时授权会持续到首次启动应用为止。
201 |
202 | 相关资料:
203 |
204 | - [通知运行时权限](https://developer.android.google.cn/about/versions/13/changes/notification-permission) —— 官方文档
205 | - [请求应用权限](https://developer.android.google.cn/training/permissions/requesting#handle-denial) —— 官方文档
206 |
207 | ### 5.2 **可降级权限(新功能)**
208 |
209 | 从 Android 13 系统开始,应用可以主动撤销用户已授予的运行时权限,这能够在不再需要权限后更好地保护用户隐私。通过调用 [revokeOwnPermissionsOnKill()](https://developer.android.google.cn/reference/android/content/Context#revokeOwnPermissionsonKill(java.util.Collection%3Cjava.lang.String%3E)) 可以撤销特定的权限或权限组。另外,撤销前台权限时,其对应的后台权限也会被撤销(例如 BODY_SENSORS & BODY_SENSORS_BACKGROUND)。
210 |
211 | ### 5.3 照片选择器(新功能)
212 |
213 | Android 13 系统引入了新的 [照片选择器](https://developer.android.google.cn/about/versions/13/features/photopicker) 功能,允许用户只向应用提供特定选择的图片或视频,而不是像旧版本那样直接授予整个媒体库的访问权限,这个功能与 IOS 14 “仅允许应用访问部分照片” 是类似的。图片选择器可以更好地保护用户隐私,并且应用不再需要请求媒体库运行时访问权限。
214 |
215 | ```kotlin
216 | 请求:
217 | val maxNumPhotosAndVideos = 10
218 | val intent = Intent(MediaStore.ACTION_PICK_IMAGES)
219 | // 设置获取的图片或视频最大数量
220 | intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxNumPhotosAndVideos)
221 | startActivityForResult(intent, PHOTO_PICKER_MULTI_SELECT_REQUEST_CODE)
222 | ```
223 |
224 | > 提示: 文件数量上限的最大数字存在平台限制 `MediaStore#getPickImagesMaxLimit()`。
225 | >
226 |
227 |
228 |
229 |
230 |
231 | 相关资料:[照片选择器](https://developer.android.google.cn/about/versions/13/features/photopicker)
232 |
233 | ## 6. 性能和电池(所有应用)
234 |
235 | ### 6.1 前台服务 FGS 管理器(新功能)
236 |
237 | Android 13 系统引入了前台服务 FGS 管理器功能,它会显示当前正在运行前台服务的应用列表,并且每个应用旁边都有一个 “停止” 按钮。当用户点击 “停止” 按钮时,系统不仅会关闭该前台服务,还会停止整个应用。例如:
238 |
239 |
240 |
241 |
242 |
243 | **可以看出,这次改动 Google 是希望提高用户对前台服务的控制性**。在旧版本的前台服务并没有直接的停止按钮,只有一些些友好的应用会在前台服务通知中使用可操作性的关闭按钮。
244 |
245 | 相关资料:[前台服务 (FGS) 任务管理器](https://developer.android.google.cn/about/versions/13/changes/fgs-manager)
246 |
247 | ### 6.2 JobScheduler 预提取作业优化
248 |
249 | JobScheduler 预提取作业是 Android 9 引入的机制,通过调用 [JobInfo.Builder.setPrefetch(true)](https://developer.android.google.cn/reference/android/app/job/JobInfo.Builder#setPrefetch(boolean)) 能够将该作业标记为 “预提取” 作业,理想情况下,开发者的预期是该作业应该在应用下一次启动前一点运行,以提升用户体验。
250 |
251 | 在旧版本中,系统只会在有充足的过剩资源时,才会允许预提取作业运行。从 Android 13 开始,系统会更智能地基于机器学习预测应用下次启动的时间,并根据该估算值执行预提取作业。此外,预提取任务也不再允许设置最后执行期限 [setOverrideDeadline(long)](https://developer.android.google.cn/reference/android/app/job/JobInfo.Builder#setOverrideDeadline(long))。
252 |
253 | ### 6.3 省电措施改进
254 |
255 | Android 13 系统引入了一些新的电池省电措施,以便为系统提供更多方法来管理电池续航时间。
256 |
257 | - **更新了应用进入 “受限” 待机分区的规则:** App Standby Buckets 应用待机分区是 Android 9 引入的电池管理功能,“受限” 待机分区是 Android 12 新增的待机分区,主要面向消耗大量系统资源的应用(目前有 “活跃、工作集、常用、极少使用、受限、从未使用” 等待机分区);
258 | - **更新了 “受限” 后台电池电量的新限制:** 后台电量限制是 Android 9 引入的电池管理功能,能够让用户调整应用处于后台运行时可以执行的工作量(目前有 “无限制、优化(默认)、受限” 等选项);
259 | - **新增一个电量提醒系统通知:** Android 13 引入了一个新的系统通知,当应用在 24 小时内消耗了大量电池电量时会显示;
260 | - **新增一个前台服务提醒系统通知:** Android 13 引入了一个新的系统通知,当应用的某项前台服务在 24 小时内至少运行了 20 小时时会显示;
261 |
262 | 相关资料:[电池资源利用率](https://developer.android.google.cn/about/versions/13/changes/battery#system-notification-long-running-fgs)
263 |
264 | **以下变更相对冷门,实用价值较低,本文暂且按住不表:**
265 |
266 | 新功能 - 用户体验 - 快捷磁贴放置 API
267 |
268 | 新功能 - 用户体验 - 多语言用户 - 文本转换 API & Unicode 库更新
269 |
270 | 新功能 - 用户体验 - 更快断字 & 彩色矢量字体 & 蓝牙 LE 音频 & MIDI 2.0
271 |
272 | 新功能 - 隐私安全 - APK 签名 v3.1
273 |
274 | 新功能 - 图形 - 可编程的着色器
275 |
276 | 新功能 - 核心功能 - OpenJDK 11 更新
277 |
--------------------------------------------------------------------------------
/Android 13/images/Android 13 计划时间轴.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Android 13/images/tmp:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [2022] [Peng Xurui]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | ## 使用方法
37 |
38 | **1、先给一个 Star:** 你的支持对我非常重要,我的内容质量绝对对得起你的 Star,给我一点创作的动力,感谢。
39 |
40 | **2、进小彭的 Android 交流群:** 加我微信进群,我们对群质量有要求,你可以在这里找到志同道合的朋友。群里可以讨论技术、分享文章、聊天、吐槽,允许适当发招聘广告,不受欢迎的行为是严格禁止的:
41 |
42 | **3、关注我的公众号 [彭旭锐]:** 坚持高质量原创内容,不人云亦云,公众号后续是我主要的内容更新平台:
43 |
44 | **4、关注我的 [掘金](https://juejin.cn/user/1063982987230392)、[知乎](https://www.zhihu.com/people/pengxurui) 和 [《AndroidFamily》](https://github.com/pengxurui/AndroidFamily) 专栏:** 掘金上有我历史发布过的所有文章。
45 |
46 | ## 1. Android 系统适配的现状
47 |
48 | 从 2008 年 9 月 23 日,Android 的第一个版本 Android 1.0 发布。到 2021 年 10 月 4 日,Android 12 正式版发布。不知不觉,Android 操作系统已经走过了十几个年头了,系统的发布周期也从最初的几年缩短到稳定的一年。
49 |
50 | 很多同学表示很难跟上系统的更新步伐:“我还没用上 Android 10,Android 12 已经更新了!”。对于版本适配也是抱着能拖就拖的态度。为什么会出现这个状况呢,我想原因是多方面的:
51 |
52 | - **1、工作指标:** 目标对人生和团队都具有巨大的导向作用,大多数情况下,新版本适配并不被认为是重要紧急的工作目标。就算是拖到不能再拖了,有些同学也只是把工作标准定为 “测试没发现问题”,草草了事;
53 |
54 | - **2、系统变更碎片化:** 新版本发布时,虽然官方的 Release 文档会列举出这个版本相关的新功能和行为变更,但是它不会告诉你哪些变更是兼容的,哪些变更又要求强制适配。有些频繁更新的功能模块甚至需要关联多个文档才能理解清楚;
55 |
56 | - **3、官方文档不易理解:** 首先官方文档在翻译时信息传递就有损失,再加上官方文档大多是陈述行为变更本身,对变更背后的原理、安全考量或设计理念少有涉及,导致开发者看得一头雾水。这也是我们倾向于通过博客文章获取知识的主要原因;
57 |
58 | - **4、浮躁焦虑的心态:** 浮躁和焦虑似乎成了一个普遍的现象,开发者宁愿把时间投入到音视频、Flutter、Framework 这些听起来更牛逼的事情上。新系统年年都有,这个性价比不高。
59 |
60 | 这样看来,新版本适配的前景看起来不明朗了。但是,对于想成为一名高级的 Android 开发工程师 / 移动开发工程师的你,我希望你明白这也是个机会:
61 |
62 | - **1、行业愈发成熟规范:** 如今的移动开发正处在挤泡沫的阶段,初级的招聘量在减少,但中高级的招聘量在增加,这说明整个行业在区域成熟规范。只要你具备足够的能力,你的薪资也会水涨船高;
63 |
64 | - **2、全面能力:** 移动开发已经不再是当年单兵作战的时代,只 “做好” 产品需求已经远远不够了。你不仅需要掌握 Android 本身的知识,还需要全链路的知识扩展,比如产品思维、设计规范、市场运营、数据分析、后端等。如果你已经不是刚工作的小白,但是你却很少了解到这些知识,建议你思考下自己是不是处于舒适区。在这个立场下,系统兼容性就是你全面能力中的一环,你的功能在不同系统下是否兼容,你的技术方案有没有考虑过不同系统的差异,你对 Android 系统有多了解,这些都是你可以体现差异化价值的地方(当然你钻研于技术层面的某一个点,把这个点做到极致也是市场的);
65 |
66 | - **3、别人在焦虑,你在行动:** 焦虑不能解决任何问题,与其把时间花在抱怨上,不如把时间花在解决问题上。
67 |
68 | ## 2. 我们在做的事
69 |
70 | 我们希望站在开发者的视角,全面且深刻地解读每个 Android 版本更新,以此建立起一个体系化的 Android 系统适配手册。具体包括:
71 |
72 | ### 2.1 两个维度
73 |
74 | 根据内容相关度,我们将从 2 个维度解读:
75 |
76 | - **基于时间线:** 现阶段官方每年会发布一个新的版本,因此有必要以一个 Android 版本为单位,解读该版本涉及的新功能与行为变更。这样可以帮助开发同学了解新版本的更新内容,例如我们会通过一个文档解读 Android 13 版本的更新内容与适配自查表;
77 |
78 | - **基于内容线:** 通常一个系统功能模块会历经多个系统版本更新才会趋于稳定,因此有必要以一个功能为单位,解读该功能的主要能力以及不同版本的变更和差异。这样可以帮助开发同学了解该功能在不同版本上的差异,例如我们会通过一个文档单独解读系统通知。
79 |
80 | ### 2.2 三个等级
81 |
82 | 根据故障敏感性分级,我们将系统变更的兼容性划分为 3 个等级:
83 |
84 | - **强制适配❗:** 所有应用必须适配,否则会出现编译不通过、功能不可用或者用户体验受损等问题;
85 |
86 | - **推荐适配⭐:** 不强制要求适配,但适配的应用将获得更出色的用户体验或更安全的隐私保护等收益;
87 |
88 | - **已适配:** 应用不需要任何改动就已经兼容。
89 |
90 | ### 2.3 两类行为变更
91 |
92 | 系统行为变更通常属于以下两种类别之一:
93 |
94 | - **面对所有应用的行为变更:** 运行在该系统版本上的所有应用都会影响,而无论应用的 targetSDKVersion 为何。通常应该先针对这些变更进行适配和测试,这有助于用户在新版本系统上运行你的应用时,用户体验不会受损;
95 |
96 | - **以特定 targetSDKVersion 为目标版本的行为变更:** 只有 targetSDKVersion 高于或等于系统版本的应用会影响,通常是影响较大或适配工作量较大的变更,我们可以理解为一个 Google 留给开发者的适配缓冲。由于受 targetSDKVersion 控制的行为变更较多,你在适配新版系统时,可以利用下面提到的 “兼容性调试框架” 逐项启用,而不是修改 targetSDKVersion 一次性启用所有变更。
97 |
98 | ## 3. 系统适配手册
99 |
100 | | 平台版本 | API Level | 官方文档 | 适配手册 |
101 | | --- | --- | --- | --- |
102 | | Android 13 | TIRAMISU | https://developer.android.google.cn/about/versions/13 https://developer.android.com/about/versions/13 | [Android_13_DP2](https://github.com/pengxurui/AndroidPlatformWiki/blob/main/Android%2013/Android_13_DP2.md)|
103 | | Android 12L | S_V2(32) | https://developer.android.google.cn/about/versions/12/12L https://developer.android.com/about/versions/12/12L | / |
104 | | Android 12 | S(31) | https://developer.android.google.cn/about/versions/12 https://developer.android.com/about/versions/12 | [Android_12_API_31_S](https://github.com/pengxurui/AndroidPlatformWiki/blob/main/Android%2012/Android_12_API_31_S.md)|
105 | | Android 11 | R(30) | https://developer.android.google.cn/about/versions/11 https://developer.android.com/about/versions/11 | |
106 | | Android 10 | Q(29) | https://developer.android.google.cn/about/versions/10 https://developer.android.com/about/versions/10 | |
107 | | Android 9 | P(28) | https://developer.android.google.cn/about/versions/pie https://developer.android.com/about/versions/pie | |
108 | | Android 8.1 | O_MR1(27) | https://developer.android.google.cn/about/versions/oreo/android-8.1 https://developer.android.com/about/versions/oreo/android-8.1 | |
109 | | Android 8.0 | O(26) | https://developer.android.google.cn/about/versions/oreo https://developer.android.com/about/versions/oreo | |
110 | | Android 7.1/7.1.1 | N_MR1(25) | https://developer.android.google.cn/about/versions/nougat/android-7.1 https://developer.android.com/about/versions/nougat/android-7.1 | |
111 | | Android 7.0 | N(24) | https://developer.android.google.cn/about/versions/nougat https://developer.android.com/about/versions/nougat | |
112 | | Android 6.0 | M(23) | https://developer.android.google.cn/about/versions/marshmallow https://developer.android.com/about/versions/marshmallow | |
113 | | Android 5.1 | LOLLIPOP_MR1(22) | https://developer.android.google.cn/about/versions/android-5.1 https://developer.android.com/about/versions/lollipop/android-5.1 | |
114 | | Android 5.0 | LOLLIPOP(21) | https://developer.android.google.cn/about/versions/lollipop https://developer.android.com/about/versions/lollipop | |
115 | | Android 4.4W | KITKAT_WATCH(20) | KitKat for Wearables Only | |
116 | | Android 4.4 | KITKAT(19) | https://developer.android.google.cn/about/versions/kitkat https://developer.android.com/about/versions/kitkat | |
117 | | Android 4.3 | JELLY_BEAN_MR2(18) | / | |
118 | | Android 4.2/4.2.2 | JELLY_BEAN_MR1(17) | / | |
119 |
120 | ## 4. 最新 Android 版本
121 |
122 | ### Android 13 开发者预览版 2
123 |
124 | 
125 |
126 | Android 13 开发者预览版从 2022 年 2 月正式启动,3 月份 Google 已经发布了第 2 个开发者预览版。目前更新的内容主要还是围绕隐私和安全这个主题,我们会持续跟进官方的 [发布计划表](https://developer.android.google.cn/about/versions/13/overview),最终版本预计在今年年底发布。
127 |
128 |
129 |
130 |
131 |
132 | ### 以 Android 13 为目标版本的应用
133 |
134 | | 类别 | 变更 | 兼容性 | 摘要 |
135 | | --- | --- | :--- | --- |
136 | | 1. 用户体验 | 等待官方更新...... | / | / |
137 | | 2. 安全和隐私设置 | 附近 Wi-Fi 设备运行时权限(新) | 推荐⭐ | 引入了新运行时权限,可使应用扫描附近的 Wi-Fi 感知设备,而无需请求位置信息权限 |
138 | | | 后台访问身体传感器运行时权限(新) | 强制❗ | 引入了新的运行时权限, 用于更好地管理应用在后台时访问身体传感器的行为 |
139 | | | IntentFilter 会屏蔽不匹配的 Intent | 已适配 | 当该 Intent 与接收应用中的 匹配时,系统才会传送该 Intent |
140 | | | 更安全地动态注册广播接收器 | 强制❗ | 应用必须明确指出动态注册的广播接收器 是否接收其他应用的广播 |
141 | | 3. 性能和电池 | 等待更新... | / | / |
142 |
143 | ### 所有应用
144 |
145 | | 类别 | 变更 | 兼容性 | 描述 |
146 | | --- | --- | :--- | --- |
147 | | 4. 用户体验 | 多语言支持改进(新) | 推荐⭐ | 引入了一系列新的语言特性优化, 用于改善多语言用户体验 |
148 | | | 自适应主题的应用图标(新) | 推荐⭐ | 应用图标颜色可以自适应 Launcher 主题色调调整配色。 |
149 | | 5. 安全和隐私设置 | 通知运行时权限(新) | 强制❗ | 引入了新的运行时权限, 用于管理应用发送系统通知的能力 |
150 | | | 可降级权限(新) | 推荐⭐ | 应用可以主动撤销用户已授予的运行时权限 |
151 | | | 照片选择器(新) | 推荐⭐ | 用户可以只向应用提供特定选择的图片或视频, 而不是直接授予整个媒体库的访问权限 |
152 | | 6. 性能和电池 | 前台服务 FGS 管理器(新) | 已适配 | 引入了前台服务 FGS 管理器功能, 可以直接关闭服务和应用 |
153 | | | JobScheduler 预提取作业优化 | 已适配 | 系统会更智能地基于机器学习预测应用下次启动 的时间,并根据该估算值执行预提取作业 |
154 | | | 省电措施改进 | 已适配 | 引入了新的电池省电措施, 以便为系统提供更多方法来管理电池续航时间 |
155 |
156 | 完整文档:[Android_13_API_33_T](https://github.com/pengxurui/AndroidPlatformWiki/blob/main/Android%2013/Android_13_API_33_T.md)
157 |
158 | ## 5. 兼容性调试框架
159 |
160 | Android 11 引入了一个新的开发者调试工具,能够帮助开发者更加灵活可控地适配新版系统。在此之前,当我们需要适配以特定 Android 系统版本为目标版本的行为变更时,我们需要先做以下操作:
161 |
162 | - 1、修改项目 targetSDKVersion,指向特定的 Android 系统版本;
163 | - 2、适配所有行为变更,或者至少适配影响编译运行的行为变更;
164 | - 3、重新编译构建应用,并安装到调试设备上。
165 |
166 | 这意味着你不仅需要重新编译应用,而且至少需要适配多个会影响编译运行的行为变更,这对适配问题比较多的应用就不太友好了。而使用应用兼容性调试框架,你可以在不升级 targetSDKVersion 的情况下,单独针对某一个行为变更进行适配。
167 |
168 | 兼容性调试框架支持通过开发者选项或 adb 命令启用或停用各项变更:
169 |
170 | - **使用开发者选项启用或停用变更:** 先启用开发者选项后,在系统设置中搜索 `应用兼容性变更`,从列表中选择调试的应用,再从变更列表中找到各项变更。例如:
171 |
172 |
173 |
174 |
175 |
176 | - **使用 adb 命令启用或停用变更:** 直接执行 adb 命令,模板如下:
177 | ```
178 | adb shell am compat enable (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME
179 | adb shell am compat disable (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME
180 | ```
181 | 其中 PACKAGE_NAME 是应用包名,CHANGE_ID 或 CHANGE_NAME 是兼容性框架为每个变更定义的唯一标识,你可以在各个版本的官方文档中找到完整的变更列表:
182 |
183 | - [Android 11(API 级别 30)](https://developer.android.google.cn/about/versions/11/reference/compat-framework-changes)
184 | - [Android 12(API 级别 31 和 32)](https://developer.android.google.cn/about/versions/12/reference/compat-framework-changes)
185 | - [Android 13(开发者预览版)](https://developer.android.google.cn/about/versions/13/reference/compat-framework-changes)
186 |
187 | 相关文档:[兼容性框架工具](https://developer.android.google.cn/guide/app-compatibility/test-debug)
188 |
189 | ## 共同成长
190 |
191 | - 欢迎提 Issue 帮助修复缺陷;
192 | - 欢迎提 Pull Request 增加新的 Feature,让 AndroidPlatforms 变得更加强大,你的 ID 会出现在 Contributors 中;
193 | - 欢迎加 [作者微信](https://github.com/pengxurui/AndroidFamily/blob/master/images/%E4%B8%AA%E4%BA%BA%E5%BE%AE%E4%BF%A1.jpeg) 与作者交流,欢迎加入交流群找到志同道合的伙伴。
194 |
195 | ## 小彭的其它开源项目
196 |
197 | - [AndroidFamily](https://github.com/pengxurui/AndroidFamily) 【Android 面经 + Android 学习指南】一份面向 Android 开发者的成长和进阶的学习路线;🔥
198 | - [EasyTrack](https://github.com/pengxurui/EasyTrack) 基于西瓜视频前端视图树埋点方案实现的埋点方案;
199 | - [EasyPrivacy](https://github.com/pengxurui/EasyPrivacy) 一个帮助开发者快速解决整改问题的工具;
200 | - [LeetCode-Kotlin](https://github.com/pengxurui/LeetCode-Kotlin) LeetCode 高频题解 - Kotlin 版本。
201 |
202 | 更多内容,请 [点击](https://juejin.cn/user/1063982987230392)
203 |
204 | ## Donate
205 |
206 | 如果本仓库对你有帮助,可以请小彭喝杯速溶咖啡。
207 |
208 | 
209 |
210 | ## License
211 |
212 | Copyright [2022] [Peng Xurui]
213 |
214 | Licensed under the Apache License, Version 2.0 (the "License");
215 | you may not use this file except in compliance with the License.
216 | You may obtain a copy of the License at
217 |
218 | [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
219 |
220 | Unless required by applicable law or agreed to in writing, software
221 | distributed under the License is distributed on an "AS IS" BASIS,
222 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
223 | See the License for the specific language governing permissions and
224 | limitations under the License.
225 |
--------------------------------------------------------------------------------
/platforms/Android_12_API_31_S:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/platforms/Android_13_API_32_T:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------