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 编译器(而不是读取提前编译好的原生代码)。我们建议您先测试应用性能,然后再决定是否在已发布的应用中启用此功能。
要启用此功能,请在应用清单文件的 元素中将 android:useEmbeddedDex
属性的值设为 true
。您还必须编译一个 APK,其中要包含 ART 可以直接访问的未压缩 DEX 代码。将以下选项添加到 Gradle 或 Bazel 配置文件,以编译包含未压缩 DEX 代码的 APK:
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 实现的一些重要的详细信息:
• TLS 1.3 加密套件不可自定义。在启用 TLS 1.3 后,受支持的 TLS 1.3 加密套件会始终保持启用状态,并且系统会忽略所有试图通过调用
setEnabledCipherSuites()
将其停用的行为。
• 在协商 TLS 1.3 时,系统会在将会话添加到会话缓存之前调用HandshakeCompletedListeners
(这与 TLS 1.2 和之前的其他版本不同)。
• 在之前本应抛出SSLHandshakeException
的某些情况下,SSLEngine
实例会抛出SSLProtocolException
。
• 不支持 0-RTT 模式。
现在,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
类中的方法。
Android Q 包含一些与网络和连接相关的改进。
Android Q 增加了对点对连接的支持。借助此功能,应用可以通过使用 NetworkSpecifier
来提示用户更改设备连接到的接入点,以描述请求的网络的属性。点对点连接用于“非网络提供”目的,例如 Chromecast 和 Google Home 硬件等辅助设备的引导配置。
点对点连接不需要位置权限。如果您发起连接到对等设备的请求,便会在对方设备上启动一个对话框,让相应设备的用户可以通过此对话框来接受连接请求。
Android Q 扩大了支持范围,现在允许应用提示用户连接到 WLAN 接入点。您可以使用 WifiNetworkSuggestion
来提供关于要连接到哪个网络的建议。平台最终会根据来自您的应用和其他应用的输入来选择要接受的接入点。
来自应用的建议必须先得到用户批准,然后平台才会发起到建议的网络的连接。当平台第一次在扫描结果中找到与应用提供的其中一个建议相匹配的网络时,将由用户响应通知进行批准。当平台连接到建议的其中某个网络时,设置会显示相关文本,将网络连接归因于提出建议的相应应用。
借助 Android Q,您可以为底层调制解调器提供提示,以最大限度地缩短延迟。
Android Q 扩展了 WLAN Lock API,以有效地支持高性能和低延迟模式。系统会针对高性能和低延迟模式停用 WLAN 节能模式,并且您可以在低延迟模式下启用进一步的延迟优化(具体取决于调制解调器支持)。
仅当获取锁的应用在前台运行且屏幕处于开启状态时才能启用低延迟模式。低延迟模式对实时移动游戏应用尤其有用。
Android Q 增加了对“通过传输层安全协议 (TLS) 执行 DNS”的原生支持,以进行专用 DNS 查找。以前,平台 DNS 解析器支持 A 类解析,它可以根据域名来解析 IP 地址,而无需与通过此 IP 提供的服务有关的具体信息。经过此次更新,它现在还支持 SRV 和 NAPTR 查找。
Android Q 可以为开发者提供标准明文查找和“通过传输层安全协议 (TLS) 执行 DNS”模式。
借助 Android Q,您可以利用 Easy Connect 为对等设备配置 WLAN 凭据,以替代已弃用的 WPS。应用可以使用 ACTION_PROCESS_WIFI_EASY_CONNECT_URI
intent
将 Easy Connect 集成到其设置和配置流程中。此 intent 需要 URI。调用应用可以通过各种方法来检索 URI,包括扫描贴纸或显示屏中的 QR 码,或通过扫描蓝牙 LE 或 NFC 广告。
当 URI 可用时,您可以立即使用 ACTION_PROCESS_WIFI_EASY_CONNECT_URI
intent
来配置对等设备的 WLAN 凭据。这样一来,用户就可以选择 WLAN 网络以共享并安全地传输相关凭据。
注意:在使用此 intent 之前,应用必须先通过调用 WifiManager.isEasyConnectSupported()
来验证设备是否支持 Easy Connect。
WifiP2pConfig
和 WifiP2pManager
API 类在 Android Q 中有更新,以支持利用预先确定的信息快速与 WLAN 直连建立连接的功能。此信息通过边信道进行共享,例如蓝牙或 NFC。
以下代码示例显示了如何使用预先确定的信息来创建群组:
Kotlin
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)
Java
WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);
// prefer 5G band for this group
WifiP2pConfig config = new 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()
替换为以下内容:
Kotlin
manager.connect(channel, config, null)
Java
manager.connect(channel, config, null);
借助 Android Q,您的应用可以使用 BLE CoC 连接在两个 BLE 设备之间传输较大的数据流。此接口抽象化处理了蓝牙和连接机制,以简化实现。
Android Q 包含一些与电话相关的改进。
Android Q 增加了在支持相关功能的设备上收集进行中的 IP 多媒体子系统 (IMS) 通话质量相关信息的功能,包括通过网络接听和拨打电话的质量。
Android Q 让您的应用可以将用户通讯录中不存在号码的来电标识为潜在骚扰电话,以及代表用户拒接骚扰电话而不响铃。系统会在通话记录中将这些已屏蔽的来电的相关信息记录为已屏蔽的来电,以便用户更清楚地了解何时有过未接来电。使用此新版 API,不需要从用户获取 READ_CALL_LOG
权限就可以提供选接电话和来电显示功能。
您还可以配置应用,让其提供来电者的相关信息(例如公司名称、Facebook 联系信息等),这些信息会显示在平台的拨号器应用中。
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
中有一些新方法可以显示有关编解码器的更多信息:
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 为单色摄像头支持增加了几项增强功能:
• 新增了对 Y8 流格式的支持,以提高内存效率。
• 支持单色原始 DNG 捕获。
• 引入了 MONO 和 NIR CFA 枚举,以区分常规单色摄像头和近红外摄像头。
您可以使用此功能来捕捉原生单色图片。逻辑多摄像头设备可以使用单色摄像头作为物理子摄像头,以获取更出色的低光图片质量。
从 Android Q 开始,摄像头可以使用名为“动态深度格式”(DDF) 的新架构将图片的深度数据存储在单独的文件中。应用可以请求 JPG 图片及其深度元数据,以便在后期处理中利用这些信息来应用所需的模糊处理,而无需修改原始图片数据。
在 Android Q 发布后,Android 开发者和合作伙伴可以选择使用 ANGLE 运行,这是 Chrome 组织中的一个项目,能够将 ES 置于 Vulkan 上层,而不必使用供应商提供的 ES 驱动程序。
有关详情,请参阅 ANGLE。
Android Q 引入了以下新的无障碍服务功能和 API:
在 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
构造函数已更改,以更好地符合 Builder
模式的要求。
在使用 Android Q 中的 UserData.Builder
时,您现在可以将一个值映射到多种类别 ID。在以前的版本中,如果一个值被添加多次,系统就会抛出异常。
现在,字段分类可以检测四位数字作为信用卡号码的最后四位数字。
Android Q 增加了 FillResponse.setUserData()
,让您能够在会话期间设置特定于应用的用户数据。这有助于自动填充服务检测包含特定于应用的内容的字段的类型。
Android Q 提供以下界面方面的改进:
Android Q 增加了对 Android JVMTI 实现中的 can_pop_frames
功能的支持。在调试时,此功能让您能够在断点暂停并调整函数的局部变量、全局变量或实现,然后重新运行函数。有关详情,请参阅 Oracle 的 Pop Frame 参考页面。
Android Q 提供了一个 SurfaceControl
API,用于对系统合成器 (SurfaceFlinger
) 进行底层访问。对于大多数用户而言,SurfaceView
是使用此合成器的正确方法。SurfaceControl
API 在某些情况下很有用,例如:
• 同步多个表面
• 跨进程的表面嵌入
• 底层生命周期管理
SurfaceControl
API 在 SDK 和 NDK 绑定中都可用。NDK 实现包含用于与合成器手动交换缓冲区的 API。这为遇到 BufferQueue
限制的用户提供了一种替代方案。
Android Q 引入了一个新的 WebViewRendererClient
抽象类,应用可以使用它来检测 WebView
是否无响应。要使用此类,请执行以下操作:
- 定义自己的子类,并实现其
onRendererResponsive()
和onRendererUnresponsive()
方法。- 将
WebViewRendererClient
的实例附加到一个或多个WebView
对象。- 如果
WebView
无响应,则系统会调用客户端的onRendererUnresponsive()
方法以传递WebView
和WebViewRenderer
(如果WebView
是单进程,则WebViewRenderer
参数为null
)。您的应用可以执行适当的操作,例如向用户显示一个对话框,以询问其是否要暂停渲染流程。
如果WebView
保持无响应状态,则系统会定期调用onRendererUnresponsive()
(不超过每五秒钟一次),但不会执行任何其他操作。如果WebView
再次无响应,系统只会调用onRendererResponsive()
一次。
Android Q 引入了“设置面板”,这是一种 API,让应用能够在自身环境中向用户显示设置。这可以避免用户转到设置更改 NFC 或移动数据等设置,以便使用此应用。
例如,假设用户打开了网络浏览器,而其设备已开启飞行模式。在 Android Q 之前的版本中,此应用只能显示一条通用消息,要求用户打开设置以恢复连接。而借助 Android Q,浏览器应用便可以显示一个内嵌面板,其中会显示各种主要连接设置,例如飞行模式、WLAN(包括附近的网络)和移动数据。借助此面板,用户无需离开应用即可恢复连接。
要显示设置面板,请使用以下其中一项新推出的 Settings.Panel
操作触发一个 intent
:
Kotlin
val panelIntent = Intent(Settings.Panel.settings_panel_type)
startActivityForResult(panelIntent)
Java
Intent panelIntent = new Intent(Settings.Panel.settings_panel_type);
startActivityForResult(panelIntent);
settings_panel_type
可以是下列项之一:
ACTION_INTERNET_CONNECTIVITY
显示与互联网连接相关的设置,例如飞行模式、WLAN 和移动数据。ACTION_WIFI
:显示 WLAN 设置,但不显示其他连接设置。这对于需要 WLAN 连接以执行大容量上传或下载的应用非常有用。ACTION_NFC
显示与近距离无线通信 (NFC) 相关的所有设置。ACTION_VOLUME
显示所有音频流的音量设置。
我们计划针对此功能引入一个 AndroidX 封装容器。在搭载 Android 9(API 级别 28)或更低级别的设备上调用时,此封装容器会在设置应用中打开最合适的页面。
Android Q 为共享功能提供了多项改进。要了解所有详情,请参阅 Android Q 中共享功能方面的改进。
Android Q 对 Kotlin 开发进行了以下更新。
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一文。
Android Q 包含以下 NDK 方面的变更。
Android Q 增加了 fdsan,它可以帮助您更轻松地查找和修复文件描述符所有权方面的问题。
与错误处理文件描述符所有权相关的错误(通常表现为“use-after-close”和“double-close”)类似于内存分配“use-after-free”和“double-free”错误,但通常更难以诊断和修复。“fdsan”会尝试通过强制执行文件描述符所有权来检测和/或防止文件描述符误管理。
要详细了解与这些问题相关的崩溃,请参阅 fdsan 检测到的错误。要详细了解 fdsan,请参阅关于 fdsan 的 Googlesource 页面。
使用 API 级别 29 及更高版本的 NDK 编译的应用无需再使用 emutls,但可以改为使用 ELF TLS。我们增加了对动态和静态链接器的支持,以支持处理线程局部变量的新方法。
对于针对 API 级别 28 及更低版本编译的应用,我们实现了针对 libgcc/compiler-rt 的改进,以便解决一些 emutls 问题。
有关详情,请参阅面向 NDK 开发者的 Android 变更。
Android Q 包含以下运行时方面的变更。
当小型平台 Java 对象引用 C++ 堆中的大型对象时,通常只有在系统已回收并(举例而言)最终确定 Java 对象后,才能回收 C++ 对象。在之前的版本中,平台会估算与 Java 对象相关联的许多 C++ 对象的大小。这种估算并不总是准确,并且偶尔会导致内存使用量大大增加,因为平台无法在应该进行垃圾回收时完成回收。
在 Android Q 中,垃圾回收器 (GC) 会跟踪系统 malloc() 分配的堆的总大小,以确保 malloc()
分配的大型堆始终包含在可触发 GC 的计算中。因此,与 Java 执行交错大量 C++ 分配的应用可能会出现垃圾回收频率提高的现象。其他应用的频率则可能会略有下降。
Android Q 包含以下测试和调试方面的改进。
现在,您在执行设备上系统跟踪时可以指定跟踪的记录大小和持续时间限制。在您指定任一值后,系统便会执行长期跟踪,并在记录跟踪时定期将跟踪缓冲区复制到目标文件。在达到您指定的记录大小或持续时间限制后,跟踪便会完成。
请使用这些附加参数来测试除了您使用标准跟踪进行测试的用例之外的其他用例。例如,您可能正在诊断某个性能错误,而此错误仅在您的应用长时间运行后才会发生。在这种情况下,您可以记录为期一整天的长期跟踪,然后分析 CPU 调度程序、磁盘活动、应用线程以及报告中的其他数据,以帮助您确定造成此错误的原因。
Android Q 功能和 API: https://developer.android.google.cn/preview/features.html