API 级别:21
除了新功能和新特性之外,Android 5.0 还包含各种系统变更和 API 行为变更。本文档重点介绍了您应了解并在应用中考虑的一些关键变更。
如果您之前发布过 Android 应用,请注意,您的应用可能会受到 Android 5.0 中的这些变更的影响。
如需简要了解新平台功能,请改为参阅 Android Lollipop 亮点。
视频
Android Runtime (ART)
在 Android 5.0 中,ART 运行时取代了 Dalvik 成为平台默认运行时。ART 运行时在 Android 4.4 中以实验性方式引入。
如需简要了解 ART 的新功能,请参阅 ART 简介。部分主要的新功能包括:
- 预先 (AOT) 编译
- 改进的垃圾回收 (GC)
- 改进的调试支持
大多数 Android 应用在 ART 下应该可以直接运行,而无需进行任何更改。不过,Dalvik 采用的一些技术并不适用于 ART。有关最重要问题的信息,请参阅在 Android 运行时 (ART) 上验证应用行为。如存在以下情况,应特别注意:
- 您的应用使用 Java 原生接口 (JNI) 运行 C/C++ 代码。
- 您使用会生成非标准代码的开发工具(例如某些混淆工具)。
- 您使用的技术与压缩式垃圾回收不兼容。
通知
请确保您的通知考虑到这些 Android 5.0 变更。如需详细了解如何针对 Android 5.0 及更高版本设计通知,请参阅通知设计指南。
Material Design 样式
通知采用深色文本绘制在白色(或非常浅色)背景上,以匹配新的 Material Design 微件。确保您的所有通知在采用新配色方案后看起来都正常。如果通知看起来有误,请进行修正:
- 使用
setColor()
在图标图片后面设置圆形强调色。 - 更新或移除涉及颜色的素材资源。系统会忽略操作图标和主通知图标中的所有非 Alpha 通道。您应假定这些图标将仅限 Alpha 版。系统会以白色绘制通知图标,以深灰色绘制操作图标。
提示音和振动
如果您目前使用 Ringtone
、MediaPlayer
或 Vibrator
类向通知添加提示音和振动,请移除此代码,以便系统能够在优先模式下正确显示通知。请改用 Notification.Builder
方法添加声音和振动。
将设备设置为 RINGER_MODE_SILENT
会导致设备进入新的优先级模式。如果您将设备设置为 RINGER_MODE_NORMAL
或 RINGER_MODE_VIBRATE
,设备将退出优先模式。
以前,Android 使用 STREAM_MUSIC
作为主音频流来控制平板电脑设备上的音量。在 Android 5.0 中,手机和平板电脑设备的主音量串流现在已统一,并由 STREAM_RING
或 STREAM_NOTIFICATION
控制。
锁定屏幕可见性
默认情况下,Android 5.0 中的通知现在会显示在用户的锁定屏幕上。
用户可以选择保护敏感信息,以免其泄露,在这种情况下,系统会自动隐去通知中显示的文本。如需自定义此隐去部分信息的通知,请使用 setPublicVersion()
。
如果通知不包含个人信息,或者您想允许对通知进行媒体播放控制,请调用 setVisibility()
方法并将通知的可见性级别设置为 VISIBILITY_PUBLIC
。
媒体播放
如果您要实现用于显示媒体播放状态或传输控件的通知,请考虑使用新的 Notification.MediaStyle
模板,而不是自定义 RemoteViews.RemoteView
对象。无论您选择哪种方法,请务必将通知的可见性设置为 VISIBILITY_PUBLIC
,以便用户能够在锁定屏幕上访问您的控件。请注意,从 Android 5.0 开始,系统不再在锁定屏幕上显示 RemoteControlClient
对象。如需了解详情,请参阅如果您的应用使用 RemoteControlClient。
提醒式通知
现在,当设备处于活动状态(即设备处于解锁状态且屏幕处于开启状态)时,通知可能会显示在一个小浮动窗口(也称为“即时通知”)中。这些通知的显示方式与通知的紧凑形式类似,但浮动通知还会显示操作按钮。用户无需离开当前应用,即可执行操作或关闭浮动通知。
可能触发浮动通知的条件示例包括:
- 用户的 activity 处于全屏模式(应用使用
fullScreenIntent
) - 通知具有较高的优先级并使用铃声或振动
如果您的应用在任何上述场景下实现通知,请确保正确显示浮动通知。
媒体控件和 RemoteControlClient
RemoteControlClient
类现已废弃。请尽快改用新的 MediaSession
API。
Android 5.0 中的锁定屏幕不会显示 MediaSession
或 RemoteControlClient
的传输控件。不过,您的应用可以通过通知在锁定屏幕上提供媒体播放控制功能。这样一来,您的应用便可以更好地控制媒体按钮的呈现方式,同时为用户提供在锁定和解锁状态下一致的体验。
Android 5.0 为此引入了新的 Notification.MediaStyle
模板。Notification.MediaStyle
会将您使用 Notification.Builder.addAction()
添加的通知操作转换为嵌入在应用的媒体播放通知中的紧凑按钮。将您的会话令牌传递给 setSession()
方法,以告知系统此通知用于控制正在进行的媒体会话。
请务必将通知的可见性设置为 VISIBILITY_PUBLIC
,以标记通知可在任何锁定屏幕(安全或非安全)上安全显示。如需了解详情,请参阅锁屏通知。
如需在应用在 Android TV 或 Wear 平台上运行时显示媒体播放控件,请实现 MediaSession
类。如果您的应用需要在 Android 设备上接收媒体按钮事件,您还应实现 MediaSession
。
getRecentTasks()
随着 Android 5.0 中引入新的并发文档和 activity 任务功能(请参阅下文中的最近用过的应用屏幕中的并发文档和 activity),ActivityManager.getRecentTasks()
方法现已废弃,以更好地保护用户隐私。为了实现向后兼容,此方法仍会返回其数据的一小部分,包括调用应用自己的任务,以及可能还有一些其他非敏感任务(例如“家庭”)。如果您的应用使用此方法检索自己的任务,请改用 getAppTasks()
检索该信息。
Android NDK 中的 64 位支持
Android 5.0 引入了对 64 位系统的支持。64 位增强功能可增加地址空间并提升性能,同时仍完全支持现有的 32 位应用。64 位支持还提高了 OpenSSL 在加密方面的性能。此外,此版本还引入了新的原生媒体 NDK API,以及原生 OpenGL ES (GLES) 3.1 支持。
如需使用 Android 5.0 中提供的 64 位支持,请从 Android NDK 页面下载并安装 NDK 修订版 10c。如需详细了解 NDK 的重要变更和 bug 修复,请参阅修订版 10c 的版本说明。
绑定到服务
Context.bindService()
方法现在需要显式 Intent
,如果传入隐式 intent,则会抛出异常。为确保应用安全无虞,请在启动或绑定 Service
时使用显式 intent,并且不要为该服务声明 intent 过滤器。
WebView
Android 5.0 更改了应用的默认行为。
- 如果您的应用以 API 级别 21 或更高版本为目标平台:
- 系统会默认屏蔽混合内容和第三方 Cookie。如需允许混合内容和第三方 Cookie,请分别使用
setMixedContentMode()
和setAcceptThirdPartyCookies()
方法。 - 现在,系统会智能地选择要绘制的 HTML 文档部分。这种新的默认行为有助于减少内存占用量并提高性能。如果您想一次性渲染整个文档,请调用
enableSlowWholeDocumentDraw()
来停用此优化。
- 系统会默认屏蔽混合内容和第三方 Cookie。如需允许混合内容和第三方 Cookie,请分别使用
- 如果您的应用以低于 21 的 API 级别为目标平台:系统允许混合内容和第三方 Cookie,并且始终一次性呈现整个文档。
自定义权限唯一性要求
如权限概览中所述,Android 应用可以定义自定义权限,以便以专有方式管理对组件的访问,而无需使用平台的预定义系统权限。应用在其清单文件中声明的
<permission>
元素中定义自定义权限。
在少数情况下,定义自定义权限是一种合法且安全的方法。不过,创建自定义权限有时是不必要的,甚至可能会给应用带来潜在风险,具体取决于分配给权限的保护级别。
Android 5.0 进行了一项行为变更,以确保只有一个应用可以定义给定自定义权限,除非该应用使用与定义该权限的其他应用相同的密钥进行签名。
使用重复自定义权限的应用
任何应用都可以定义所需的任何自定义权限,因此可能会出现多个应用定义相同的自定义权限的情况。例如,如果两个应用提供类似的功能,它们可能会为自定义权限派生相同的逻辑名称。应用可能还会纳入本身包含相同自定义权限定义的常用公共库或代码示例。
在 Android 4.4 及更低版本中,用户可以在给定设备上安装多个此类应用,但系统会分配第一个安装的应用指定的保护级别。
从 Android 5.0 开始,系统会对使用不同密钥签名的应用强制执行一项新的自定义权限唯一性限制。现在,设备上只有一个应用可以定义给定自定义权限(由其名称决定),除非定义该权限的其他应用使用相同的密钥进行签名。如果用户尝试安装具有重复自定义权限且未使用定义该权限的常驻应用所用的密钥进行签名的应用,系统会阻止安装。
应用注意事项
在 Android 5.0 及更高版本中,应用可以继续像以前一样定义自己的自定义权限,并通过 <uses-permission>
机制向其他应用请求自定义权限。不过,鉴于 Android 5.0 中引入了新要求,您应仔细评估对应用的可能影响。
请注意以下几点:
- 您的应用是否在清单中声明了任何
<permission>
元素?如果是,这些权限对于应用或服务的正常运行是否确实必不可少?或者,您可以改用系统默认权限吗? - 如果您的应用中有
<permission>
元素,您知道它们的来源吗? - 您是否真的打算允许其他应用通过
<uses-permission>
请求您的自定义权限? - 您的应用中是否使用了包含
<permission>
元素的样板代码或示例代码?这些权限元素是否真的必要? - 您的自定义权限的名称是否简单明了,或者是否基于其他应用可能共享的通用字词?
新安装和更新
如上所述,在搭载 Android 4.4 或更低版本的设备上,应用的新安装和更新不会受到影响,行为也不会发生变化。对于在搭载 Android 5.0 或更高版本的设备上进行的新安装和更新,如果应用定义了现有常驻应用已定义的自定义权限,系统会阻止安装您的应用。
已安装 Android 5.0 系统更新
如果您的应用使用自定义权限且已广泛分发和安装,那么当用户将其设备更新到 Android 5.0 时,该应用可能会受到影响。安装系统更新后,系统会重新验证已安装的应用,包括检查其自定义权限。如果您的应用定义的自定义权限已由其他已验证的应用定义,并且您的应用未使用与该应用相同的密钥进行签名,系统不会重新安装您的应用。
建议
对于搭载 Android 5.0 或更高版本的设备,我们建议您立即检查应用,进行必要的调整,并尽快向用户发布更新后的版本。
- 如果您在应用中使用自定义权限,请考虑其来源以及您是否实际需要这些权限。从应用中移除所有
<permission>
元素,除非您确定应用正常运行需要这些元素。 - 请尽可能将自定义权限替换为系统默认权限。
- 如果您的应用需要自定义权限,请重命名自定义权限,使其具有应用专有的唯一性,例如将其附加到应用的完整软件包名称后面。
- 如果您有一套使用不同密钥签名的应用,并且这些应用通过自定义权限访问共享组件,请确保在共享组件中仅定义一次自定义权限。使用共享组件的应用不应自行定义自定义权限,而应通过
<uses-permission>
机制请求访问权限。 - 如果您有一套使用同一密钥签名的应用,则每个应用都可以根据需要定义相同的自定义权限,系统会允许以常规方式安装这些应用。
TLS/SSL 默认配置变更
Android 5.0 引入了更改,更改了应用针对 HTTPS 和其他 TLS/SSL 流量使用的默认 TLS/SSL 配置:
- TLSv1.2 和 TLSv1.1 协议现已启用,
- AES-GCM (AEAD) 加密套件现已启用,
- MD5、3DES、导出和静态密钥 ECDH 加密套件现已停用,
- 首选使用 Forward Secrecy 加密套件(ECDHE 和 DHE)。
在下列少数情况下,这些更改可能会导致 HTTPS 或 TLS/SSL 连接中断。
请注意,Google Play 服务中的安全 ProviderInstaller 已在 Android 2.3 及更低版本的 Android 平台版本中提供这些更改。
服务器不支持任何已启用的加密套件
例如,服务器可能仅支持 3DES 或 MD5 加密套件。首选解决方法是改进服务器的配置,以启用更强大、更现代的加密套件和协议。理想情况下,应启用 TLSv1.2 和 AES-GCM,并启用正向加密套件 (ECDHE、DHE) 并将其作为首选。
另一种方法是修改应用以使用自定义 SSLSocketFactory 与服务器通信。该工厂应设计为创建 SSLSocket 实例,除了默认加密套件之外,这些实例还启用了服务器所需的部分加密套件。
应用对用于连接到服务器的加密套件做出了错误的假设
例如,某些应用包含自定义 X509TrustManager,但该自定义 X509TrustManager 会因预期 authType 参数为 RSA 但遇到 ECDHE_RSA 或 DHE_RSA 而发生故障。
服务器不支持 TLSv1.1、TLSv1.2 或新的 TLS 扩展
例如,与服务器的 TLS/SSL 握手被错误地拒绝或暂停。首选解决方法是升级服务器以符合 TLS/SSL 协议。这将使服务器成功协商这些较新的协议,或协商 TLSv1 或更低版本的协议,并忽略它不理解的 TLS 扩展。在某些情况下,在服务器上停用 TLSv1.1 和 TLSv1.2 可能会作为权宜之计,直到服务器软件升级为止。
另一种方法是修改应用以使用自定义 SSLSocketFactory 与服务器通信。工厂应设计为仅启用服务器正确支持的协议,以创建 SSLSocket 实例。
支持托管配置文件
设备管理员可以向设备添加受管理的个人资料。此资料归管理员所有,可让管理员控制受管理的资料,同时让用户的个人资料及其存储空间由用户控制。 此更改可能会通过以下方式影响现有应用的行为。
处理 Intent
设备管理员可以限制受管理个人资料中的应用对于系统应用的访问。在这种情况下,如果应用从受管理资料中触发通常由该应用处理的 intent,并且受管理资料中没有适用于该 intent 的处理脚本,则该 intent 会导致异常。例如,设备管理员可以限制受管理个人资料中的应用访问系统的相机应用。如果您的应用在受管理个人资料中运行并针对 MediaStore.ACTION_IMAGE_CAPTURE
调用 startActivityForResult()
,而受管理个人资料中没有任何应用可以处理 intent,则会导致 ActivityNotFoundException
。
您可以通过在触发任何 intent 之前检查是否至少有一个处理程序来防止这种情况。如需检查是否有有效的处理脚本,请调用 Intent.resolveActivity()
。如需查看相关示例,请参阅轻松拍照:使用相机应用拍照。
在各个配置文件中共享文件
每个个人资料都有自己的文件存储空间。由于文件 URI 是指文件存储空间中的特定位置,这意味着在一个个人资料中有效的文件 URI 在另一个个人资料中无效。这通常不会对应用造成问题,因为应用通常只会访问自己创建的文件。但是,如果应用将文件附加到 intent,则附加文件 URI 并不安全,因为在某些情况下,intent 可能会在其他资料中处理。例如,设备管理员可以指定图片拍摄事件应由个人资料中的相机应用处理。如果 intent 由受管理个人资料中的应用触发,相机需要能够将图片写入受管理个人资料的应用可以读取的位置。
为安全起见,当您需要将文件附加到可能从一个配置文件跨越到另一个配置文件的 intent 时,应为文件创建并使用内容 URI。如需详细了解如何使用内容 URI 共享文件,请参阅共享文件。例如,设备管理员可以允许个人资料中的相机处理 ACTION_IMAGE_CAPTURE
。触发 intent 的 EXTRA_OUTPUT
应包含一个内容 URI,用于指定照片应存储在何处。相机应用可以将图片写入该 URI 指定的位置,而触发 intent 的应用将能够读取该文件,即使该应用位于其他资料中也是如此。
已移除锁定屏幕小部件支持
Android 5.0 移除了对锁定屏幕 widget 的支持;它继续支持主屏幕上的 widget。