blob: 3c4b2e1e7338a1fc8493c9e6927c44da9c73b10b (
plain)
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
|
page.title=行为变更
page.keywords=preview,sdk,compatibility
meta.tags="预览版", "兼容性"
page.tags="preview", "developer preview"
page.image=images/cards/card-n-changes_2x.png
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>本文内容</h2>
<ol>
<li><a href="#perf">性能提升</a>
<ol>
<li><a href="#doze">打盹</a></li>
<li><a href="#bg-opt">后台优化</a></li>
</ol>
</li>
<li><a href="#perm">权限更改</a></li>
<li><a href="#accessibility">辅助工具改进</a>
<ol>
<li><a href="#screen-zoom">屏幕缩放</a></li>
<li><a href="#vision-settings">设置向导中的视觉设置</a></li>
</ol>
</li>
<li><a href="#ndk">NDK 应用链接至平台库</a></li>
<li><a href="#afw">Android for Work</a></li>
</ol>
<h2>另请参阅</h2>
<ol>
<li><a href="{@docRoot}preview/api-overview.html">
Android N API 概览</a></li>
</ol>
</div>
</div>
<p>
Android N 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更。本文重点介绍您应该了解并在开发应用时加以考虑的一些重要变更。
</p>
<p>
如果您之前发布过 Android 应用,请注意您的应用可能受到这些平台变更的影响。
</p>
<h2 id="perf">性能提升</h2>
<p>
为延长设备的电池寿命、降低内存使用率以及提升应用性能,Android N 对系统行为做出了一些变更。这些变更可能会影响系统资源和系统通知对应用的可用性。您应仔细检查这些变更并评估应用可能需要做何调整以适应这些变更。
</p>
<h3 id="doze">打盹</h3>
<p>
Android 6.0(API 级别 23)引入了打盹模式,当用户设备未插接电源、处于静止状态且屏幕关闭时,该模式会推迟 CPU 和网络活动,从而延长电池寿命。而 Android N 则通过在设备未插接电源且屏幕关闭状态下、但不一定要处于静止状态(例如用户外出时把手持式设备装在口袋里)时应用部分 CPU 和网络限制,进一步增强了打盹模式。
</p>
<img src="{@docRoot}preview/images/doze-diagram-1.png" alt="" height="251px" id="figure1" />
<p class="img-caption">
<strong>图 1.</strong> 打盹模式如何应用第一级系统活动限制以延长电池寿命的图示。
</p>
<p>
当设备处于充电状态且屏幕已关闭一定时间后,设备会进入打盹模式并应用第一部分限制:关闭应用网络访问、推迟作业和同步。如果进入打盹模式后设备处于静止状态达到一定时间,系统则会对 {@link android.os.PowerManager.WakeLock}、{@link android.app.AlarmManager} 闹铃、GPS 和 Wi-Fi 扫描应用余下的打盹限制。无论是应用部分还是全部打盹限制,系统都会唤醒设备以提供简短的维护时间窗口,在此窗口期间,应用程序可以访问网络并执行任何被推迟的作业/同步。
</p>
<img src="{@docRoot}preview/images/doze-diagram-2.png" alt="" id="figure2" />
<p class="img-caption">
<strong>图 2.</strong> 打盹模式如何在设备处于静止状态达到一定时间后应用第二级系统活动限制的图示。
</p>
<p>
请注意,激活屏幕或插接设备电源时,系统将退出打盹模式并取消这些处理限制。此项新增的行为不会影响有关使您的应用适应 Android 6.0(API 级别 23)中所推出的旧版本打盹模式的建议和最佳实践,如<a href="{@docRoot}training/monitoring-device-state/doze-standby.html">打盹和应用待机优化</a>中所讨论。您仍应遵循这些建议(例如使用 Google Cloud Messaging (GCM) 发送和接收消息)并开始安排更新计划以适应新增的打盹行为。
</p>
<h3 id="bg-opt">Project Svelte:后台优化</h3>
<p>
Android N 删除了三项隐式广播,以帮助优化内存使用和电量消耗。此项变更很有必要,因为隐式广播会在后台频繁启动已注册侦听这些广播的应用。删除这些广播可以显著提升设备性能和用户体验。
</p>
<p>
移动设备会经历频繁的连接变更,例如在 Wi-Fi 和移动数据之间切换时。目前,可以通过在应用清单文件中注册一个接收器来侦听隐式 {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION} 广播,让应用能够监控这些变更。由于很多应用会注册接收此广播,因此单次网络切换即会导致所有应用被唤醒并同时处理此广播。
</p>
<p>
同理,应用可以注册接收来自其他应用(例如相机)的隐式 {@link
android.hardware.Camera#ACTION_NEW_PICTURE} 和 {@link
android.hardware.Camera#ACTION_NEW_VIDEO} 广播。当用户使用相机应用拍摄照片时,这些应用即会被唤醒以处理广播。
</p>
<p>
为减缓这些问题,Android N 应用了以下优化措施:
</p>
<ul>
<li>面向 Android N 开发的应用不会收到 {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION} 广播,即使它们已有清单条目来请求接受这些事件的通知。在前台运行的应用如果使用 {@link
android.content.BroadcastReceiver} 请求接收通知,则仍可以在主线程中侦听 {@code CONNECTIVITY_CHANGE}。
</li>
<li>应用无法发送或接收 {@link
android.hardware.Camera#ACTION_NEW_PICTURE} 或 {@link
android.hardware.Camera#ACTION_NEW_VIDEO} 广播。此项优化会影响所有应用,而不仅仅是面向 Android N 的应用。
</li>
</ul>
<p>
未来的 Android 版本还可能会弃用其他隐式广播以及未绑定的后台服务。有鉴于此,您应避免依赖在清单文件中声明的接收器来侦听隐式广播或删除此依赖关系,以及避免或删除对后台服务的依赖关系。
</p>
<p>
Android 框架提供多种解决方案来降低这些隐式广播或后台服务的必要性。例如,{@link
android.app.job.JobScheduler} API 提供了一个稳健可靠的机制来安排满足指定条件(例如连入不按流量计费的网络)时所执行的网络操作。您甚至可以使用 {@link
android.app.job.JobScheduler} 来响应内容提供程序所发生的变更。
</p>
<p>
如需了解有关此行为变更及如何改写应用的详细信息,请参阅<a href="{@docRoot}preview/features/background-optimization.html">后台优化</a>。
</p>
<h2 id="perm">权限更改</h2>
<p>
Android N 做了一些权限更改,包括用户帐户权限和向外部存储设备写入信息的新权限,这些更改可能会影响您的应用。下面概要列出了预览版中已发生更改的权限。
</p>
<ul>
<li>{@code GET_ACCOUNTS}(已弃用)
<p>
GET_ACCOUNTS 权限现已弃用。对于面向 Android N 的应用,系统将忽略此权限。
</p>
</li>
</ul>
<h2 id="accessibility">辅助工具改进</h2>
<p>
为提高平台对于视力不佳或视力受损用户的可用性,Android N 做出了一些更改。这些更改一般并不要求更改您的应用代码,不过您应仔细检查并使用您的应用测试这些功能,以评估它们对用户体验的潜在影响。
</p>
<h3 id="screen-zoom">屏幕缩放</h3>
<p>
Android N 支持用户设置<strong>显示尺寸</strong>,以放大或缩小屏幕上的所有元素,从而提升设备对视力不佳用户的可访问性。用户无法将屏幕缩放至低于最小屏幕宽度<a href="http://developer.android.com/guide/topics/resources/providing-resources.html">
sw320dp</a>,该宽度是 Nexus 4 的宽度,也是常规中等大小手机的宽度。
</p>
<div class="cols">
<div class="col-6">
<img src="{@docRoot}preview/images/screen-zoom-1.png" alt="" height="XXX" id="figure1" />
</div>
<div class="col-6">
<img src="{@docRoot}preview/images/screen-zoom-2.png" alt="" height="XXX" id="figure1" />
</div>
</div> <!-- end cols -->
<p class="img-caption">
<strong>图 3.</strong> 右侧屏幕显示的是一台运行 Android N 系统映像的设备增大显示尺寸后的效果。
</p>
<p>
当设备密度发生更改时,系统会以如下方式通知正在运行的应用:
</p>
<ul>
<li>如果是面向 API 级别 23 或更低版本系统的应用,则系统会自动终止其所有后台进程。这意味着如果用户切换离开此类应用,转而打开 <em>Settings</em> 屏幕并更改 <strong>Display size</strong> 设置,则系统会像处理内存不足的情况一样终止该应用。如果应用具有任何前台进程,则系统会如<a href="{@docRoot}guide/topics/resources/runtime-changes.html">处理运行时变更</a>中所述将配置变更通知给这些进程,就像对待设备屏幕方向变更一样。
</li>
<li>如果是面向 Android N 的应用,则其所有进程(前台和后台)都会收到有关配置变更的通知,如<a href="{@docRoot}guide/topics/resources/runtime-changes.html">处理运行时变更</a>中所述。
</li>
</ul>
<p>
大多数应用并不需要进行任何更改即可支持此功能,不过前提是这些应用遵循 Android 最佳实践。具体要检查的事项:
</p>
<ul>
<li>在屏幕宽度为 <code><a href=
"{@docRoot}guide/topics/resources/providing-resources.html">sw320dp</a></code> 的设备上测试您的应用,并确保其充分运行。
</li>
<li>当设备配置发生变更时,更新任何与密度相关的缓存信息,例如缓存位图或从网络加载的资源。当应用从暂停状态恢复运行时,检查配置变更。
<p class="note">
<strong>注:</strong>如果您要缓存与配置相关的数据,则最好也包括相关元数据,例如该数据对应的屏幕尺寸或像素密度。保存这些元数据便于您在配置变更后决定是否需要刷新缓存数据。
</p>
</li>
<li>避免用像素单位指定尺寸,因为像素不会随屏幕密度缩放。应改为使用<a href="{@docRoot}guide/practices/screens_support.html">与密度无关像素</a> (<code>dp</code>) 单位指定尺寸。
</li>
</ul>
<h3 id="vision-settings">设置向导中的视觉设置</h3>
<p>
Android N 在“Welcome”屏幕中加入了“Vision Settings”,用户可以在新设备上设置以下辅助工具设置:<strong>Magnification gesture</strong>、<strong>Font size</strong>、<strong>Display size</strong> 和 <strong>TalkBack</strong>。此项变更增强了与不同屏幕设置相关的错误的可见性。要评估此功能的影响,您应在启用这些设置的状态下测试应用。您可以在 <strong>Settings >
Accessibility</strong> 中找到这些设置。
</p>
<h2 id="ndk">NDK 应用链接至平台库</h2>
<p>
Android N 做了一些命名空间更改,以阻止加载非公开 API。如果您使用 NDK,则只能使用 Android 平台提供的公开 API。在下一个官方发布的 Android 版本上使用非公开 API 会导致应用崩溃。
</p>
<p>
为提醒您使用了非公开 API,在 Android N
设备上运行的应用会在有应用调用非公开 API 时在日志消息输出中生成一个错误。此错误还会作为消息显示在设备屏幕上,以帮助增强您对此情况的认识。您应检查应用代码以删除使用非公开平台 API,并使用预览版设备或模拟器全面测试应用。
</p>
<p>
如果您的应用依赖平台库,则请参见 NDK 文档,了解使用公开 API 等效项替换普通私有 API 的典型修复。您还可以链接至平台库,而无需实现此应用,如果应用使用的库是平台的一部分(例如 <code>libpng</code>),但不属于 NDK,则更可如此。此情况下,请确保您的 APK 包含您打算链接到的所有 .so 文件。
</p>
<p class="caution">
<strong>注意:</strong>有些第三方库可能会链接至非公开 API。如果您的应用使用这些库,那么当您的应用在下一个官方发布的 Android 版本上运行时可能会出现崩溃现象。
</p>
<p>
应用不应依赖或使用不属于 NDK 的原生库,因为这些库可能会发生更改或从一个 Android 版本迁移至另一版本。例如,从 OpenSSL 切换至 BoringSSL 即属于此类更改。此外,不同的设备可能提供不同级别的兼容性,因为不属于 NDK 中的平台库没有兼容性要求。如果您必须在较旧设备上访问非 NDK 库,则请依据 Android API 级别进行加载。
</p>
<p>
为帮助您诊断此类问题,下面列举了一些在您试图使用 Android N 开发应用时可能遇到的 Java 和 NDK 错误:
</p>
<p>Java 错误示例:</p>
<pre class="no-pretty-print">
java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so"
is not accessible for the namespace "classloader-namespace"
</pre>
<p>NDK 错误示例:</p>
<pre class="no-pretty-print">
dlopen failed: cannot locate symbol "__system_property_get" referenced by ...
</pre>
<p>
以下是遇到这类错误的应用的一些典型修复:
</p>
<ul>
<li>可以使用标准 JNI 函数来替代使用 libandroid_runtime.so 中的 getJavaVM 和 getJNIEnv:
<pre class="no-pretty-print">
AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
JavaVM::AttachCurrentThread from <jni.h>.
</pre>
</li>
<li>可以使用公开备选项 {@code __system_property_get} 来替代使用 {@code libcutils.so} 中的 {@code property_get} 符号。如需这样做,请使用 {@code __system_property_get} 及以下 include 函数:
<pre>
#include <sys/system_properties.h>
</pre>
</li>
<li>应使用应用本地版本来替代使用 {@code libcrypto.so} 中的 {@code SSL_ctrl} 符号。例如,您应在 {@code .so} 文件中静态链接 {@code libcyrpto.a},或者在应用中包含您自己的来自 BoringSSL 或 OpenSSL 的动态 {@code libcrypto.so}。
</li>
</ul>
<h2 id="afw">Android for Work</h2>
<p>
Android N 包含一些针对面向 Android for Work 的应用的变更,包括对证书安装、密码重置、二级用户管理、设备标识符访问权限的变更。如果您是要针对 Android for Work 环境开发应用,则应仔细检查这些变更并相应地修改您的应用。
</p>
<ul>
<li>您必须先安装授权证书安装程序,然后 DPC 才能对其进行设置。对于面向 N SDK 的配置文件和设备所有者应用,您应在设备策略控制器 (DPC) 调用 <code>DevicePolicyManager.setCertInstallerPackage()</code> 之前安装授权证书安装程序。如果尚未安装此安装程序,则系统会引发 <code>IllegalArgumentException</code>。
</li>
<li>针对设备管理员的重置密码限制现在也适用于配置文件所有者。设备管理员无法再使用
<code>DevicePolicyManager.resetPassword()</code> 来清除或更改已经设置的密码。不过,设备管理员仍可以设置密码,但只能在设备没有密码、PIN 或图案时这样做。
</li>
<li>即使设置了限制,设备所有者和配置文件所有者仍可以管理帐户。而且,即使具有 <code>DISALLOW_MODIFY_ACCOUNTS</code> 用户限制,设备所有者和配置文件所有者仍可调用 Account Management API。
</li>
<li>设备所有者可以更轻松地管理二级用户。当设备在设备所有者模式下运行时,系统将自动设置 <code>DISALLOW_ADD_USER</code> 限制。这样可以防止用户创建非托管二级用户。此外,<code>CreateUser()</code> 和
<code>createAndInitial()</code> 方法已弃用,取而代之的是 <code>DevicePolicyManager.createAndManageUser()</code> 方法。
</li>
<li>设备所有者可以访问设备标识符。设备所有者可以使用
<code>DevicePolicyManagewr.getWifiMacAddress()</code> 访问设备的 Wi-Fi MAC 地址。如果设备上从未启用 Wi-Fi,则此方法将返回一个 {@code null} 值。
</li>
</ul>
<p>
如需了解有关 Android N 中针对 Android for Work 所做变更的详细信息,请参阅
<a href="{@docRoot}preview/features/afw.html">Android for Work 更新</a>。
</p>
<h2 id="other">其他重要说明</h2>
<ul>
<li>如果一个应用在 Android N 上运行,但却是针对更低 API 级别开发的,那么在用户更改显示尺寸时,系统将终止此应用进程。因此,应用必须能够正常处理此情景。否则,当用户从最近使用记录中恢复运行应用时,应用将会出现崩溃现象。
<p>
您应测试应用以确保不会发生此行为。要进行此测试,您可以通过 DDMS 手动终止应用,以造成相同的崩溃现象。
</p>
<p>
在密度发生更改时,系统不会自动终止面向 N 及更高版本的应用;不过,这些应用仍可能对配置变更做出不良响应。
</p>
</li>
<li>
Android N 上的应用应能够正常处理配置变更,并且在后续启动时不会出现崩溃现象。您可以通过更改字体大小 (<strong>Setting</strong> >
<strong>Display</strong> > <strong>Font size</strong>) 并随后从最近使用记录中恢复运行应用,来验证应用行为。
</li>
</ul>
|