Android 5.0 行为变更

API 等级:21

Android 5.0 除了提供新功能和新能力外,还包含各种系统变更和 API 行为变更。本文档重点介绍了一些关键变更,您应了解这些变更并在应用中予以考虑。

如果您之前发布过 Android 应用,请注意您的应用可能会受到这些 Android 5.0 变更的影响。

如需了解新平台功能的概览,请参阅 Android Lollipop 亮点

视频

Dev Byte:Android 5.0 的新增功能

Dev Byte:通知

Android 运行时 (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 通道。系统使用白色绘制通知图标,使用深灰色绘制操作图标。

声音和振动

如果您目前正在通过使用 RingtoneMediaPlayerVibrator 类向通知添加声音和振动,请移除此代码,以便系统可以在 *优先级* 模式下正确显示通知。改为使用 Notification.Builder 方法添加声音和振动。

将设备设置为 RINGER_MODE_SILENT 会使设备进入新的优先级模式。如果您将其设置为 RINGER_MODE_NORMALRINGER_MODE_VIBRATE,则设备将退出优先级模式。

之前,Android 使用 STREAM_MUSIC 作为平板设备的主音量流来控制音量。在 Android 5.0 中,手机和平板设备的主音量流现在已统一,并由 STREAM_RINGSTREAM_NOTIFICATION 控制。

锁屏可见性

默认情况下,在 Android 5.0 中,通知现在会显示在用户的锁屏上。用户可以选择保护敏感信息不被泄露,在这种情况下,系统会自动屏蔽通知显示的文本。要自定义此屏蔽的通知,请使用 setPublicVersion()

如果通知不包含个人信息,或者您想允许在通知上进行媒体播放控制,请调用 setVisibility() 方法并将通知的可见性级别设置为 VISIBILITY_PUBLIC

媒体播放

如果您正在实现显示媒体播放状态或传输控件的通知,请考虑使用新的 Notification.MediaStyle 模板,而不是自定义的 RemoteViews.RemoteView 对象。无论您选择哪种方法,请确保将通知的可见性设置为 VISIBILITY_PUBLIC,以便可以从锁屏访问您的控件。请注意,从 Android 5.0 开始,系统不再在锁屏上显示 RemoteControlClient 对象。更多信息,请参见 如果您的应用使用 RemoteControlClient

悬浮式通知

当设备处于活动状态(即设备已解锁且屏幕已开启)时,通知现在可能会显示在一个小的浮动窗口中(也称为悬浮式通知)。这些通知与您通知的紧凑形式类似,不同之处在于悬浮式通知还会显示操作按钮。用户无需离开当前应用即可操作或关闭悬浮式通知。

可能触发悬浮式通知的条件示例包括:

  • 用户的活动处于全屏模式(应用使用 fullScreenIntent
  • 通知具有高优先级并使用铃声或振动

如果您的应用在任何这些场景下实现通知,请确保正确显示悬浮式通知。

媒体控件和 RemoteControlClient

RemoteControlClient 类现已弃用。请尽快切换到新的 MediaSession API。

Android 5.0 的锁屏不会显示您的 MediaSessionRemoteControlClient 的传输控件。相反,您的应用可以通过通知在锁屏上提供媒体播放控制。这使您的应用可以更好地控制媒体按钮的显示,同时为锁定和解锁设备上的用户提供一致的体验。

Android 5.0 引入了一个新的 Notification.MediaStyle 模板用于此目的。Notification.MediaStyle 将您使用 Notification.Builder.addAction() 添加的通知操作转换为嵌入在您的应用媒体播放通知中的紧凑型按钮。将您的会话令牌传递给 setSession() 方法,以告知系统此通知控制正在进行的媒体会话。

请确保将通知的可见性设置为 VISIBILITY_PUBLIC,以将通知标记为可在任何锁屏(安全或非安全)上显示。更多信息,请参见 锁屏通知

如果您的应用在 Android TVWear 平台上运行,要显示媒体播放控件,请实现 MediaSession 类。如果您的应用需要在 Android 设备上接收媒体按钮事件,也应实现 MediaSession

getRecentTasks()

随着 Android 5.0 中新的 *并发文档和活动任务* 功能的引入(请参见下面的 近期屏幕中的并发文档和活动),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 Revision 10c。有关 NDK 的重要更改和错误修复的更多信息,请参阅 Revision 10c 的 发行说明

绑定到服务

Context.bindService() 方法现在需要一个显式的 Intent,如果给定一个隐式意图,则会抛出异常。为了确保您的应用安全,请在启动或绑定您的 Service 时使用显式意图,并且不要为服务声明意图过滤器。

WebView

Android 5.0 更改了您的应用的默认行为。

  • 如果您的应用的目标 API 级别为 21 或更高
  • **如果您的应用的目标 API 级别低于 21:**系统允许混合内容和第三方 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 密码套件。
  • 首选前向保密密码套件(ECDHE 和 DHE)。

在少数情况下(如下所示),这些更改可能会导致 HTTPS 或 TLS/SSL 连接中断。

请注意,来自 Google Play 服务的安全 ProviderInstaller 已经为 Android 2.3 及更高版本的 Android 平台提供了这些更改。

服务器不支持任何启用的密码套件

例如,服务器可能只支持 3DES 或 MD5 密码套件。首选的解决方法是改进服务器的配置,以启用更强大和更现代的密码套件和协议。理想情况下,应启用 TLSv1.2 和 AES-GCM,并且应启用并首选前向保密密码套件(ECDHE、DHE)。

另一种方法是修改应用以使用自定义 SSLSocketFactory 与服务器通信。该工厂应设计为创建 SSLSocket 实例,这些实例除了默认密码套件之外还启用了服务器所需的一些密码套件。

应用对用于连接到服务器的密码套件做出了错误的假设

例如,某些应用包含一个自定义 X509TrustManager,因为它会因预期 authType 参数为 RSA 但遇到 ECDHE_RSA 或 DHE_RSA 而中断。

服务器无法容忍 TLSv1.1、TLSv1.2 或新的 TLS 扩展

例如,与服务器的 TLS/SSL 握手被错误地拒绝或停滞。首选的解决方法是升级服务器以符合 TLS/SSL 协议。这将使服务器成功协商这些较新的协议或协商 TLSv1 或较旧的协议,并忽略它不理解的 TLS 扩展。在某些情况下,在服务器软件升级之前,禁用服务器上的 TLSv1.1 和 TLSv1.2 可以作为权宜之计。

另一种方法是修改应用以使用自定义 SSLSocketFactory 与服务器通信。该工厂应设计为创建 SSLSocket 实例,这些实例仅启用了服务器正确支持的协议。

对托管配置文件的支持

设备管理员可以向设备添加托管配置文件。此配置文件由管理员拥有,使管理员可以控制托管配置文件,同时将用户的个人配置文件及其存储空间保留在用户的控制之下。此更改可能会影响现有应用的行为,方式如下。

处理意图

设备管理员可以限制从托管配置文件访问系统应用程序。在这种情况下,如果应用从托管配置文件触发一个通常由该应用程序处理的意图,并且托管配置文件上没有合适的意图处理程序,则该意图会导致异常。例如,设备管理员可以限制托管配置文件上的应用访问系统的相机应用程序。如果您的应用正在托管配置文件上运行并调用startActivityForResult() 用于MediaStore.ACTION_IMAGE_CAPTURE,并且托管配置文件上没有可以处理该意图的应用,则会导致ActivityNotFoundException

您可以通过在触发意图之前检查是否有至少一个处理程序来防止这种情况。要检查有效的处理程序,请调用Intent.resolveActivity()。您可以在简单拍摄照片:使用相机应用拍摄照片中看到此操作的示例。

跨配置文件共享文件

每个配置文件都有自己的文件存储。由于文件 URI 指的是文件存储中的特定位置,这意味着在一个配置文件上有效的文件 URI 在另一个配置文件上无效。对于通常只访问其创建的文件的应用来说,这通常不是问题。但是,如果应用将文件附加到意图,则附加文件 URI 不安全,因为在某些情况下,意图可能在另一个配置文件上处理。例如,设备管理员可能会指定应由个人配置文件上的相机应用处理图像捕获事件。如果意图由托管配置文件上的应用触发,则相机需要能够将图像写入托管配置文件的应用可以读取的位置。

为安全起见,当您需要将文件附加到可能跨越一个配置文件到另一个配置文件的意图时,您应该为该文件创建并使用内容 URI。有关使用内容 URI 共享文件的更多信息,请参阅共享文件。例如,设备管理员可能会允许ACTION_IMAGE_CAPTURE 由个人配置文件中的相机处理。触发意图的EXTRA_OUTPUT 应包含一个内容 URI,指定应将照片存储在何处。相机应用可以将图像写入该 URI 指定的位置,并且触发意图的应用能够读取该文件,即使该应用位于另一个配置文件中也是如此。

锁屏小部件支持已移除

Android 5.0 移除了对锁屏小部件的支持;它继续支持主屏幕上的小部件。