Android 9 功能和 API

Android 9(API 级别 28)针对 用户和开发者本文重点介绍面向开发者的新功能。

要了解这些新 API,请参阅 API 差异报告或访问 Android API 参考文档。此外,请务必查看 Android 9 行为变更(学习资源) 。

利用 Wi-Fi RTT 进行室内定位

新的 RTT API 支持在应用中进行室内定位。

Android 9 添加了对 IEEE 802.11-2016 Wi-Fi 的平台支持 (也称为 Wi-Fi 往返时间 [RTT]) 如何在应用中进行室内定位

在搭载 Android 9 且具有硬件支持的设备上,您的应用可以使用 RTT API,用于测量 与附近支持 RTT 的 Wi-Fi 接入点 (AP) 的距离。设备必须具有 已启用定位服务并打开 Wi-Fi 扫描(在 设置 >位置),并且您的应用必须具有 ACCESS_FINE_LOCATION 权限。设备无需连接到接入点即可使用 RTT。 为保护隐私,只有手机可以确定用户与 接入点;接入点没有此信息。

如果您的设备测量与 3 个或更多接入点的距离,您可以使用 多点定位算法,以推测出最适合这些对象的设备位置 测量结果。结果通常精准至 1 至 2 米。

有了这种准确性,您可以打造新的体验,例如建筑物导航 和基于位置的精细服务,例如无歧义语音控制 (例如“打开这盏灯”)和基于位置信息的信息(例如 “此产品有特别优惠吗?”

查看正在使用的 Wi-Fi RTT API <ph type="x-smartling-placeholder"></ph> Android WifiRttScan 演示版应用。

如需了解详情,请参阅 通过 RTT 确定 WLAN 位置信息

刘海屏支持

显示不同刘海屏尺寸的开发者选项界面

使用模拟器测试刘海屏

Android 9 支持最新的无边框屏幕 包含摄像头和音响设备刘海屏。通过 DisplayCutout 类可以让您找出非功能区域的位置和形状, 内容。为了确定是否存在 这些刘海区域,请使用 getDisplayCutout() 方法。

新的窗口布局属性 layoutInDisplayCutoutMode、 可让应用围绕设备的刘海屏来布局内容。您可以设置 将此属性设为以下值之一:

您可以在任何搭载 Android 9 的设备或模拟器上模拟刘海屏 如下所示:

  1. 启用开发者选项
  2. 开发者选项屏幕中,向下滚动到绘图部分 然后选择模拟刘海屏
  3. 选择刘海屏的大小。

通知

Android 9 引入了几项通知增强功能, 适用于以 API 级别 28 及更高级别为目标的开发者。

消息通知

附加了照片的 MessagingStyle。

消息通知

包含回复和对话的 MessagingStyle。

有关使用通知(包括 Android 9 功能)的示例代码,请参阅 人物 示例

增强的即时通讯体验

从 Android 7.0(API 级别 24)开始,您可以添加要回复的操作 消息或直接在通知中输入其他文字。Android 9 增强 并增强了此功能:

  • 简化了对对话参与者的支持: Person 类用于识别参与对话的参与者,包括 头像和 URI许多其他 API,如 addMessage()、 现在利用 Person 类,而不是 CharSequencePerson 类 也支持构建器设计模式。

  • 支持图片:Android 9 现在可在“消息通知”中显示图片 。您可以使用 setData() 以显示图片。以下代码段展示了如何 以创建 Person 和包含图像的消息。

Kotlin

// Create new Person.
val sender = Person()
        .setName(name)
        .setUri(uri)
        .setIcon(null)
        .build()
// Create image message.
val message = Message("Picture", time, sender)
        .setData("image/", imageUri)
val style = Notification.MessagingStyle(getUser())
        .addMessage("Check this out!", 0, sender)
        .addMessage(message)

Java

// Create new Person.
Person sender = new Person()
        .setName(name)
        .setUri(uri)
        .setIcon(null)
        .build();
// Create image message.
Message message = new Message("Picture", time, sender)
        .setData("image/", imageUri);
Notification.MessagingStyle style = new Notification.MessagingStyle(getUser())
        .addMessage("Check this out!", 0, sender)
        .addMessage(message);
  • 将回复保存为草稿:您的应用可以检索 EXTRA_REMOTE_INPUT_DRAFT 在用户无意中关闭消息通知时由系统发送。 您可以使用此 extra 预填充应用中的文本字段,以便用户可以 完成回复。

  • 确定对话是否为群组对话:您可以使用 setGroupConversation() 有目的地将对话标识为群组对话或非群组对话。

  • 为 intent 设置语义操作: setSemanticAction() 方法可以为操作指定语义含义,例如 “标记为已读”“删除”“回复”依此类推。

  • SmartReply:Android 9 支持的建议回复与 消息应用。使用 RemoteInput.setChoices() 以向用户提供一组标准响应。

频道设置、广播和勿扰模式

Android 8.0 引入了通知渠道, 可让您创建 用户可自定义渠道。 Android 9 通过下列变更简化通知渠道设置:

多摄像头支持和摄像头更新

在搭载 Android 9 的设备上,你可以访问视频流 两个或更多个物理服务器 摄像头。 在配备双前置摄像头或双后置摄像头的设备上,您可以创建 无法只使用单个摄像头的创新功能,例如无缝衔接的 缩放、焦外成像和立体视觉。通过该 API,您还可以调用逻辑 摄像头实时画面,可在两个或更多摄像头之间自动切换。

相机的其他改进包括在会话 参数 有助于减少初始拍摄过程中的延迟,以及提供表面共享功能, 相机客户端可处理各种用例,而无需停止和启动 摄像头实时画面我们还为基于显示屏的 Flash 的 支持 以及访问OIS 时间戳

在 Android 9 中,多摄像头 API 支持单色摄像头 FULLLIMITED 功能。 单色输出是通过 YUV_420_888 格式,其中 Y 为灰度,U (Cb) 为 128,V (Cr) 为 128。

Android 9 还支持外部 USB/UVC 摄像头处于开启状态 受支持的设备。

适用于可绘制对象和位图的 ImageDecoder

Android 9 引入了 ImageDecoder 类,它提供了一种现代化的图像解码方法。使用此类 而非 BitmapFactoryBitmapFactory.Options API。

借助 ImageDecoder,您可以创建 DrawableBitmap,从字节缓冲区、文件 或 URI要解码图像,请先调用 createSource() 替换为编码图片的来源。然后,调用 decodeDrawable()decodeBitmap() 方法是传递 ImageDecoder.Source 用于创建 DrawableBitmap。要更改 默认设置,请将 OnHeaderDecodedListener 传递给 decodeDrawable()decodeBitmap()ImageDecoder 次通话 onHeaderDecoded() 设置为已知图像的默认宽度和高度。 如果编码的图片是动画 GIF 或 WebP,decodeDrawable() 会返回 Drawable,它是 AnimatedImageDrawable 类。

您可以使用不同的方法来设置图像属性:

  • 要将解码的图片缩放到确切大小,请将目标尺寸传递到 setTargetSize()。 您也可以使用样本大小缩放图片。将样本大小直接传递给 setTargetSampleSize()
  • 要在缩放图片的范围内剪裁图片,请调用 setCrop()
  • 如需创建可变位图,请将 true 传入 setMutableRequired()

借助 ImageDecoder,你还可以为图片添加复杂的自定义效果 例如圆角或 圆圈遮罩。使用 setPostProcessor() 包含 PostProcessor 类来执行所需的任何绘制命令。

动画

Android 9 引入了 AnimatedImageDrawable 用于绘制和显示 GIF 和 WebP 动画图片的类。 AnimatedImageDrawable 的工作原理类似于 AnimatedVectorDrawable 因为渲染线程会驱动 AnimatedImageDrawable 的动画。 渲染线程还使用工作线程进行解码,因此解码 会干扰渲染线程上的其他操作。这种实现方法 让您的应用显示动画图片,而无需管理其更新或 干扰应用界面线程上的其他事件。

AnimatedImageDrawable 可以使用 ImageDecoder。以下 代码段展示了如何使用 ImageDecoder 解码 AnimatedImageDrawable

Kotlin

@Throws(IOException::class)
private fun decodeImage() {
    val decodedAnimation = ImageDecoder.decodeDrawable(
        ImageDecoder.createSource(resources, R.drawable.my_drawable))

    // Prior to start(), the first frame is displayed.
    (decodedAnimation as? AnimatedImageDrawable)?.start()
}

Java

private void decodeImage() throws IOException {
    Drawable decodedAnimation = ImageDecoder.decodeDrawable(
        ImageDecoder.createSource(getResources(), R.drawable.my_drawable));

    if (decodedAnimation instanceof AnimatedImageDrawable) {
        // Prior to start(), the first frame is displayed.
        ((AnimatedImageDrawable) decodedAnimation).start();
    }
}

ImageDecoder 有多种方法供您进一步修改图片。 例如,您可以使用 setPostProcessor() 方法修改图片的外观,如应用圆形遮罩或 圆角。

HDR VP9 视频、HEIF 图片压缩和 Media API

Android 9 内置了对高动态范围 (HDR) VP9 Profile 2 的支持, 这样您就能通过 YouTube、Play 电影 在支持 HDR 的设备上播放和显示其他来源。

Android 9 还增加了对使用 High Efficiency Image 编码图片的支持 文件格式 (HEIF) (即 HEIC),这样可以提高压缩率并减少存储空间和网络流量消耗 。HEIF 静态图片示例 MediaMuxerMediaExtractor 类。借助 Android 9 设备上的平台支持,您可以轻松发送和 利用来自后端服务器的 HEIF 图片。确认您的 应用兼容这种用于分享和显示的数据格式,不妨试试 HEIF 存储为应用中的图片存储格式您可以执行 jpeg-to-heic 转换 使用 ImageDecoderBitmapFactory(用于获取 JPEG 文件中的位图)。然后,您可以使用 HeifWriter:用于写入 HEIF 来自 YUV 字节缓冲区的静态图像 SurfaceBitmap

您还可以从 AudioTrackAudioRecord, 和 MediaDrm 类。

Android 9 引入了 用于获取指标的 MediaDRM 类,HDCP 安全等级和会话数量 并进一步控制 以及安全停止。请参阅 API 差异 报告以了解详情。

在 Android 9 中,AAudio API 添加了 支持几个额外的 AAudioStream 属性,包括用法、内容 类型和输入预设值使用这些属性,您可以创建 针对 VoIP 或摄像机应用进行微调。您还可以将会话 ID 设置为 将 AAudio 流与可包含音效的子混音相关联。使用 AudioEffect API,用于控制 效果。

Android 9 引入了 AudioEffect API,用于 动态处理。 借助这个类,您可以构建基于声道的音频效果,包括 均衡、多频段压缩和限制器 - 跨多个阶段。通过 频段和活动阶段的数量可配置,且大多数参数也可 实时控制

JobScheduler 中的数据流量费用敏感度

从 Android 9 开始,JobScheduler 可以利用运营商提供的网络状态信号来改进处理能力 网络相关作业的特征。

作业可以声明其估算的数据大小、信号预提取,以及指定 网络要求然后,JobScheduler按照 网络状态。例如,当网络检测到拥塞时, JobScheduler 可能会延迟较大的网络请求。在 不按流量计费的网络,JobScheduler 可以运行预提取作业 改善用户体验,例如预取标题。

添加作业时,请务必使用setEstimatedNetworkBytes()setPrefetch(), 和setRequiredNetwork() 以便帮助 JobScheduler 可正确处理工作。执行作业时 请务必使用 Network 对象 返回者 JobParameters.getNetwork()。 否则,您将隐式使用设备的默认网络 可能不符合您的要求,从而导致意外的流量消耗。

神经网络 API 1.1

我们推出了 Neural Networks API。 (Android 8.1(API 级别 27)),以加快基于应用的设备端机器学习 Android。Android 9 扩展并改进了该 API,在 支持九种新操作:

已知问题:通过 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM 张量传递给 ANEURALNETWORKS_PAD 操作,该操作在 Android 9 及更高版本上提供; NNAPI 的输出可能与较高级别机器的输出不匹配 学习框架,例如 TensorFlow Lite。您 应改为只传递 <ph type="x-smartling-placeholder"></ph> ANEURALNETWORKS_TENSOR_FLOAT32 直到问题得到解决。

此外,该 API 还引入了一个新函数 ANeuralNetworksModel_relaxComputationFloat32toFloat16()、 用于指定是否计算 ANEURALNETWORKS_TENSOR_FLOAT32 其范围和精度与 IEEE 754 16 位浮点数一样低 格式。

自动填充框架

Android 9 引入了多项改进,可自动填充 服务可以实现进一步改善用户在填写 表单。如需详细了解如何在应用中使用自动填充功能,请参阅 自动填充框架指南。

安全增强功能

Android 9 引入了若干安全功能, 以下部分总结了以下内容:

Android Protected Confirmation

搭载 Android 9 或更高版本的受支持设备可为您提供 能够使用 Android 受保护的确认。使用此工作流程时,您的 应用向用户显示提示,请他们批准一个简短的声明。 此声明允许应用再次确认,用户想要 敏感交易(如付款)。

如果用户接受该声明,Android 密钥库会收到并存储一个 受密钥哈希消息身份验证保护的加密签名 代码 (HMAC)。Android 密钥库确认消息有效后,您的应用 可以使用通过可信来源中的 trustedConfirmationRequired 生成的密钥 执行环境 (TEE) 来对用户已接受的消息进行签名。通过 签名具有很高的可信度,表示用户已经看到了 并同意该声明。

注意:Android 受保护的确认并非为用户提供安全信息通道。您的应用不能假定存在 Android 平台所能提供的机密性保证之外的其他机密性保证。在 切勿使用此工作流程展示您 一般不会显示在用户设备上

如需了解如何添加对 Android Protected Confirmation 的支持,请参阅 受 Android 保护 确认 指南。

统一的生物识别身份验证对话框

在 Android 9 中,系统代表提供生物识别身份验证对话框 。此功能可创建标准化的外观、风格和位置 让用户更放心地验证身份 可信的生物识别凭据检查工具

如果您的应用使用 FingerprintManager 向用户显示指纹身份验证对话框,请改用 BiometricPromptBiometricPrompt 依赖系统来显示身份验证信息 对话框。它还会改变自身行为,以适应生物识别类型 身份验证。

硬件安全模块

运行 Android 9 或更高版本的受支持设备 拥有 StrongBox Keymaster,它是 Keymaster HAL 的一种实现, 位于硬件安全模块中该模块包含以下组成部分:

  • 自己的 CPU。
  • 安全存储空间。
  • 真实随机数生成器。
  • 可抵御软件包篡改和未经授权的旁加载的其他机制 。

检查存储在 StrongBox Keymaster 中的密钥时,系统会证实 密钥的完整性。

要详细了解如何使用 Strongbox Keymaster,请参阅硬件安全性 模块

保护将密钥导入密钥库的安全

Android 9 通过添加 可以使用 ASN.1 编码密钥格式。Keymaster 随后会解密 密钥库,因此密钥的内容永远不会以明文形式出现在设备的主机内存中。

详细了解如何导入加密密钥 安全

具有密钥轮替的 APK 签名方案

Android 9 增加了对 APK 签名方案 v3 的支持。该方案提供 将 proof-of-rotation 记录添加到每次签名的签名块中 证书。借助此功能,您可以使用新的签名对您的应用进行签名 将 APK 文件过去的签名证书关联至 它现在已签名。

详细了解如何使用 apksigner

用于仅允许在未锁定设备上进行密钥解密的选项

Android 9 引入了 unlockedDeviceRequired 标记。此选项决定了 密钥库是否要求先解锁屏幕,然后才能允许 使用指定密钥对任何运行中或存储的数据进行解密。这些类型 的密钥非常适合用于加密要存储在磁盘上的敏感数据,例如 健康或企业数据。该标记可以更好地确保用户 如果手机丢失,无法在设备锁定时解密数据 或被盗

若要在设备锁定时保护密钥不会被解密,请启用此标记 通过将 true 传递给 setUnlockedDeviceRequired() 来实现 方法。完成此步骤后,当用户的屏幕锁定时,任何 则使用此密钥解密或签署数据失败。锁定的设备需要 PIN 码、密码、指纹或一些其他可信因素,然后才能 。

旧版加密支持

搭载 Keymaster 4 的 Android 9 设备支持三重数据 加密算法,即三重 DES。如果您的应用与旧版应用互操作 需要三重 DES 的系统,请使用这种加密方式进行加密 敏感凭据

要详细了解如何提高应用的安全性,请参阅 Android 安全性 开发者

WPS 弃用

出于安全考虑,WLAN 保护设置 (WPS) 已被弃用。

Android 备份

Android 9 新增了一些 进行备份和恢复这些更改的详细信息显示在 部分。

客户端加密功能备份

Android 9 增加了对使用 客户端密钥。执行以下操作时,系统会自动启用这项支持 条件:

启用此隐私保护措施后,设备的 PIN 码、解锁图案或密码将 从用户设备创建的备份中恢复数据所需的资源。学习内容 此功能背后的技术,请参阅 Google 云密钥保险柜 服务白皮书。

定义备份所需的设备条件

如果您的应用数据包含敏感信息或偏好设置,Android 9 让您能够定义 条件下 例如,在客户端 加密功能处于启用状态,或者正在进行设备到设备传输。

要详细了解如何在 Android 设备上备份数据,请参阅数据 备份概览

无障碍

Android 9 引入了针对无障碍功能的增强功能, 框架,让您可以更轻松地为 Google Cloud 上的用户 。

导航语义

Android 9 中添加的属性可让您更轻松地定义 无障碍服务(尤其是屏幕阅读器)会从 复制到另一个屏幕上以下属性可帮助视障用户 在应用界面中快速浏览文本,并允许用户进行选择。

例如,在购物应用中,屏幕阅读器可以帮助用户 无需屏幕阅读器即可直接从一种交易类别跳转到另一种交易类别 必须先读取某个类别中的所有项,然后才能继续下一个类别。

无障碍窗格标题

在 Android 8.1(API 级别 27)及更低版本中,无障碍服务并非始终可用 确定屏幕的特定窗格何时更新,例如某个 Activity 将一个 Fragment 替换为另一个 Fragment 时。窗格包括 逻辑分组、视觉相关的界面元素,通常包括 fragment。

在 Android 9 中,您可以提供无障碍窗格标题,也可以单独提供 为这些窗格显示可识别的标题如果某个窗格具有无障碍窗格标题 当窗格变化时,无障碍服务会收到更详细的信息。 借助此功能,服务可以为用户提供更精细的信息 界面中的变化

要指定窗格的标题,请使用 android:accessibilityPaneTitle 属性。您也可以更新界面窗格的标题,在 运行时(使用 setAccessibilityPaneTitle())。 例如,您可以为某网页的内容区域 Fragment 对象。

基于标题的导航

如果您的应用显示的文本内容包含逻辑标题,请将 android:accessibilityHeading 属性设为 true View。修改者 添加这些标题后,无障碍服务就可以帮助用户进行导航 您可以直接从一个标题跳转到下一个标题任何无障碍服务都可以使用 提升用户的界面导航体验。

群组导航和输出

传统上,屏幕阅读器使用 android:focusable属性 确定他们何时应该阅读 ViewGroup,或者 View 对象,是一个单元。这样, 用户可以明白,这些视图在逻辑上彼此相关。

在 Android 8.1 及更低版本中,您需要标记ViewViewGroup 设为不可聚焦,并将 ViewGroup 本身设为可聚焦。这个 这种安排会导致 View 的某些实例被标记为可聚焦, 让键盘导航变得更为繁琐

从 Android 9 开始,您可以使用 android:screenReaderFocusable 属性,而不是 android:focusable 属性 将 View 对象设为可聚焦会产生一些不良后果。屏幕阅读器 将焦点置于设置了 android:screenReaderFocusable 的所有元素上 或将 android:focusable 更改为 true

便捷操作

Android 9 新增了一些方便用户执行操作的支持功能:

与提示的交互
借助无障碍功能框架中的新功能,您可以访问 应用界面中的提示。使用 getTooltipText() 来读取提示文字,并使用 ACTION_SHOW_TOOLTIPACTION_HIDE_TOOLTIP 指示 View 的实例显示或 隐藏其提示。
新增全局操作
Android 9 引入了对 AccessibilityService 类。您的服务可帮助用户锁定设备和截取屏幕截图 使用 GLOBAL_ACTION_LOCK_SCREENGLOBAL_ACTION_TAKE_SCREENSHOT 操作。

窗口更改详情

Android 9 让您可以在应用运行时更轻松地跟踪应用窗口的更新 同时重新绘制多个窗口。当 TYPE_WINDOWS_CHANGED 事件发生后,使用 getWindowChanges() 用于确定窗口是如何更改的 API。在多窗口更新期间,每个 窗口会生成自己的一组事件。 getSource() 方法返回与每个事件相关联的窗口的根视图。

如果应用已为其应用的无障碍窗格标题 View 对象,您的服务可以识别 当应用的界面更新时触发。当 TYPE_WINDOW_STATE_CHANGED 事件发生时,请使用由 getContentChangeTypes() 以确定窗口是如何变化的。例如,框架 检测窗格何时有新标题或者窗格何时消失。

旋转

为避免无意的旋转,我们添加了一种模式,可将当前的 即使设备位置发生变化,屏幕也不会改变。用户可以触发轮替 根据需要手动按系统栏中的按钮。

在大多数情况下,对应用的兼容性影响微乎其微。但是,如果您的 应用具有任何自定义的旋转行为,或使用任何异常的屏幕方向 那么您可能会遇到以前被忽视的问题 用户旋转偏好设置始终设为纵向。我们建议您完成 观察应用所有关键 activity 中的旋转行为, 确保所有屏幕方向设置仍在提供 最佳体验。

有关详情,请参阅相关的行为 更改

旋转的移动设备显示新的旋转模式,让用户可以手动触发旋转

新的旋转模式可让用户在需要时使用系统栏中的按钮手动触发旋转。

文本

Android 9 为 平台:

  • 预先计算文本: 改进了 PrecomputedText 类 从而计算和缓存所需的 提前获取相关信息它还允许应用关闭文本布局 主线程。

  • 放大镜:Magnifier 类是一个 平台微件,它提供放大镜 API,可实现一致的 放大镜功能体验在所有应用中。

  • Smart Linkify:Android 9 增强了 TextClassifier 类, 该模型利用机器学习来识别所选文本中的某些实体, 提供操作建议。例如,TextClassifier 可让您的应用检测 用户已选择电话号码。这样,您的应用就可以 用户使用该号码拨打电话。TextClassifier 中的功能 替换 Linkify 类的功能。

  • 文本布局:使用多种便捷方法和属性, 实现界面设计有关详情,请参阅 TextView

DEX 文件的 ART 提前转换

在搭载 Android 9 或更高版本的设备上,Android Runtime (ART) 提前编译器可进一步优化压缩的 Dalvik 可执行文件 格式 (DEX) 文件,方法是将应用软件包中的 DEX 文件转换为 压缩表示法。此变更可让您的应用更快地启动并使用 磁盘空间和 RAM 更少。

这一改进特别有利于磁盘 I/O 较慢的低端设备 速度。

设备端系统跟踪

Android 9 可让您录制设备的系统轨迹, 然后与开发团队分享这些录制内容的报告。此报告 支持多种格式,包括 HTML。

通过收集这些跟踪记录,您可以捕获与应用的 进程和线程,以及查看其他类型的具有全局意义的设备 状态。

如需详细了解此工具,请参阅执行设备上的系统 跟踪记录