Android 6.0 更新

Android 6.0(API 级别 23)除了提供新的功能和特性外,还包含各种系统变更和 API 行为变更。本文件重点介绍您应该了解并在应用中考虑的一些关键变更。

如果您之前已发布 Android 应用,请注意平台中的这些变更会影响您的应用。

运行时权限

此版本引入了一种新的权限模型,用户现在可以在运行时直接管理应用权限。此模型使用户能够更好地了解和控制权限,同时简化了应用开发人员的安装和自动更新流程。用户可以分别为已安装的应用授予或撤销权限。

对于目标 Android 6.0(API 级别 23)或更高版本的应用,请确保在运行时检查并请求权限。要确定您的应用是否已获得权限,请调用新的 checkSelfPermission() 方法。要请求权限,请调用新的 requestPermissions() 方法。即使您的应用并非以 Android 6.0(API 级别 23)为目标,也应该在新权限模型下测试您的应用。

有关在应用中支持新权限模型的详细信息,请参阅 使用系统权限。有关如何评估对应用的影响的提示,请参阅 权限使用说明

Doze 模式和应用待机

此版本引入了针对空闲设备和应用的新节电优化功能。这些功能会影响所有应用,因此请确保在这些新模式下测试您的应用。

  • **Doze 模式**: 如果用户拔下设备电源并在一段时间内将其静置,屏幕关闭,则设备将进入 *Doze* 模式,在此模式下,它会尝试使系统保持睡眠状态。在此模式下,设备会定期恢复正常运行很短的时间,以便可以进行应用同步,并且系统可以执行任何挂起的操作。
  • **应用待机**: 应用待机允许系统在用户未主动使用应用时确定应用处于空闲状态。当用户在一段时间内未触碰应用时,系统会做出此判断。如果设备已拔下电源,则系统会禁用网络访问并暂停其认为处于空闲状态的应用的同步和作业。

要了解有关这些节电更改的更多信息,请参阅 针对 Doze 模式和应用待机进行优化

移除 Apache HTTP 客户端

Android 6.0 版本移除了对 Apache HTTP 客户端的支持。如果您的应用正在使用此客户端且目标为 Android 2.3(API 级别 9)或更高版本,请改用 HttpURLConnection 类。此 API 效率更高,因为它通过透明压缩和响应缓存减少了网络使用,并最大限度地减少了功耗。要继续使用 Apache HTTP API,您必须首先在 build.gradle 文件中声明以下编译时依赖项

android {
    useLibrary 'org.apache.http.legacy'
}

BoringSSL

Android 正在从 OpenSSL 迁移到 BoringSSL 库。如果您的应用中使用了 Android NDK,请不要链接到 NDK API 之外的加密库,例如 libcrypto.solibssl.so。这些库不是公共 API,并且在不同版本和设备之间可能会发生更改或中断,恕不另行通知。此外,您还可能会面临安全漏洞。相反,请修改您的原生代码以通过 JNI 调用 Java 加密 API,或静态链接到您选择的加密库。

访问硬件标识符

为了增强用户数据保护,从本版本开始,Android 将移除应用使用 Wi-Fi 和蓝牙 API 获取设备本地硬件标识符的编程访问权限。WifiInfo.getMacAddress()BluetoothAdapter.getAddress() 方法现在将返回常量值 02:00:00:00:00:00

要通过蓝牙和 Wi-Fi 扫描访问附近外部设备的硬件标识符,您的应用现在必须具有 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 权限。

注意:当运行 Android 6.0(API 级别 23)的设备启动后台 Wi-Fi 或蓝牙扫描时,该操作对于外部设备来说,源自随机 MAC 地址。

通知

本版本移除了 Notification.setLatestEventInfo() 方法。请改用 Notification.Builder 类来构建通知。要反复更新通知,请重复使用 Notification.Builder 实例。调用 build() 方法以获取更新的 Notification 实例。

adb shell dumpsys notification 命令不再打印您的通知文本。请改用 adb shell dumpsys notification --noredact 命令来打印通知对象中的文本。

AudioManager 更改

不再支持通过 AudioManager 类直接设置音量或静音特定流。setStreamSolo() 方法已弃用,您应该改用 requestAudioFocus() 方法。类似地,setStreamMute() 方法已弃用;请改用 adjustStreamVolume() 方法并传入方向值 ADJUST_MUTEADJUST_UNMUTE

文本选择

Screen showing new text selection features within a floating toolbar

当用户在您的应用中选择文本时,您现在可以在 浮动工具栏 中显示文本选择操作,例如“剪切”、“复制”和“粘贴”。用户交互实现类似于上下文操作栏的实现,如 为各个视图启用上下文操作模式 中所述。

要为文本选择实现浮动工具栏,请在现有应用中进行以下更改。

  1. 在您的 ViewActivity 对象中,将您的 ActionMode 调用从 startActionMode(Callback) 更改为 startActionMode(Callback, ActionMode.TYPE_FLOATING)
  2. 获取您现有的 ActionMode.Callback 实现,并使其扩展 ActionMode.Callback2
  3. 覆盖 onGetContentRect() 方法以提供视图中内容 Rect 对象(例如文本选择矩形)的坐标。
  4. 如果矩形定位不再有效,并且这是唯一需要无效化的元素,请调用 invalidateContentRect() 方法。

如果您使用的是 Android 支持库 修订版 22.2,请注意,浮动工具栏不向后兼容,并且 appcompat 默认情况下会控制 ActionMode 对象。这将阻止显示浮动工具栏。要在 AppCompatActivity 中启用 ActionMode 支持,请调用 getDelegate(),然后在返回的 AppCompatDelegate 对象上调用 setHandleNativeActionModesEnabled() 并将输入参数设置为 false。此调用将 ActionMode 对象的控制权返回给框架。在运行 Android 6.0(API 级别 23)的设备上,这允许框架支持 ActionBar 或浮动工具栏模式,而在运行 Android 5.1(API 级别 22)或更低版本的设备上,仅支持 ActionBar 模式。

浏览器书签更改

本版本移除了对全局书签的支持。android.provider.Browser.getAllBookmarks()android.provider.Browser.saveBookmark() 方法现已移除。同样,READ_HISTORY_BOOKMARKSWRITE_HISTORY_BOOKMARKS 权限也已移除。如果您的应用的目标 Android 版本为 Android 6.0(API 级别 23)或更高版本,请不要访问全局提供程序中的书签或使用书签权限。相反,您的应用应在内部存储书签数据。

Android 密钥库更改

在本版本中,Android 密钥库提供程序 不再支持 DSA。ECDSA 仍然受支持。

不需要加密存储的密钥在禁用或重置安全锁屏时将不再被删除(例如,由用户或设备管理员删除)。需要加密存储的密钥在这些事件期间将被删除。

Wi-Fi 和网络更改

本版本引入了对 Wi-Fi 和网络 API 的以下行为更改。

  • 只有在您创建了这些 WifiConfiguration 对象的情况下,您的应用才能更改其状态。您无权修改或删除用户或其他应用创建的 WifiConfiguration 对象。
  • 以前,如果应用使用 enableNetwork()disableAllOthers=true 设置强制设备连接到特定的 Wi-Fi 网络,则设备将断开与其他网络(例如蜂窝数据)的连接。在本版本中,设备将不再断开与这些其他网络的连接。如果您的应用的 targetSdkVersion“20” 或更低版本,则它将固定到所选 Wi-Fi 网络。如果您的应用的 targetSdkVersion“21” 或更高版本,请使用多网络 API(例如 openConnection()bindSocket() 和新的 bindProcessToNetwork() 方法)以确保其网络流量通过所选网络发送。

相机服务更改

在本版本中,访问相机服务中共享资源的模型已从之前的“先到先得”访问模型更改为优先考虑高优先级进程的访问模型。服务行为的更改包括:

  • 对相机子系统资源(包括打开和配置相机设备)的访问是根据客户端应用程序进程的“优先级”授予的。具有用户可见或前台活动的应用程序进程通常会获得更高的优先级,从而使相机资源的获取和使用更加可靠。
  • 当高优先级应用程序尝试使用相机时,低优先级应用的活动相机客户端可能会被“逐出”。在已弃用的 Camera API 中,这会导致为被逐出的客户端调用 onError()。在 Camera2 API 中,这会导致为被逐出的客户端调用 onDisconnected()
  • 在具有适当相机硬件的设备上,单独的应用程序进程能够独立地同时打开和使用单独的相机设备。但是,相机服务现在会检测到并禁止多进程用例,在这种用例中,同时访问会导致任何打开的相机设备的性能或功能严重下降。此更改可能会导致低优先级客户端被“逐出”,即使没有其他应用直接尝试访问同一相机设备也是如此。
  • 更改当前用户会导致先前用户帐户拥有的应用中的活动相机客户端被逐出。对相机的访问仅限于当前设备用户拥有的用户配置文件。实际上,这意味着例如,“访客”帐户在用户切换到其他帐户后,将无法保留使用相机子系统的运行进程。

运行时

ART 运行时现在正确地实现了 newInstance() 方法的访问规则。此更改修复了 Dalvik 在以前版本中不正确地检查访问规则的问题。如果您的应用使用 newInstance() 方法并且您想要覆盖访问检查,请使用输入参数设置为 true 来调用 setAccessible() 方法。如果您的应用使用 v7 appcompat 库v7 recyclerview 库,则必须更新您的应用以使用这些库的最新版本。否则,请确保从 XML 引用 的任何自定义类都已更新,以便其类构造函数可访问。

本版本更新了动态链接器的行为。动态链接器现在理解库的 soname 与其路径之间的区别(公共错误 6670),并且现在已实现按 soname 搜索。以前有效的但具有错误 DT_NEEDED 条目(通常是构建机器文件系统上的绝对路径)的应用在加载时可能会失败。

dlopen(3) RTLD_LOCAL 标志现在已正确实现。请注意,RTLD_LOCAL 是默认值,因此对 dlopen(3) 的调用没有显式使用 RTLD_LOCAL 将受到影响(除非您的应用显式使用了 RTLD_GLOBAL)。使用 RTLD_LOCAL,符号将不会提供给以后对 dlopen(3) 的调用加载的库(与被 DT_NEEDED 条目引用相反)。

在之前的Android版本中,如果您的应用请求系统加载带有文本重定位的共享库,系统会显示警告,但仍然允许加载该库。从本版本开始,如果您的应用的目标SDK版本为23或更高,系统将拒绝此库。为了帮助您检测库加载失败的情况,您的应用应该记录dlopen(3)错误,并包含dlerror(3)调用返回的问题描述文本。要了解有关处理文本重定位的更多信息,请参阅此指南

APK验证

平台现在执行更严格的APK验证。如果清单中声明的文件在APK本身中不存在,则APK被认为已损坏。如果删除了任何内容,则必须重新签署APK。

USB连接

现在,通过USB端口进行的设备连接默认设置为仅充电模式。要通过USB连接访问设备及其内容,用户必须明确授予此类交互的权限。如果您的应用支持通过USB端口与设备进行用户交互,请考虑必须明确启用该交互。

Android for Work变更

此版本包含以下Android for Work行为变更

  • 个人环境中的工作联系人。当用户查看过去通话时,Google拨号器通话记录现在会显示工作联系人。将setCrossProfileCallerIdDisabled()设置为true会在Google拨号器通话记录中隐藏工作配置文件联系人。只有在您将setBluetoothContactSharingDisabled()设置为false的情况下,工作联系人才能与蓝牙设备上的个人联系人一起显示。默认情况下,它设置为true
  • Wi-Fi配置删除:如果删除了该工作配置文件,则由配置文件所有者(例如,通过调用addNetwork()方法)添加的Wi-Fi配置将被删除。
  • Wi-Fi配置锁定:如果WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN非零,则活动设备所有者创建的任何Wi-Fi配置都无法再被用户修改或删除。用户仍然可以创建和修改他们自己的Wi-Fi配置。活动设备所有者有权编辑或删除任何Wi-Fi配置,包括非其创建的配置。
  • 通过添加Google帐户下载设备策略控制器:当需要通过设备策略控制器 (DPC) 应用进行管理的Google帐户添加到非托管环境中的设备时,添加帐户流程现在会提示用户安装相应的WPC。此行为也适用于通过设置>帐户和初始设备设置向导添加的帐户。
  • 对特定DevicePolicyManager API行为的更改
  • 其他API的更改:
    • 数据使用情况:android.app.usage.NetworkUsageStats类已重命名为NetworkStats
  • 全局设置的更改: