Android Q 为用户和开发者引入了强大的新功能。本文重点介绍面向开发者的新功能。
要了解新版 API,请阅读 API 差异报告或访问 Android API 参考。为醒目起见,将突出显示新版 API。此外,请务必查阅 Android Q 行为变更(针对以 Android Q 为目标平台的应用和所有应用)以及隐私权变更,以了解平台变更可能给您的应用带来哪些方面的影响。
Android Q 引入了若干安全功能,详见以下各节摘要说明:
改进了生物识别身份验证对话框
Android Q 对 Android 9 中增加的统一生物识别身份验证对话框进行了以下改进:
您现在可以提供一个提示,以告知系统在用户使用隐式生物识别模式完成身份验证后无需要求用户进行确认。例如,您可以告知系统,在用户使用面孔身份验证完成身份验证后无需进行进一步确认。
默认情况下,系统会要求用户进行确认。通常,用户希望确认敏感或高风险的操作(例如,购买商品)。但是,如果您的应用存在某些低风险操作,那么您就可以将 false 传递至 setRequireConfirmation() 方法,提供不要求用户确认的提示。由于此标记作为提示传递到系统,因此如果用户更改了针对生物识别身份验证的系统设置,则系统可能会忽略相应的值。
您现在可以告知系统,如果用户因某种原因而无法使用其生物识别输入设备,则可以使用设备 PIN 码、图案或密码来进行身份验证。要启用此回退支持,请使用 setAllowDeviceCredential() 方法。
如果您的应用目前使用 createConfirmDeviceCredentialIntent() 来回退到设备凭据,请改为使用新方法。
现在,您可以在调用 BiometricPrompt 之前,先使用 BiometricManager 类中的 canAuthenticate() 方法检查设备是否支持生物识别身份验证。
您现在可以告知平台直接从应用的 APK 文件中运行嵌入式 DEX 代码。如果攻击者曾设法篡改了设备上本地编译的代码,则此选项有助于防止相应攻击。
注意:启用此功能可能会影响应用的性能,因为在应用启动时 ART 必须使用 JIT 编译器(而不是读取提前编译的原生代码)。我们建议您先测试应用性能,然后再决定是否在已发布的应用中启用此功能。
要启用此功能,请在应用清单文件的
Gradle
aaptOptions {
noCompress 'dex'
}
Bazel
android_binary(
...,
nocompress_extensions = [“.dex”],
)
现在,平台的 TLS 实现支持 TLS 1.3。TLS 1.3 是 TLS 标准的主要修订版本,它提升了性能和安全性。我们的基准测试数据表明,与 TLS 1.2 相比,使用 TLS 1.3 可以将建立安全连接的速度提高 40%。
默认情况下,系统会为所有 TLS 连接启用 TLS 1.3。您可以通过调用 SSLContext.getInstance("TLSv1.2") 来获取停用 TLS 1.3 的 SSLContext。您还可以对相关对象调用 setEnabledProtocols() 来为每个连接来启用或停用协议版本。
以下是有关 TLS 1.3 实现的一些重要的详细信息:
公共 Conscrypt API
现在,Conscrypt 安全提供程序包含适用于 TLS 功能的公共 API。过去,用户可以通过反射来访问此功能。但是,由于在 Android P 中增加了关于调用非公共 API 的限制,因此这已在 Android Q 中加入了灰名单,并将在未来版本中进一步受限。
此更新在 android.net.ssl 下增加了一组类,这些类包含用于访问通用 javax.net.ssl API 不提供的功能的静态方法。这些类的名称为相关 javax.net.ssl 类的复数,用户可以由此推断是否为这些类。例如,在 javax.net.ssl.SSLSocket 实例中运行的代码可以使用新的 android.net.ssl.SSLSockets 类中的方法。
ELF TLS
使用 API 级别 29 及更高版本的 NDK 编译的应用无需再使用 emutls,但可以改为使用 ELF TLS。我们增加了对动态和静态链接器的支持,以支持处理线程局部变量的新方法。
对于针对 API 级别 28 及更低版本编译的应用,我们实现了针对 libgcc/compiler-rt 的改进,以便解决一些 emutls 问题。
有关详情,请参阅面向 NDK 开发者的 Android 变更。
Android Q 包含一些与网络和连接相关的改进。
WLAN 网络连接 API
Android Q 增加了对点对连接的支持。借助此功能,应用可以提示用户更改设备连接到的接入点。点对点连接用于“非网络提供”目的,例如 Chromecast 和 Google Home 硬件等辅助设备的引导配置。
点对点连接不需要位置权限。如果您发起连接到对等设备的请求,便会在对方设备上启动一个对话框,让相应设备的用户可以通过此对话框来接受连接请求。
WLAN 网络建议 API
Android Q 扩大了支持范围,现在允许应用提示用户连接到 WLAN 接入点。您可以提供关于要连接到哪个网络的建议。平台最终会根据来自您的应用和其他应用的输入来选择要接受的接入点。
来自应用的建议必须先得到用户批准,然后平台才会发起到建议的网络的连接。当平台第一次在扫描结果中找到与应用提供的其中一个建议相匹配的网络时,将由用户响应通知进行批准。当平台连接到建议的其中某个网络时,设置会显示相关文本以将网络连接归因于提出建议的相应应用。
改进了 WLAN 高性能和低延迟模式
借助 Android Q,您可以为底层调制解调器提供提示,以最大限度地缩短延迟。
Android Q 扩展了 WLAN Lock API,以有效地支持高性能和低延迟模式。系统会针对高性能和低延迟模式停用 WLAN 节能模式,并且您可以在低延迟模式下启用进一步的延迟优化(具体取决于调制解调器支持)。
仅当获取锁的应用在前台运行且屏幕处于开启状态时才能启用低延迟模式。低延迟模式对实时移动游戏应用尤其有用。
DNS 解析器中的专用查找
先前版本的 Android 信息和运营商服务使用 org.xbill.DNS2 软件包来执行 NAPTR 和 SRV 查询。Android Q 增加了对“通过传输层安全协议 (TLS) 执行 DNS”的原生支持,以进行专用 DNS 查找。这项新增功能可以为开发者提供标准明文查找和“通过传输层安全协议 (TLS) 执行 DNS”模式。
WLAN Easy Connect
借助 Android Q,您可以利用 Easy Connect 为使用 URI 的对等设备配置 WLAN 凭据。您可以通过各种方法来检索此 URI,包括从 QR 码或者通过蓝牙 LE 或 NFC。
当 URI 可用时,您可以立即使用 ACTION_PROCESS_WIFI_EASY_CONNECT_QR_CODE Intent 来配置对等设备的 WLAN 凭据。这样一来,用户就可以选择 WLAN 网络以共享并安全地传输相关凭据。
注意:在使用此 Intent 之前,应用必须先通过调用 WifiManager.isEasyConnectSupported() 来验证设备是否支持 Easy Connect。
WLAN 直连连接 API
WifiP2pConfig 和 WifiP2pManager API 类在 Android Q 中有更新,以支持利用预先确定的信息快速与 WLAN 直连建立连接的功能。此信息通过边信道进行共享,例如蓝牙或 NFC。
以下代码示例显示了如何使用预先确定的信息来创建群组:
val manager = getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager
val channel = manager.initialize(this, mainLooper, null)
// prefer 5G band for this group
val config = WifiP2pConfig.Builder()
.setNetworkName("networkName")
.setPassphrase("passphrase")
.enablePersistentMode(false)
.setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_5GHZ)
.build()
// create a non-persistent group on 5GHz
manager.createGroup(channel, config, null)
要使用凭据加入群组,请将 manager.createGroup() 替换为以下内容:
manager.connect(channel, config, null)
借助 Android Q,您的应用可以使用 BLE CoC 连接在两个 BLE 设备之间传输较大的数据流。此接口抽象化处理了蓝牙和连接机制,以简化实现。
Android Q 包含一些与电话相关的改进。
通话质量方面的改进
Android Q 增加了在支持相关功能的设备上收集进行中的 IP 多媒体子系统 (IMS) 通话质量相关信息的功能,包括通过网络接听和拨打电话的质量。
选接电话和来电显示
Android Q 让您的应用可以将用户通讯录中不存在号码的来电标识为潜在骚扰电话,以及代表用户拒接骚扰电话而不响铃。系统会在通话记录中将这些已屏蔽的来电的相关信息记录为已屏蔽的来电,以便用户更清楚地了解何时有过未接来电。使用此新版 API,不需要从用户获取 READ_CALL_LOG 权限就可以提供选接电话和来电显示功能。
您还可以配置应用,让其提供来电者的相关信息(例如公司名称、Facebook 联系信息等),这些信息会显示在平台的拨号器应用中。
Call Redirection Service API
Android Q 更改了来电 Intent 的处理方式。我们弃用了 NEW_OUTGOING_CALL 广播,并将其替换为 CallRedirectionService API。CallRedirectionService 提供了相关接口,以供您修改 Android 平台拨打的去电。例如,第三方应用可能会取消通话并通过 VoIP 对其进行重新路由。
媒体和图形
Android Q 引入了以下媒体和图形方面的新功能和 API:
借助 Android Native MIDI API (AMidi),应用开发者可以使用 C/C++ 代码发送和接收 MIDI 数据、与 C/C++ 音频/控制逻辑进行更紧密的集成以及最大限度地减少对 JNI 的需求。
有关详情,请参阅 Android Native MIDI API。
MediaCodecInfo 方面的改进
MediaCodecInfo 中有一些新方法可以显示有关编解码器的更多信息:
isSoftwareOnly()
如果编解码器仅在软件中运行,则返回 true。软件编解码器并不能保证渲染性能。
isHardwareAccelerated()
如果编解码器由硬件加速,则返回 true。
isVendor()
如果编解码器由设备供应商提供,则返回 true;如果由 Android 平台提供,则返回 false。
isAlias()
MediaCodecList 可能针对使用备用编解码器名称(别名)的同一底层编解码器包含额外的条目。如果此条目中的编解码器是另一个编解码器的别名,则此方法会返回 true。
此外,MediaCodec.getCanonicalName() 会针对通过别名创建的编解码器返回底层编解码器名称。
“性能点”表示编解码器以特定高度、宽度和帧速率渲染视频的能力。例如,UHD_60 性能点表示以每秒 60 帧的速度渲染超高清视频(3840x2160 像素)。
方法 MediaCodecInfo.VideoCapabilities.getSupportedPerformancePoints() 会返回编解码器可以渲染或捕获的 PerformancePoint 条目列表。
您可以通过调用 PerformancePoint.covers(PerformancePoint) 来检查给定的 PerformancePoint 是否会覆盖另一个性能点。例如,UHD_60.covers(UHD_50) 会返回 true。
我们为所有硬件加速的编解码器都提供了性能点列表。如果编解码器连标准性能点的最低值都不能满足,则此列表可能为空。
请注意,已升级到 Android Q 但未更新供应商映像的设备是没有性能点数据的,因为此数据来自供应商 HAL。在这种情况下,getSupportedPerformancePoints() 会返回 null。
Android 9(API 等级 28)首次引入了单色摄像头功能。Android Q 为单色摄像头支持增加了几项增强功能:
您可以使用此功能来捕捉原生单色图片。逻辑多摄像头设备可以使用单色摄像头作为物理子摄像头,以获取更出色的低光图片质量。
从 Android Q 开始,摄像头可以使用名为“动态深度格式”(DDF) 的新架构将图片的深度数据存储在单独的文件中。应用可以请求 JPG 图片及其深度元数据,以便在后期处理中利用这些信息来应用所需的模糊处理,而无需修改原始图片数据。
在 Android Q 发布后,Android 开发者和合作伙伴可以选择使用 ANGLE 运行,这是 Chrome 组织中的一个项目,能够将 ES 置于 Vulkan 上层,而不必使用供应商提供的 ES 驱动程序。
有关详情,请参阅 ANGLE。
Android Q 引入了以下新的无障碍服务功能和 API:
AccessibilityNodeInfo 输入键标记
在 Android Q 中,AccessibilityNodeInfo 得到了增强,现在增加了一个新标记,用于指示其是否代表文本输入键的。您可以使用 AccessibilityNodeInfo.isTextEntryKey() 方法来访问此标记。
无障碍对话框语音反馈
当无障碍服务要求用户重复按无障碍快捷方式以启动服务时,此对话框现在可以在服务请求时附带文字转语音提示。
物理键盘的无障碍快捷方式
在 Android Q 中,用户现在可以通过物理键盘来触发无障碍快捷方式,只需按 Control+Alt+Z 即可。
软键盘控制器增强功能
在 Android Q 中,无障碍服务现在可以请求显示软键盘,即使设备检测到连接了硬键盘也不例外。用户可以替换此行为。
用户定义的无障碍服务超时
Android Q 引入了 API 方法 AccessibilityManager.getRecommendedTimeoutMillis(),用于为用户针对互动式和非互动式的无障碍界面元素定义的超时提供支持。返回值受用户偏好设置和无障碍服务 API 的影响。
Android Q 包含对自动填充服务的以下改进。
与兼容性相关的自动填充请求
您现在可以使用 FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST 标记来确定是否通过兼容性模式生成了自动填充请求。
同时保存用户名和密码
您现在可以支持应用使用多个活动来显示用户名、密码和其他字段的情况,只需使用 SaveInfo.FLAG_DELAY_SAVE 标记即可。
用户与保存界面的互动
您现在可以在保存对话框中显示和隐藏密码字段,只需在此对话框中设置操作监听器,并更改相应密码远程视图的可见性即可。
支持更新数据集
现在,自动填充功能可以更新现有密码。例如,如果用户已经存储了一个密码,然后又保存了一个新密码,则自动填充功能现在会提示用户更新现有密码,而不是保存新密码。
Android Q 包含对 Field Classification API 的以下改进。
UserData.Builder 构造函数
UserData.Builder 构造函数已更改,以更好地符合 Builder 模式的要求。
允许将一个值映射到多种类别 ID
在使用 Android Q 中的 UserData.Builder 时,您现在可以将一个值映射到多种类别 ID。在以前的版本中,如果一个值被添加多次,系统就会抛出异常。
改进了对信用卡号码的支持
现在,字段分类可以检测四位数字作为信用卡号码的最后四位数字。
支持特定于应用的字段分类
Android Q 增加了 FillResponse.setUserData(),让您能够在会话期间设置特定于应用的用户数据。这有助于自动填充服务检测包含特定于应用的内容的字段的类型。
Android Q 提供以下界面方面的改进:
支持 JVMTI PopFrame 功能
Android Q 增加了对 Android JVMTI 实现中的 can_pop_frames 功能的支持。在调试时,此功能让您能够在断点暂停并调整函数的局部变量、全局变量或实现,然后重新运行函数。有关详情,请参阅 Oracle 的 Pop Frame 参考页面。
Surface Control API
Android Q 提供了一个 SurfaceControl API,用于对系统合成器 (SurfaceFlinger) 进行底层访问。对于大多数用户而言,SurfaceView 是使用此合成器的正确方法。SurfaceControl API 在某些情况下很有用,例如:
SurfaceControl API 在 SDK 和 NDK 绑定中都可用。NDK 实现包含用于与合成器手动交换缓冲区的 API。这为遇到 BufferQueue 限制的用户提供了一种替代方案。
WebView 挂起渲染程序检测
Android Q 引入了一个新的 WebViewRendererClient 抽象类,应用可以使用它来检测 WebView 是否无响应。要使用此类,请执行以下操作:
如果 WebView 保持无响应状态,则系统会定期调用 onRendererUnresponsive()(不超过每五秒钟一次),但不会执行任何其他操作。如果 WebView 再次无响应,系统只会调用 onRendererResponsive() 一次。
设置面板
Android Q 引入了“设置面板”,这是一种 API,让应用能够在自身环境中向用户显示设置。这可以避免用户转到设置更改 NFC 或移动数据等设置,以便使用此应用。
图 1. 用户尝试在设备未连接到网络时打开网页。Chrome 弹出互联网连接设置面板…
图 2. 用户可以开启 WLAN 并选择网络,而无需离开 Chrome 应用。
例如,假设用户打开了网络浏览器,而其设备已开启飞行模式。在 Android Q 之前的版本中,此应用只能显示一条通用消息,要求用户打开设置以恢复连接。而借助 Android Q,浏览器应用便可以显示一个内嵌面板,其中会显示各种主要连接设置,例如飞行模式、WLAN(包括附近的网络)和移动数据。借助此面板,用户无需离开应用即可恢复连接。
要显示设置面板,请使用以下其中一项新推出的 Settings.Panel 操作触发一个 Intent:
val panelIntent = Intent(Settings.Panel.settings_panel_type)
startActivityForResult(panelIntent)
settings_panel_type 可以是下列项之一:
我们计划针对此功能引入一个 AndroidX 封装容器。在搭载 Android 9(API 级别 28)或更低级别的设备上调用时,此封装容器会在设置应用中打开最合适的页面。
Android Q 为共享功能提供了多项改进。要了解所有详情,请参阅 Android Q 中共享功能方面的改进。
角色
Android Q 引入了一种标准工具,即“角色”。借助此工具,操作系统可以根据易于理解的用例授予应用越权访问系统功能和用户数据的权限。在语义上,每个角色都代表着一个常见的用例,例如播放音乐、管理照片或发送短信。
从测试版 1 开始,平台就为 Android Q 提供了一组预定义的角色。应用可以使用新的 RoleManager 类来查询可用角色并发出担任特定角色的请求。
要详细了解角色如何影响 Android Q 中应用的行为,请参阅角色预览指南。
Kotlin
Android Q 对 Kotlin 开发进行了以下更新。
libcore API 的可空性注释
Android Q 改进了 SDK 中针对 libcore API 的可空性注释的覆盖范围。借助这些注释,在 Android Studio 中使用 Kotlin 或 Java 可空性分析的应用开发者可以在与这些 API 互动时获取非 Null 信息。
通常,Kotlin 中的为空性合同违规行为会导致编译错误。为确保与现有代码兼容,所有新注释都仅限于 @RecentlyNullable 和 @RecentlyNonNull。这意味着为空性违规行为会引发警告,而不是错误。
此外,Android 9 中添加的所有 @RecentlyNullable 或 @RecentlyNonNull 注释都会分别更改为 @Nullable和 @NonNull。这意味着为空性违规行为现在会引发错误,而不是警告。
要详细了解注释方面的变更,请参阅 Android 开发者博客中的 Android Pie SDK 现已更适用于 Kotlin一文。
NDK
Android Q 包含以下 NDK 方面的变更。
触发基于 Mallinfo 的垃圾回收
当小型平台 Java 对象引用 C++ 堆中的大型对象时,通常只有在系统已回收并(举例而言)最终确定 Java 对象后,才能回收 C++ 对象。在之前的版本中,平台会估算与 Java 对象相关联的许多 C++ 对象的大小。这种估算并不总是准确,并且偶尔会导致内存使用量大大增加,因为平台无法在应该进行垃圾回收时完成回收。
在 Android Q 中,垃圾回收器 (GC) 会跟踪系统 malloc() 分配的堆的总大小,以确保 malloc() 分配的大型堆始终包含在可触发 GC 的计算中。因此,与 Java 执行交错大量 C++ 分配的应用可能会出现垃圾回收频率提高的现象。其他应用的频率则可能会略有下降。
改进了文件描述符所有权的调试
Android Q 增加了 fdsan,它可以帮助您更轻松地查找和修复文件描述符所有权方面的问题。
与错误处理文件描述符所有权相关的错误(通常表现为“use-after-close”和“double-close”)类似于内存分配“use-after-free”和“double-free”错误,但通常更难以诊断和修复。“fdsan”会尝试通过强制执行文件描述符所有权来检测和/或防止文件描述符误管理。
要详细了解与这些问题相关的崩溃,请参阅 fdsan 检测到的错误。要详细了解 fdsan,请参阅关于 fdsan 的 Googlesource 页面。