Android5.0、6.0、7.0的新特性

通过goole官网摘要

Android 6.0


Android Runtime (ART)

在 Android 5.0 中,ART 运行时取代 Dalvik 成为平台默认设置。Android 4.4 中已引入处于实验阶段的 ART 运行时。

有关 ART 的新功能概述,请参阅 ART 简介。部分主要的新功能包括:

  • 预先 (AOT) 编译
  • 改进的垃圾回收 (GC)
  • 改进的调试支持

大多数 Android 应用无需任何更改就可以在 ART 下工作。不过,部分适合 Dalvik 的技术并不适用于 ART。如需了解有关最重要问题的信息,请参阅在 Android Runtime (ART) 上验证应用行为。如存在以下情况,应特别注意:

  • 您的应用使用 Java 原生接口 (JNI) 运行 C/C++ 代码。
  • 您使用生成非标准代码的开发工具(例如,一些代码混淆工具)。
  • 您使用与压缩垃圾回收不兼容的技术

通知


请确保您的通知考虑了上述 Android 5.0 变更。要详细了解如何为 Android 5.0 及更高版本设计通知,请参阅通知设计指南

Material Design 样式

在白色(或非常浅)的背景上使用深色文本绘制通知,以便与新的 Material Design 小部件匹配。请确保您的所有通知都与新的配色方案协调一致。如果您的通知看上去不协调,请进行修正:

  • 使用 setColor() 在您的图标图像后面的圆形中设置重点色彩。
  • 更新或移除使用色彩的资源。系统在操作图标和主要通知图标中忽略所有非阿尔法通道。您应假设这些图标仅支持阿尔法通道。系统用白色绘制通知图标,用深灰色绘制操作图标。

声音和振动

如果您当前使用 RingtoneMediaPlayer 或 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 Revision 10c。有关对 NDK 进行的重要变更和问题修复的更多信息,请参阅 Revision 10c 版本说明

绑定到服务


Context.bindService() 方法现在需要显式 Intent,如果提供隐式 intent,将引发异常。为确保应用的安全性,请使用显式 intent 启动或绑定 Service,且不要为服务声明 intent 过滤器。

WebView


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

  • 如果您的应用是面向 API 级别 21 或更高级别:
  • 如果您的应用是面向低于 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 以及 Forward Secrecy 加密套件(ECDHE、DHE),且最好使用后者。

也可以修改应用以使用自定义 SSLSocketFactory 与服务器通信。出厂时应精心设计以创建 SSLSocket 实例,除默认加密套件外,此实例还应启用服务器所需的部分加密套件。

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

例如,某些应用包含中断的自定义 X509TrustManager,因为它预计 authType 参数将成为 RSA,但出现了 ECDHE_RSA 或 DHE_RSA。

服务器不支持 TLSv1.1、TLSv1.2 或新的 TLS 扩展

例如,与服务器握手的 TLS/SSL 被错误地拒绝或出现停顿。首选的修复方法是升级服务器以符合 TLS/SSL 协议。这使服务器可以成功地协商这些更新的协议或协商 TLSv1 或更早的协议,并忽略它不理解的传输层安全协议扩展程序。在某些情况下,在服务器上禁用 TLSv1.1 和 TLSv1.2 可以作为权宜之计,直到升级服务器软件。

也可以修改应用以使用自定义 SSLSocketFactory 与服务器通信。出厂时应精心设计以创建 SSLSocket 实例,该实例仅包含已启用且服务器可以正确为其提供支持的协议。

支持托管配置文件


设备管理员可以向设备添加托管配置文件。此配置文件由管理员所有,让管理员控制托管配置文件的同时,允许由用户控制其自己的个人配置文件及其存储空间。此变更会通过下列方式影响您的现有应用的行为。

处理 Intent

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

为防止出现此情况,您可以在触发任何 intent 之前检查是否至少有一个适合此 intent 的处理程序。要检查是否存在有效的处理程序,请调用 Intent.resolveActivity()。您可以在轻松拍照:使用相机应用拍摄照片中查看执行上述操作的示例。

在各个配置文件中共享文件

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

为安全起见,如果您需要将文件附加到某个可能会从一个配置文件移动到另一个配置文件的 intent,您应为该文件创建并使用内容 URI。有关共享文件及内容 URI 的更多信息,请参阅共享文件。例如,设备管理员可能会制定将由个人配置文件中的相机处理的 ACTION_IMAGE_CAPTURE 白名单。触发的 intent 的 EXTRA_OUTPUT 应包含指定照片应存储在何处的内容 URI。相机应用可以将图像写入该 URI 指定的位置,触发 intent 的应用将能够读取该文件,即使应用位于其他配置文件上。

已移除锁定屏幕小部件支持

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

Android 6.0

运行时权限


此版本引入了一种新的权限模式,如今,用户可直接在运行时管理应用权限。这种模式让用户能够更好地了解和控制权限,同时为应用开发者精简了安装和自动更新过程。用户可为所安装的各个应用分别授予或撤销权限。

对于以 Android 6.0(API 级别 23)或更高版本为目标平台的应用,请务必在运行时检查和请求权限。要确定您的应用是否已被授予权限,请调用新增的 checkSelfPermission() 方法。要请求权限,请调用新增的 requestPermissions() 方法。即使您的应用并不以 Android 6.0(API 级别 23)为目标平台,您也应该在新权限模式下测试您的应用。

如需了解有关在您的应用中支持新权限模式的详情,请参阅使用系统权限。如需了解有关如何评估新模式对应用的影响的提示,请参阅权限最佳做法

低电耗模式和应用待机模式


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

  • 低电耗模式:如果用户拔下设备的电源插头,并在屏幕关闭后的一段时间内使其保持不活动状态,设备会进入低电耗模式,在该模式下设备会尝试让系统保持休眠状态。在该模式下,设备会定期短时间恢复正常工作,以便进行应用同步,还可让系统执行任何挂起的操作。
  • 应用待机模式:应用待机模式允许系统判定应用在用户未主动使用它时处于空闲状态。当用户有一段时间未触摸应用时,系统便会作出此判定。如果拔下了设备电源插头,系统会为其视为空闲的应用停用网络访问以及暂停同步和作业。

要详细了解这些节能变更,请参阅对低电耗模式和应用待机模式进行针对性优化

取消支持 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.so 和 libssl.so。这些库并非公共 API,可能会在不同版本和设备上毫无征兆地发生变化或出现故障。此外,您还可能让自己暴露在安全漏洞的风险之下。请改为修改原生代码,以通过 JNI 调用 Java 加密 API,或静态链接到您选择的加密库。

硬件标识符访问权


为给用户提供更严格的数据保护,从此版本开始,对于使用 WLAN API 和 Bluetooth API 的应用,Android 移除了对设备本地硬件标识符的编程访问权。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getAddress() 方法现在会返回常量值 02:00:00:00:00:00

现在,要通过蓝牙和 WLAN 扫描访问附近外部设备的硬件标识符,您的应用必须拥有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 权限。

:当运行 Android 6.0(API 级别 23)的设备发起后台 WLAN 或蓝牙扫描时,在外部设备看来,该操作的发起来源是一个随机化 MAC 地址。

通知


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

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

音频管理器变更


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

文本选择


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

要实现可用于文本选择的浮动工具栏,请在您的现有应用中做出以下更改:

  1. 在 View 对象或 Activity 对象中,将 ActionMode 调用从 startActionMode(Callback) 更改为 startActionMode(Callback, ActionMode.TYPE_FLOATING)
  2. 改为使用 ActionMode.Callback 的现有实现扩展 ActionMode.Callback2
  3. 替代 onGetContentRect() 方法,用于提供 Rect 内容对象(如文本选择矩形)在视图中的坐标。
  4. 如果矩形的定位不再有效,并且这是唯一需要声明为无效的元素,请调用 invalidateContentRect() 方法。

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

浏览器书签变更


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

Android 密钥库变更


从此版本开始,Android 密钥库提供程序不再支持 DSA。但仍支持 ECDSA。

停用或重置安全锁定屏幕时(例如,由用户或设备管理员执行此类操作时),系统将不再删除需要闲时加密的密钥,但在上述事件期间会删除需要闲时加密的密钥。

WLAN 和网络连接变更


此版本对 WLAN API 和 Networking API 引入了以下行为变更。

  • 现在,您的应用只能更改由您创建的 WifiConfiguration 对象的状态。系统不允许您修改或删除由用户或其他应用创建的 WifiConfiguration 对象。
  • 在之前的版本中,如果应用利用带有 disableAllOthers=true 设置的 enableNetwork() 强制设备连接特定 WLAN 网络,设备将会断开与移动数据网络等其他网络的连接。在此版本中,设备不再断开与上述其他网络的连接。如果您的应用的 targetSdkVersion 为 “20” 或更低,则会固定连接所选 WLAN 网络。如果您的应用的 targetSdkVersion 为 “21” 或更高,请使用多网络 API(如 openConnection()bindSocket() 和新增的 bindProcessToNetwork() 方法)来确保通过所选网络传送网络流量。

相机服务变更


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

  • 根据客户端应用进程的“优先级”授予对相机子系统资源的访问权,包括打开和配置相机设备。带有对用户可见 Activity 或前台 Activity 的应用进程一般会被授予较高的优先级,从而使相机资源的获取和使用更加可靠;
  • 当高优先级的应用尝试使用相机时,系统可能会“驱逐”正在使用相机客户端的低优先级应用。在已弃用的 Camera API 中,这会导致系统为被驱逐的客户端调用 onError()。在 Camera2 API 中,这会导致系统为被驱逐的客户端调用 onDisconnected()
  • 在配备相应相机硬件的设备上,不同的应用进程可同时独立打开和使用不同的相机设备。但现在,如果在多进程用例中同时访问相机会造成任何打开的相机设备的性能或能力严重下降,相机服务会检测到这种情况并禁止同时访问。即使并没有其他应用直接尝试访问同一相机设备,此变更也可能导致低优先级客户端被“驱逐”。
  • 更改当前用户会导致之前用户帐户拥有的应用内活动相机客户端被驱逐。对相机的访问仅限于访问当前设备用户拥有的用户个人资料。举例来说,这意味着,当用户切换到其他帐户后,“来宾”帐户实际上无法让使用相机子系统的进程保持运行状态。

运行时


ART 运行时环境现在可正确实现 newInstance() 方法的访问规则。此变更修正了之前版本中 Dalvik 无法正确检查访问规则的问题。如果您的应用使用 newInstance() 方法,并且您想重写访问检查,请调用 setAccessible() 方法(将输入参数设置为 true)。如果您的应用使用 v7 appcompat 库或 v7 recyclerview 库,则您必须更新应用以使用这些库的最新版本。否则,请务必更新从 XML 引用的任何自定义类,以便能够访问它们的类构造函数。

此版本更新了动态链接程序的行为。动态链接程序现在可以识别库的 soname 与其路径之间的差异(公开错误 6670),并且现在已实现了按 soname 搜索。之前包含错误的 DT_NEEDED 条目(通常是开发计算机文件系统上的绝对路径)却仍工作正常的应用,如今可能会出现加载失败。

现已正确实现 dlopen(3) RTLD_LOCAL 标记。请注意,RTLD_LOCAL 是默认值,因此不显式使用 RTLD_LOCAL 的 dlopen(3) 调用将受到影响(除非您的应用显式使用 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
  • WLAN 配置删除:现在,当删除某个托管配置文件时,将会移除由配置文件所有者添加的 WLAN 配置(例如,通过调用 addNetwork() 方法添加的配置)。
  • WLAN 配置锁定:如果 WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN 不为零,则用户无法再修改或删除任何由活动设备所有者创建的 WLAN 配置。用户仍可创建和修改其自己的 WLAN 配置。活动设备所有者拥有编辑或删除任何 WLAN 配置(包括并非由其创建的配置)的权限。
  • 通过添加 Google 帐户下载设备规范控制器:向托管环境以外的设备添加需要通过设备规范控制器 (DPC) 应用管理的 Google 帐户时,帐户添加流程现在会提示用户安装相应的 WPC。在设备初始设置向导中通过 Settings > Accounts 添加帐户时,也会出现此行为。
  • 对特定 DevicePolicyManager API 行为的变更:
  • 对其他 API 的变更
    • 流量消耗:android.app.usage.NetworkUsageStats 类已重命名为 NetworkStats
  • 对全局设置的变更

Android 7.0

Android 7.0 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更。本文重点介绍您应该了解并在开发应用时加以考虑的一些主要变更。

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

电池和内存


Android 7.0 包括旨在延长设备电池寿命和减少 RAM 使用的系统行为变更。这些变更可能会影响您的应用访问系统资源,以及您的应用通过特定隐式 intent 与其他应用交互的方式。

低电耗模式

Android 6.0(API 级别 23)引入了低电耗模式,当用户设备未插接电源、处于静止状态且屏幕关闭时,该模式会推迟 CPU 和网络活动,从而延长电池寿命。而 Android 7.0 则通过在设备未插接电源且屏幕关闭状态下、但不一定要处于静止状态(例如用户外出时把手持式设备装在口袋里)时应用部分 CPU 和网络限制,进一步增强了低电耗模式。

图 1. 低电耗模式如何应用第一级系统活动限制以延长电池寿命的图示。

当设备处于充电状态且屏幕已关闭一定时间后,设备会进入低电耗模式并应用第一部分限制:关闭应用网络访问、推迟作业和同步。如果进入低电耗模式后设备处于静止状态达到一定时间,系统则会对 PowerManager.WakeLockAlarmManager 闹铃、GPS 和 WLAN 扫描应用余下的低电耗模式限制。无论是应用部分还是全部低电耗模式限制,系统都会唤醒设备以提供简短的维护时间窗口,在此窗口期间,应用程序可以访问网络并执行任何被推迟的作业/同步。

图 2. 低电耗模式如何在设备处于静止状态达到一定时间后应用第二级系统活动限制的图示。

请注意,激活屏幕或插接设备电源时,系统将退出低电耗模式并移除这些处理限制。此项新增的行为不会影响有关使您的应用适应 Android 6.0(API 级别 23)中所推出的旧版本低电耗模式的建议和最佳做法,如对低电耗模式和应用待机模式进行针对性优化中所讨论。您仍应遵循这些建议(例如使用 Google 云消息传递 (GCM) 发送和接收消息)并开始安排更新计划以适应新增的低电耗模式行为。

Project Svelte:后台优化

Android 7.0 移除了三项隐式广播,以帮助优化内存使用和电量消耗。此项变更很有必要,因为隐式广播会在后台频繁启动已注册侦听这些广播的应用。删除这些广播可以显著提升设备性能和用户体验。

移动设备会经历频繁的连接变更,例如在 WLAN 和移动数据之间切换时。目前,可以通过在应用清单中注册一个接收器来侦听隐式 CONNECTIVITY_ACTION 广播,让应用能够监控这些变更。由于很多应用会注册接收此广播,因此单次网络切换即会导致所有应用被唤醒并同时处理此广播。

同理,在之前版本的 Android 中,应用可以注册接收来自其他应用(例如相机)的隐式 ACTION_NEW_PICTURE 和 ACTION_NEW_VIDEO 广播。当用户使用相机应用拍摄照片时,这些应用即会被唤醒以处理广播。

为缓解这些问题,Android 7.0 应用了以下优化措施:

  • 面向 Android 7.0 开发的应用不会收到 CONNECTIVITY_ACTION 广播,即使它们已有清单条目来请求接受这些事件的通知。在前台运行的应用如果使用 BroadcastReceiver 请求接收通知,则仍可以在主线程中侦听 CONNECTIVITY_CHANGE
  • 应用无法发送或接收 ACTION_NEW_PICTURE 或 ACTION_NEW_VIDEO 广播。此项优化会影响所有应用,而不仅仅是面向 Android 7.0 的应用。

如果您的应用使用任何 intent,您仍需要尽快移除它们的依赖关系,以正确适配 Android 7.0 设备。Android 框架提供多个解决方案来缓解对这些隐式广播的需求。例如,JobScheduler API 提供了一个稳健可靠的机制来安排满足指定条件(例如连入无限流量网络)时所执行的网络操作。您甚至可以使用 JobScheduler 来适应内容提供程序变化。

如需了解有关 Android N 中后台优化以及如何改写应用的详细信息,请参阅后台优化

权限更改


Android 7.0 做了一些权限更改,这些更改可能会影响您的应用。

系统权限更改

为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问 (0700)。此设置可防止私有文件的元数据泄漏,如它们的大小或存在性。此权限更改有多重副作用:

在应用间共享文件


对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。

要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类。如需了解有关权限和共享文件的详细信息,请参阅共享文件

无障碍改进


为提高平台对于视力不佳或视力受损用户的易用性,Android 7.0 做出了一些更改。这些更改一般并不要求更改您的应用代码,不过您应仔细检查并使用您的应用测试这些功能,以评估它们对用户体验的潜在影响。

屏幕缩放

Android 7.0 支持用户设置显示尺寸,以放大或缩小屏幕上的所有元素,从而提升设备对视力不佳用户的可访问性。用户无法将屏幕缩放至低于最小屏幕宽度 sw320dp,该宽度是 Nexus 4 的宽度,也是常规中等大小手机的宽度。

图 3. 右侧屏幕显示的是一台运行 Android 7.0 系统映像的设备增大显示尺寸后的效果。

当设备密度发生更改时,系统会以如下方式通知正在运行的应用:

  • 如果是面向 API 级别 23 或更低版本系统的应用,系统会自动终止其所有后台进程。这意味着如果用户切换离开此类应用,转而打开 Settings 屏幕并更改 Display size 设置,则系统会像处理内存不足的情况一样终止该应用。如果应用具有任何前台进程,则系统会如处理运行时更改中所述将配置变更通知给这些进程,就像对待设备屏幕方向变更一样。
  • 如果是面向 Android 7.0 的应用,则其所有进程(前台和后台)都会收到有关配置变更的通知,如处理运行时更改中所述。

大多数应用并不需要进行任何更改即可支持此功能,不过前提是这些应用遵循 Android 最佳做法。具体要检查的事项:

  • 在屏幕宽度为 sw320dp 的设备上测试您的应用,并确保其充分运行。
  • 当设备配置发生变更时,更新任何与密度相关的缓存信息,例如缓存位图或从网络加载的资源。当应用从暂停状态恢复运行时,检查配置变更。

    :如果您要缓存与配置相关的数据,则最好也包括相关元数据,例如该数据对应的屏幕尺寸或像素密度。保存这些元数据便于您在配置变更后决定是否需要刷新缓存数据。

  • 避免用像素单位指定尺寸,因为像素不会随屏幕密度缩放。应改为使用与密度无关像素 (dp) 单位指定尺寸。

设置向导中的视觉设置

Android 7.0 在“Welcome”屏幕中加入了“Vision Settings”,用户可以在新设备上设置以下无障碍功能设置:Magnification gestureFont sizeDisplay size 和话语提示。此项变更让您可以更容易发现与不同屏幕设置有关的错误。要评估此功能的影响,您应在启用这些设置的状态下测试应用。您可以在 Settings > Accessibility 中找到这些设置。

NDK 应用链接至平台库


从 Android 7.0 开始,系统将阻止应用动态链接非公开 NDK 库,这种库可能会导致您的应用崩溃。此行为变更旨在为跨平台更新和不同设备提供统一的应用体验。即使您的代码可能不会链接私有库,但您的应用中的第三方静态库可能会这么做。因此,所有开发者都应进行相应检查,确保他们的应用不会在运行 Android 7.0 的设备上崩溃。如果您的应用使用原生代码,则只能使用公开 NDK API

您的应用可通过以下三种方式尝试访问私有平台 API:

  • 您的应用直接访问私有平台库。您应更新您的应用以添加该应用的库副本,或使用公开 NDK API
  • 您的应用使用一个可访问私有平台库的第三方库。即使您确定您的应用不会直接访问私有库,您仍应针对此情景测试您的应用。
  • 您的应用引用一个其 APK 中未包含的库。例如,如果您尝试使用您自己的 OpenSSL 副本,但忘记将它与应用的 APK 进行捆绑,则可能会出现此情况。正常情况下,此应用可在包含 libcrypto.so 的 Android 平台版本上运行。不过,此应用在不包含此库的新版 Android(例如,Android 6.0 和更高的版本)上会崩溃。为修复此问题,请确保您的 APK 捆绑您的所有非 NDK 库。

应用不应使用 NDK 中未包含的原生库,因为这些库可能会发生更改或在不同 Android 版本之间的可用性不同。例如,从 OpenSSL 切换至 BoringSSL 即属于此类更改。此外,由于不属于 NDK 中的平台库没有兼容性要求,因此不同的设备可能提供不同级别的兼容性。

为降低此限制可能对当前发布的应用的影响,面向 API 级别 23 或更低级别的应用在 Android N 上可暂时访问颇为常用的一组库,例如 libandroid_runtime.solibcutils.solibcrypto.so 和 libssl.so。如果您的应用加载其中某个库,logcat 会生成一个警告,并在目标设备上显示一个 Toast 来通知您。如果您看到这些警告,您应更新您的应用以添加该应用自己的库副本,或仅使用公开 NDK API。将来发布的 Android 平台可能会完全限制对私有库的使用,并导致您的应用崩溃。

所有应用在调用既非公开又不可暂时访问的 API 时都会生成一个运行时错误。结果就是 System.loadLibrary 和 dlopen(3) 同时返回 NULL,并可能导致您的应用崩溃。您应检查应用代码以移除对私有平台 API 的使用,并使用预览版设备或模拟器全面测试应用。如果您不确定您的应用是否使用私有库,您可以检查 logcat 以识别运行时错误。

下表描述的是根据应用使用的私有原生库及其目标 API 级别 (android:targetSdkVersion),应用预期显示的行为。

目标 API 级别 通过动态链接器进行运行时访问 N Developer Preview 行为 最终 Android N 版本行为 未来的 Android 平台行为
公开 NDK 任意 可访问 合乎预期 合乎预期 合乎预期
私有(暂时可访问的私有库) 23 或更低 暂时可访问 合乎预期,但您会在目标设备上收到一个 logcat 警告和一条消息。 合乎预期,但您会收到一个 logcat 警告。 运行时错误
私有(暂时可访问的私有库) 24 或更高 受限 运行时错误 运行时错误 运行时错误
私有(其他) 任意 受限 运行时错误 运行时错误 运行时错误

检查您的应用是否使用私有库

为帮助您识别加载私有库的问题,logcat 可能会生成一个警告或运行时错误。例如,如果您的应用面向 API 级别 23 或更低级别,并在运行 Android 7.0 的设备上尝试访问私有库,您可能会看到一个类似于下面所示的警告:

03-21 17:07:51.502 31234 31234 W linker  : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120

这些 logcat 警告通知您哪个库正在尝试访问私有平台 API,但不会导致您的应用崩溃。但是,如果应用面向 API 级别 24 或更高级别,logcat 会生成以下运行时错误,您的应用可能会崩溃:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so"
("/system/lib/libcutils.so") needed or dlopened by
"/system/lib/libnativeloader.so" is not accessible for the namespace
"classloader-namespace"
  at java.lang.Runtime.loadLibrary0(Runtime.java:977)
  at java.lang.System.loadLibrary(System.java:1602)

如果您的应用使用动态链接到私有平台 API 的第三方库,您可能也会看到上述 logcat 输出。利用 Android 7.0DK 中的 readelf 工具,您可以通过运行以下命令生成给定 .so 文件的所有动态链接的共享库列表:

aarch64-linux-android-readelf -dW libMyLibrary.so

更新您的应用

通过下面的一些步骤,您可以修复上述类型的错误并确保您的应用不会在将来的更新版平台上崩溃:

  • 如果您的应用使用私有平台库,您应更新它,以添加该应用自己的库副本或使用公开 NDK API
  • 如果您的应用使用访问私有符号的第三方库,则联系库作者以更新库。
  • 请确保将您的所有非 NDK 库与您的 APK 打包在一起。
  • 使用标准 JNI 函数而非来自 libandroid_runtime.so 的 getJavaVM 和 getJNIEnv
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • 使用 __system_property_get 而非来自 libcutils.so 的私有 property_get 符号。为此,请使用 __system_property_get及以下 include 函数:
    #include <sys/system_properties.h>

    :系统属性的可用性和内容未通过 CTS 进行测试。应执行进一步修复以避免同时使用这些属性。

  • 使用来自 libcrypto.so 的 SSL_ctrl 符号的本地版本。例如,您应在您的 .so 文件中静态链接 libcyrpto.a,或从 BoringSSL/OpenSSL 添加一个动态链接的 libcrypto.so 版本,并将其打包到您的 APK 中。

Android for Work


Android 7.0 包含一些针对面向 Android for Work 的应用的变更,包括对证书安装、密码重置、二级用户管理、设备标识符访问权限的变更。如果您是要针对 Android for Work 环境开发应用,则应仔细检查这些变更并相应地修改您的应用。

  • 您必须先安装授权证书安装程序,然后 DPC 才能对其进行设置。对于面向 N SDK 的配置文件和设备所有者应用,您应在设备规范控制器 (DPC) 调用 DevicePolicyManager.setCertInstallerPackage() 之前安装授权证书安装程序。如果尚未安装此安装程序,则系统会引发 IllegalArgumentException
  • 针对设备管理员的重置密码限制现在也适用于配置文件所有者。设备管理员无法再使用 DevicePolicyManager.resetPassword() 来清除或更改已经设置的密码。设备管理员仍可以设置密码,但只能在设备没有密码、PIN 码或图案时这样做。
  • 即使设置了限制,设备所有者和配置文件所有者仍可以管理帐户。而且,即使具有 DISALLOW_MODIFY_ACCOUNTS 用户限制,设备所有者和配置文件所有者仍可调用 Account Management API。
  • 设备所有者可以更轻松地管理二级用户。当设备在设备所有者模式下运行时,系统将自动设置 DISALLOW_ADD_USER 限制。这样可以防止用户创建非托管二级用户。此外,CreateUser() 和 createAndInitializeUser() 方法已弃用,取而代之的是 DevicePolicyManager.createAndManageUser() 方法。
  • 设备所有者可以访问设备标识符。设备所有者可以使用 DevicePolicyManagewr.getWifiMacAddress() 访问设备的 WLAN MAC 地址。如果设备上从未启用 WLAN,则此方法将返回一个 null 值。
  • 工作模式设置控制工作应用访问。当工作模式关闭时,系统启动器通过使工作应用显示为灰色来指示它们不可用。启用工作模式会再次恢复正常行为。
  • 从 Settings UI 安装包含客户端证书链和对应的私钥的 PKCS #12 文件时,系统不再将该证书链中的 CA 证书安装到受信任的凭据存储空间。当应用稍后尝试检索客户端证书链时,这不会影响 KeyChain.getCertificateChain() 的结果。如果需要,使用 .crt 或 .cer 文件扩展名的 DER 编码格式通过 Settings UI 单独将 CA 证书安装到受信任的凭据存储空间。
  • 从 Android 7.0 开始,可针对每个用户管理指纹登记和存储空间。如果配置文件所有者的设备规范客户端 (DPC) 面向 Android N 设备上的 Android N 之前的版本,则用户仍可以在该设备上设置指纹,但工作应用不能访问设备指纹。当 DPC 面向 Android N 和更高版本时,用户可以通过转到 Settings > Security > Work profile security 专门为托管配置文件设置指纹。
  • DevicePolicyManager.getStorageEncryptionStatus() 返回新的加密状态 ENCRYPTION_STATUS_ACTIVE_PER_USER,以表明加密处于活动状态,且加密密钥与用户关联。仅当 DPC 面向 API 级别 24 和更高级别时才会返回新的状态。对于面向更早的 API 级别的应用,即使加密密钥是用户或配置文件特有的,系统也会返回 ENCRYPTION_STATUS_ACTIVE
  • 在 Android 7.0 中,如果设备通过单独的工作挑战安装了托管配置文件,则原本通常会影响整个设备的多个方法将会改变其行为方式。这些方法将仅应用于托管配置文件,而不是影响整个设备。(此类方法的完整列表位于 DevicePolicyManager.getParentProfileInstance() 文档中。)例如,DevicePolicyManager.lockNow() 只锁定托管配置文件,而不是锁定整个设备。对于上述每个方法,您可以通过对 DevicePolicyManager 的父实例调用该方法来获取以前的行为;您可以通过调用 DevicePolicyManager.getParentProfileInstance() 获取此父项。例如,如果您调用父实例的 lockNow() 方法,则整个设备将被锁定。

如需了解有关 Android 7.0 中针对 Android for Work 所做变更的详细信息,请参阅 Android for Work 更新

注解保留


Android 7.0 修复了一个注解可见性被忽略的错误。这种问题会导致应用可在运行时访问原本不允许访问的注解。这些注解包括:

  • VISIBILITY_BUILD:仅应编译时可见。
  • VISIBILITY_SYSTEM:运行时应可见,但仅限底层系统。

如果您的应用依赖这种行为,请为运行时必须可用的注解添加保留政策。您可通过使用 @Retention(RetentionPolicy.RUNTIME) 来执行此操作。

其他重要说明


  • 如果一个应用在 Android 7.0 上运行,但却是针对更低 API 级别开发的,那么在用户更改显示尺寸时,系统将终止此应用进程。应用必须能够妥善处理此情景。否则,当用户从最近使用记录中恢复运行应用时,应用将会出现崩溃现象。

    您应测试应用以确保不会发生此行为。要进行此测试,您可以通过 DDMS 手动终止应用,以造成相同的崩溃现象。

    在密度发生更改时,系统不会自动终止面向 N 及更高版本的应用;不过,这些应用仍可能对配置变更做出不良响应。

  • Android 7.0 上的应用应能够妥善处理配置变更,并且在后续启动时不会出现崩溃现象。您可以通过更改字体大小 (Setting >Display > Font size) 并随后从最近使用记录中恢复运行应用,来验证应用行为。
  • 由于之前的 Android 版本中的一项错误,系统未能将对主线程上的一个 TCP 套接字的写入操作举报为违反严格模式。Android 7.0 修复了此错误。呈现出这种行为的应用现在会引发 android.os.NetworkOnMainThreadException。一般情况下,我们不建议在主线程上执行网络操作,因为这些操作通常会出现可能导致 ANR 和卡顿的高尾延迟。
  • Debug.startMethodTracing() 方法系列现在默认在您的共享存储空间上的软件包特定目录中存储输出,而非 SD 卡根目录。这意味着应用不再需要请求 WRITE_EXTERNAL_STORAGE 权限来使用这些 API 。
  • 许多平台 API 现在开始检查在 Binder 事务间发送的大负载,系统现在会将 TransactionTooLargeExceptions 作为 RuntimeExceptions 再次引发,而不再只是默默记录或抑制它们。一个常见例子是在 Activity.onSaveInstanceState()上存储过多数据,导致 ActivityThread.StopInfo 在您的应用面向 Android 7.0 时引发 RuntimeException
  • 如果应用向 View 发布 Runnable 任务,并且 View 未附加到窗口,系统会用 View 为 Runnable 任务排队;在 View 附加到窗口之前,不会执行 Runnable 任务。此行为会修复以下错误:
    • 如果一项应用是从并非预期窗口 UI 线程的其他线程发布到 View,则 Runnable 可能会因此运行错误的线程。
    • 如果 Runnable 任务是从并非环路线程的其他线程发布,则应用可能会曝光 Runnable 任务。
  • 如果 Android 7.0 上一项有 DELETE_PACKAGES 权限的应用尝试删除一个软件包,但另一项应用已经安装了这个软件包,则系统需要用户进行确认。在这种情况下,应用在调用 PackageInstaller.uninstall() 时预计的返回状态应为 STATUS_PENDING_USER_ACTION
  • 名为 Crypto 的 JCA 提供程序已弃用,因为它仅有的 SHA1PRNG 算法为弱加密。应用无法再使用 SHA1PRNG(不安全地)派生密钥,因为不再提供此提供程序。如需了解详细信息,请参阅博文 Android N 中已弃用“Crypto”安全提供程序




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值