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 米。

凭借这种精准度,您可以打造新的体验,例如楼内导航、基于精确位置的服务,如无歧义语音控制(例如,“打开这盏灯”)以及基于位置的信息(例如,“此产品是否有特别优惠?”)。

您可以在 Android WifiRttScan 演示应用中查看 Wi-Fi RTT API 的使用情况。

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

刘海屏支持

显示各种屏幕缺口尺寸的开发者选项界面

使用模拟器测试刘海屏

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

全新的窗口布局属性 layoutInDisplayCutoutMode 让您的应用可以为设备屏幕缺口周围的内容进行布局。您可以将此属性设置为以下某个值:

您可以按如下方法在任何搭载 Android 9 的设备或模拟器上模拟屏幕缺口:

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

通知

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

即时通讯通知

附带照片的 MessagingStyle。

即时通讯通知

包含回复和对话的 MessagingStyle。

如需查看使用通知(包括 Android 9 中的功能)的示例代码,请参阅 People 示例

增强的即时通讯体验

从 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() 方法允许您为操作提供语义含义,如“标记为已读”“删除”“回复”等。

  • 智能回复:Android 9 支持在您的即时通讯应用中提供相同的建议回复。使用 RemoteInput.setChoices() 为用户提供一组标准回复。

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

Android 8.0 引入了通知渠道,允许您为要显示的每种通知类型创建用户可自定义的渠道。Android 9 通过下列变更简化通知渠道设置:

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

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

摄像头方面的其他改进还包括附加的会话参数,有助于降低首次拍照期间的延迟,而 Surface 共享则让摄像头客户端能够处理各种用例,而无需停止并启动摄像头视频流。我们还针对基于显示屏的闪光灯支持OIS 时间戳访问新增了一些 API,用以实现应用级的图像稳定化和特效。

在 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,您可以通过字节缓冲区、文件或 URI 创建 DrawableBitmap。要解码图像,请先调用 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 的动画。 渲染线程还使用工作线程进行解码,因此解码 会干扰渲染线程上的其他操作。这种实现机制允许您的应用在显示动画图像时,无需管理其更新,也不会干扰应用界面线程上的其他事件。

您可以使用 ImageDecoder 的实例对 AnimatedImageDrawable 进行解码。以下 代码段展示了如何使用 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 提供对 High Dynamic Range (HDR) VP9 Profile 2 的内置支持,因此您可以在支持 HDR 的设备上为用户提供来自 YouTube、Play 电影和其他来源的采用 HDR 的影片。

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

还可通过 AudioTrackAudioRecordMediaDrm 类获取媒体指标。

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 可正确处理工作。在执行作业时,请务必使用 JobParameters.getNetwork() 返回的 Network 对象。否则,您将隐式使用设备的默认网络 可能不符合您的要求,从而导致意外的流量消耗。

Neural Networks API 1.1

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

已知问题:将 ANEURALNETWORKS_TENSOR_QUANT8_ASYMM 张量传递给 Android 9 及更高版本中提供的 ANEURALNETWORKS_PAD 运算时,NNAPI 的输出可能与更高层级机器学习框架(如 TensorFlow Lite)的输出不匹配。在问题得到解决之前,您应改为只传递 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 密钥库确认消息的有效性之后,您的应用可以使用在可信执行环境 (TEE) 下通过 trustedConfirmationRequired 生成的密钥来签署用户已接受的消息。通过 签名具有很高的可信度,表示用户已经看到了 并同意该声明。

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

如需获得 Android Protected Confirmation 新增支持方面的指导,请参阅 Android Protected Confirmation 指南。

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

在 Android 9 中,系统代表您的应用提供生物识别身份验证对话框。此功能可创建标准化的对话框外观、风格和位置,让用户更加确信,他们在使用可信的生物识别凭据检查程序进行身份验证。

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

硬件安全模块

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

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

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

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

安全地将密钥导入密钥库

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

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

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

Android 9 新增了对 APK Signature Scheme v3 的支持。该架构提供的选择可以在其签名块中为每个签名证书加入一条轮替证据记录。借助此功能,您可以使用新的签名对您的应用进行签名 将 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 开始,如果将 View 对象标记为可聚焦会产生不良后果,则可以使用 android:screenReaderFocusable 属性代替 android:focusable 属性。屏幕阅读器会聚焦在所有将 android:screenReaderFocusableandroid: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 运行时 (ART) 提前编译器通过将应用软件包中的 DEX 文件转换为更紧凑的表示形式,进一步优化了压缩的 Dalvik 可执行格式 (DEX) 文件。此变更可让您的应用更快地启动并使用 磁盘空间和 RAM 更少。

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

设备端系统跟踪

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

通过收集这些轨迹,您可以获取与应用进程和线程相关的计时数据,并查看其他类型的具有全局意义的设备状态。

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