元素。 如果您的应用请求了 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION,系统会自动将 ACCESS_BACKGROUND_LOCATION 添加到请求中。 在设备升级到 Android 10 后访问 如果用户向您的应用授予对设备位置信息的访问权限(ACCESS_COARSE_LOCATION 或 ACCESS_FINE_LOCATION),然后将其设备从 Android 9 升级到 Android 10,则系统会自动更新应用已获取的基于位置信息的那组权限。您的应用在设备升级后接收的那组权限取决于应用的目标 SDK 版本及其定义的权限,如下表所示: 表 1. 设备升级至 Android 10 之后位置权限状态发生的变化 目标平台版本 是否授予了粗略或精确位置信息使用权限? 清单中是否定义了后台权限? 更新后的默认权限状态 Android 10 是 是 前台和后台访问权 Android 10 是 否 仅前台访问权 Android 10 否 (被系统忽略) 无访问权 Android 9 或更低版本 是 在设备升级时由系统自动添加 前台和后台访问权 Android 9 或更低版本 否 (被系统忽略) 无访问权 注意:即使在系统自动更新应用对设备位置信息的访问权限之后,用户仍然可以选择更改这种访问权限级别。用户可以选择让应用只能在前台访问位置信息,或者完全撤消使用权。在尝试访问设备的位置信息之前,尤其是在前台服务中,您的应用应检查用户是否仍然允许您的应用接收此类位置信息。 如需详细了解如何在应用在后台运行时检索设备的位置信息,请参阅有关如何定期接收位置信息更新的指南。 针对从后台启动 Activity 的限制 从 Android 10 开始,系统会增加针对从后台启动 Activity 的限制。此项行为变更有助于最大限度地减少对用户造成的中断,并且可以让用户更好地控制其屏幕上显示的内容。只要您的应用启动 Activity 是因用户互动直接引发的,该应用就极有可能不会受到这些限制的影响。 要详细了解从后台启动 Activity 的建议替代方法,请参阅有关如何在应用中提醒用户注意有时效性的事件的指南。 标识符和数据 本部分列出了针对如何使用标识符和数据的变更。 移除了联系人亲密程度信息 从 Android 10 开始,平台不再跟踪联系人亲密程度信息。因此,如果您的应用对用户的联系人进行搜索,系统将不会按互动频率对搜索结果排序。 有关 ContactsProvider 的指南包含一项描述特定字段和方法的声明(从 Android 10 开始,这些字段和方法在所有设备上已作废)。 随机分配 MAC 地址 默认情况下,在搭载 Android 10 或更高版本的设备上,系统会传输随机分配的 MAC 地址。 如果您的应用处理企业使用场景,平台会提供 API,用于执行与 MAC 地址相关的几个操作。 获取随机分配的 MAC 地址:设备所有者应用和资料所有者应用可以通过调用 getRandomizedMacAddress() 检索分配给特定网络的随机分配 MAC 地址。 获取实际的出厂 MAC 地址:设备所有者应用可以通过调用 getWifiMacAddress() 检索设备的实际硬件 MAC 地址。此方法对于跟踪设备队列非常有用。 对 /proc/net 文件系统的访问权限实施了限制 在搭载 Android 10 或更高版本的设备上,应用无法访问 /proc/net,其中包含与设备的网络状态相关的信息。需要访问这些信息的应用(如 VPN)应使用 NetworkStatsManager 或 ConnectivityManager 类。 对不可重置的设备标识符实施了限制 从 Android 10 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能访问设备的不可重置标识符(包含 IMEI 和序列号)。 注意:从 Google Play 商店安装的第三方应用无法声明特许权限。 受影响的方法包括: Build getSerial() TelephonyManager getImei() getDeviceId() getMeid() getSimSerialNumber() getSubscriberId() 如果您的应用没有该权限,但您仍尝试查询不可重置标识符的相关信息,则平台的响应会因目标 SDK 版本而异: 如果应用以 Android 10 或更高版本为目标平台,则会发生 SecurityException。 如果应用以 Android 9(API 级别 28)或更低版本为目标平台,则相应方法会返回 null 或占位符数据(如果应用具有 READ_PHONE_STATE 权限)。否则,会发生 SecurityException。 注意:如果您的应用是设备所有者或资料所有者应用,那么即使您的应用以 Android 10 或更高版本为目标平台,您也只需 READ_PHONE_STATE 权限即可访问不可重置的设备标识符。此外,如果您的应用具有特殊运营商权限,则无需任何权限即可访问这些标识符。 许多使用场景都不需要不可重置的设备标识符。例如,如果您的应用将不可重置的设备标识符用于广告跟踪或用户分析目的,请为这些特定使用场景使用 Android 广告 ID。要了解详情,请参阅唯一标识符的最佳做法。 限制了对剪贴板数据的访问权限 除非您的应用是默认输入法 (IME) 或是目前处于焦点的应用,否则它无法访问 Android 10 或更高版本平台上的剪贴板数据。 保护 USB 设备序列号 如果您的应用以 Android 10 或更高版本为目标平台,则该应用只能在用户授予其访问 USB 设备或配件的权限后才能读取序列号。 要详细了解如何使用 USB 设备,请参阅有关如何配置 USB 主机的指南。 摄像头和连接性 本部分列出了针对摄像头元数据和连接 API 的变更。 对访问摄像头详情和元数据的权限实施了限制 Android 10 更改了 getCameraCharacteristics() 方法默认返回的信息的广度。具体而言,您的应用必须具有 CAMERA 权限才能访问此方法的返回值中可能包含的设备特定元数据。 要详细了解这些变更,请参阅关于需要权限的摄像头字段。 对启用和停用 WLAN 实施了限制 以 Android 10 或更高版本为目标平台的应用无法启用或停用 WLAN。WifiManager.setWifiEnabled() 方法始终返回 false。 如果您需要提示用户启用或停用 WLAN,请使用设置面板。 对直接访问已配置的 WLAN 网络实施了限制 为了保护用户隐私,只有系统应用和设备政策控制器 (DPC) 支持手动配置 WLAN 网络列表。给定 DPC 可以是设备所有者,也可以是资料所有者。 如果应用以 Android 10 或更高版本为目标平台,并且应用不是系统应用或 DPC,则下列方法不会返回有用数据: getConfiguredNetworks() 方法始终返回空列表。 注意:如果运营商应用调用 getConfiguredNetworks(),则系统返回的列表仅包含运营商配置的网络。 每个返回整数值的网络操作方法(addNetwork() 和 updateNetwork())始终返回 -1。 每个返回布尔值的网络操作(removeNetwork()、reassociate()、enableNetwork()、disableNetwork()、reconnect() 和 disconnect())始终返回 false。 如果您的应用需要连接到 WLAN 网络,请使用以下备用方法: 要触发与 WLAN 网络的即时本地连接,请在标准 NetworkRequest 对象中使用 WifiNetworkSpecifier。 要添加 WLAN 网络以便考虑为用户提供互联网访问权限,请使用 WifiNetworkSuggestion 对象。您可以分别通过调用 addNetworkSuggestions() 和 removeNetworkSuggestions() 来添加和移除显示在自动连接网络选择对话框中的网络。这些方法不需要任何位置权限。 一些电话 API、蓝牙 API 和 WLAN API 需要精确位置权限 如果应用以 Android 10 或更高版本为目标平台,则它必须具有 ACCESS_FINE_LOCATION 权限才能使用 WLAN、WLAN 感知或蓝牙 API 中的一些方法。以下部分列举了受影响的类和方法。 注意:如果您的应用在 Android 10 或更高版本平台上运行,但其目标平台是 Android 9(API 级别 28)或更低版本,则只要您的应用已声明 ACCESS_COARSE_LOCATION 或 ACCESS_FINE_LOCATION 权限,您就可以使用受影响的 API(WifiP2pManager API 除外)。 电话 TelephonyManager getCellLocation() getAllCellInfo() requestNetworkScan() requestCellInfoUpdate() getAvailableNetworks() getServiceState() TelephonyScanManager requestNetworkScan() TelephonyScanManager.NetworkScanCallback onResults() PhoneStateListener onCellLocationChanged() onCellInfoChanged() onServiceStateChanged() WLAN WifiManager startScan() getScanResults() getConnectionInfo() getConfiguredNetworks() WifiAwareManager WifiP2pManager WifiRttManager 蓝牙 BluetoothAdapter startDiscovery() startLeScan() BluetoothAdapter.LeScanCallback BluetoothLeScanner startScan() 权限 本部分介绍了 Android 权限模型的相关更新。 注意:本部分中介绍的每项变更均会影响搭载 Android 10 或更高版本的设备上的所有应用,甚至是以 Android 9(API 级别 28)或更低版本为目标平台的应用。 限制对屏幕内容的访问 为了保护用户的屏幕内容,Android 10 更改了 READ_FRAME_BUFFER、CAPTURE_VIDEO_OUTPUT 和 CAPTURE_SECURE_VIDEO_OUTPUT 权限的作用域,从而禁止以静默方式访问设备的屏幕内容。从 Android 10 开始,这些权限只能通过签名访问。 需要访问设备屏幕内容的应用应使用 MediaProjection API,此 API 会显示提示,要求用户同意访问。 面向用户的权限检查(针对旧版应用) 如果您的应用以 Android 5.1(API 级别 22)或更低版本为目标平台,则用户首次在搭载 Android 10 或更高版本的平台上使用您的应用时,系统会向其显示权限屏幕,如图 1 所示。此屏幕让用户有机会撤消系统先前在安装时向应用授予的访问权限。 注意:如果您要在 Google Play 上发布应用,则必须以 Android 9(API 级别 28)或更高版本为目标平台。要了解详情,请参阅有关如何符合 Google Play 的目标 API 级别要求的指南。 图 1. 面向用户的对话框,允许查看旧版权限 身体活动识别 Android 10 针对需要检测用户步数或对用户的身体活动(例如步行、骑车或坐车)进行分类的应用引入了 ACTIVITY_RECOGNITION 运行时权限。此项权限旨在让用户了解设备传感器数据在“设置”中的使用方式。 除非用户已向您的应用授予此权限,否则 Google Play 服务中的一些库(例如 Activity Recognition API 和 Google Fit API)不会提供结果。 设备上要求您声明此权限的内置传感器只有计步器和步测器传感器。 如果您的应用以 Android 9(API 级别 28)或更低版本为目标平台,并在其清单文件中指定 com.google.android.gms.permission.ACTIVITY_RECOGNITION 权限,则系统会根据需要自动向您的应用授予此权限。当您将应用更新为以 Android 10 为目标平台时,平台会保留此权限。但是,用户可以随时在系统设置中撤消此权限。 从界面中移除了权限组 从 Android 10 开始,应用无法在界面中查询权限的分组方式。 行为变更:所有应用 目录 限制非 SDK 接口 手势导航 NDK 共享对象不得包含文本重定位 Bionic 库和动态链接器路径变更 系统二进制文件/库会映射到只执行内存 安全 TLS 1.3 默认处于启用状态 TLS 不信任使用 SHA-1 签名的证书 KeyChain 行为变更和改进 其他 TLS 和加密更改 WLAN 直连广播 WLAN 感知功能 Go 设备上的 SYSTEM_ALERT_WINDOW 关于以旧版 Android 系统为目标平台的应用的警告 移除了 SHA-2 CBC 加密套件 应用使用情况 HTTPS 连接变更 android.preference 库已弃用 ZIP 文件实用程序库变更 Inflater ZipFile ZipOutputStream 摄像头变更 电池用量跟踪 Android Beam 已弃用 Android 10 包含一些可能会影响您的应用的行为变更。本文档中列出的变更适用于在 Android 10 上运行的应用(无论应用的 targetSdkVersion 如何)。您应该测试您的应用,然后根据需要进行更改以适当地支持这些变更。 如果您的应用的 targetSdkVersion 为 29 或更高,则您还需要支持其他变更。请务必查看针对以 API 级别 29 为目标的应用的行为变更,以了解详情。 注意:在本文档中,除了这些行为变更之外,请确保查看并支持 Android 10 隐私功能。 限制非 SDK 接口 为了帮助确保应用的稳定性和兼容性,Android 平台开始限制应用在 Android 9(API 级别 28)中使用非 SDK 接口。Android 10 包含更新后的受限制非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。我们的目标是在限制使用非 SDK 接口之前确保有可用的公开替代方案。 如果您不打算以 Android 10(API 级别 29)为目标平台,那么其中一些变更可能不会立即对您产生影响。虽然您目前仍然可以使用灰名单中的一些非 SDK 接口(取决于您的应用的目标 API 级别),但如果您使用任何非 SDK 方法或字段,则应用无法运行的风险终归较高。 如果您不确定自己的应用是否使用了非 SDK 接口,则可以测试该应用,进行确认。如果您的应用依赖于非 SDK 接口,则应该开始计划迁移到 SDK 替代方案。不过,我们知道某些应用具有使用非 SDK 接口的有效用例。如果您无法为应用中的某项功能找到使用非 SDK 接口的替代方案,则应该请求新的公共 API。 要了解详情,请参阅 Android 10 中有关限制非 SDK 接口的更新以及针对非 SDK 接口的限制。 手势导航 从 Android 10 开始,用户可以在设备中启用手势导航。用户启用后,手势导航会影响设备上的所有应用,无论应用是否以 API 级别 29 为目标平台。例如,如果用户从屏幕边缘向内滑动,系统会将该手势解读为“返回”导航,除非应用针对屏幕的相应部分明确替换该手势。 为了确保您的应用与手势导航兼容,您需要将应用内容扩展到屏幕边缘,并适当地处理存在冲突的手势。有关信息,请参阅手势导航文档。 NDK Android 10 包含 NDK 方面的以下变更。 共享对象不得包含文本重定位 Android 6.0(API 级别 23)已禁止在共享对象中使用文本重定位。代码必须按原样加载,且不得修改。此变更可以缩短应用的加载时间并提高安全性。 SELinux 针对以 Android 10 或更高版本为目标平台的应用强制执行此限制。如果这些应用继续使用包含文本重定位的共享对象,则它们出现中断的风险较高。 Bionic 库和动态链接器路径变更 从 Android 10 开始,多个路径不再采用常规文件形式,而是采用符号链接形式。如果应用一直以来依赖的都是采用常规文件形式的路径,则可能会出现中断: /system/lib/libc.so -> /apex/com.android.runtime/lib/bionic/libc.so /system/lib/libm.so -> /apex/com.android.runtime/lib/bionic/libm.so /system/lib/libdl.so -> /apex/com.android.runtime/lib/bionic/libdl.so /system/bin/linker -> /apex/com.android.runtime/bin/linker 这些变更也会影响文件的 64 位版本,对于这些版本,系统会将 lib/ 替换为 lib64/。 为了确保兼容性,符号链接会基于旧路径提供。例如,/system/lib/libc.so 是指向 /apex/com.android.runtime/lib/bionic/libc.so 的符号链接。因此,dlopen(“/system/lib/libc.so”) 会继续工作,但当应用尝试通过读取 /proc/self/maps 或类似项来检测已加载的库时,将会发现不同之处。这并不常见,但我们发现一些应用会将这种做法作为对抗黑客攻击的一项举措。如果是这样,则应该将 /apex/… 路径添加为 Bionic 文件的有效路径。 系统二进制文件/库会映射到只执行内存 从 Android 10 开始,系统二进制文件和库的可执行部分会映射到只执行(不可读取)内存,作为防范代码重用攻击的一种安全强化技术。如果您的应用针对已标记为只执行的内存段执行读取操作(无论此读取操作是来自错误、漏洞还是有意的内存检查),系统都会向您的应用发送 SIGSEGV 信号。 您可以通过检查 /data/tombstones/ 中的相关 tombstone 文件来确定此行为是否会导致崩溃。与只执行相关的崩溃包含以下中止消息: Cause: execute-only (no-read) memory access error; likely due to data in .text. 要解决此问题以执行内存检查等操作,可以通过调用 mprotect() 将只执行内存段标记为“读取+执行”。不过,我们强烈建议您事后将其重新设为只执行,因为此访问权限设置可以更好地保护您的应用和用户。 注意:此行为不会对 ptrace 的调用产生影响,可允许您调试 ptrace。 安全 Android 10 包含安全方面的以下变更。 TLS 1.3 默认处于启用状态 在 Android 10 及更高版本中,系统默认会为所有 TLS 连接启用 TLS 1.3。以下是有关 TLS 1.3 实现的一些重要的详细信息: TLS 1.3 加密套件不可自定义。在启用 TLS 1.3 后,受支持的 TLS 1.3 加密套件会始终保持启用状态。任何尝试通过调用 setEnabledCipherSuites() 停用该加密套件的操作均会被忽略。 在协商 TLS 1.3 时,系统会在将会话添加到会话缓存之前调用 HandshakeCompletedListener 对象。(在 TLS 1.2 和之前的其他版本中,系统会在将会话添加到会话缓存之后调用这些对象。) 在某些情况下,SSLEngine 实例会在之前的 Android 版本中抛出 SSLHandshakeException,而这些实例在 Android 10 及更高版本中会改为抛出 SSLProtocolException。 不支持 0-RTT 模式。 如有需要,您可以通过调用 SSLContext.getInstance("TLSv1.2") 来获取已停用 TLS 1.3 的 SSLContext。您还可以对相关对象调用 setEnabledProtocols(),从而为每个连接启用或停用协议版本。 TLS 不信任使用 SHA-1 签名的证书 在 Android 10 中,使用 SHA-1 哈希算法的证书在 TLS 连接中不受信任。自 2016 年以来,根 CA 未再颁发过此类证书,因为它们不再受 Chrome 或其他主流浏览器的信任。 如果某网站使用的是 SHA-1 证书,则任何尝试连接该网站的操作都将失败。 KeyChain 行为变更和改进 当 TLS 服务器在 TLS 握手中发送证书请求消息时,某些浏览器(如 Google Chrome)允许用户选择证书。从 Android 10 开始,KeyChain 对象会在调用 KeyChain.choosePrivateKeyAlias() 时信任颁发机构和密钥规范参数,以向用户显示证书选择提示。需要注意的是,此提示不包含不符合服务器规范的选项。 如果没有可用的用户可选证书(当没有与服务器规范匹配的证书或设备没有安装任何证书时,便会出现这种情况),则完全不会出现证书选择提示。 此外,在 Android 10 或更高版本上,无需具备设备屏幕锁定功能,就能将密钥或 CA 证书导入 KeyChain 对象中。 其他 TLS 和加密更改 Android 10 中引入的 TLS 和加密库方面的一些细小变更包括: AES/GCM/NoPadding 和 ChaCha20/Poly1305/NoPadding 加密会从 getOutputSize() 中返回更准确的缓冲区大小。 使用 TLS 1.2 或更高版本的最高协议在尝试连接时会忽略 TLS_FALLBACK_SCSV 加密套件。由于 TLS 服务器实现方面的改进,我们不建议尝试 TLS 外部回退。不过,我们建议依赖于 TLS 版本协商。 ChaCha20-Poly1305 是 ChaCha20/Poly1305/NoPadding 的别名。 带有尾随点的主机名不属于有效的 SNI 主机名。 为证书响应选择签名密钥时,将遵循 CertificateRequest 中的 supported_signature_algorithms 扩展。 不透明的签名密钥(如 Android 密钥库中的密钥)可在 TLS 中与 RSA-PSS 签名一起使用。 WLAN 直连广播 在 Android 10 中,以下与 WLAN 直连相关的广播不具有粘性: WIFI_P2P_CONNECTION_CHANGED_ACTION WIFI_P2P_THIS_DEVICE_CHANGED_ACTION 如果您的应用依赖于在注册时接收这些广播(因为其之前一直具有粘性),请在初始化时使用适当的 get() 方法获取信息。 WLAN 感知功能 Android 10 扩大了支持范围,现在可以使用 WLAN 感知数据路径轻松创建 TCP/UDP 套接字。要创建连接到 ServerSocket 的 TCP/UDP 套接字,客户端设备需要知道服务器的 IPv6 地址和端口。这在之前需要通过频外方式进行通信(例如使用 BT 或 WLAN 感知第 2 层消息传递),或者使用其他协议(例如 mDNS)通过频内方式发现。而借助 Android 10,可以将此类消息作为网络设置的一部分进行传递。 服务器可以执行以下任一操作: 初始化 ServerSocket 并设置或获取要使用的端口。 将端口信息指定为 WLAN 感知网络请求的一部分。 以下代码示例显示了如何将端口信息指定为网络请求的一部分: KotlinJava更多 val ss = ServerSocket() val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("some-password") .setPort(ss.localPort) .build() val myNetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(ns) .build() ServerSocket ss = new ServerSocket(); WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier .Builder(discoverySession, peerHandle) .setPskPassphrase(“some-password”) .setPort(ss.getLocalPort()) .build(); NetworkRequest myNetworkRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(ns) .build(); 然后,客户端会执行 WLAN 感知网络请求来获取服务器提供的 IPv6 和端口: KotlinJava更多 val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { ... } override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { ... } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { ... val ti = networkCapabilities.transportInfo if (ti is WifiAwareNetworkInfo) { val peerAddress = ti.peerIpv6Addr val peerPort = ti.port } } override fun onLost(network: Network) { ... } }; connMgr.requestNetwork(networkRequest, callback) callback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { ... } @Override public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { ... } @Override Public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { ... TransportInfo ti = networkCapabilities.getTransportInfo(); if (ti instanceof WifiAwareNetworkInfo) { WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti; Inet6Address peerAddress = info.getPeerIpv6Addr(); int peerPort = info.getPort(); } } @Override public void onLost(Network network) { ... } }; connMgr.requestNetwork(networkRequest, callback); Go 设备上的 SYSTEM_ALERT_WINDOW 在 Android 10(Go 版本)设备上运行的应用无法获得 SYSTEM_ALERT_WINDOW 权限。这是因为绘制叠加层窗口会使用过多的内存,这对低内存 Android 设备的性能十分有害。 如果在搭载 Android 9 或更低版本的 Go 版设备上运行的应用获得了 SYSTEM_ALERT_WINDOW 权限,则即使设备升级到 Android 10,也会保留此权限。不过,尚不具有此权限的应用在设备升级后便无法获得此权限了。 如果 Go 设备上的应用发送具有 ACTION_MANAGE_OVERLAY_PERMISSION 操作的 intent,则系统会自动拒绝此请求,并将用户转到设置屏幕,上面会显示不允许授予此权限,原因是它会减慢设备的运行速度。如果 Go 设备上的应用调用 Settings.canDrawOverlays(),则此方法始终返回 false。同样,这些限制不适用于在设备升级到 Android 10 之前便已收到 SYSTEM_ALERT_WINDOW 权限的应用。 关于以旧版 Android 系统为目标平台的应用的警告 在搭载 Android 10 或更高版本的设备上,如果用户首次运行以 Android 5.1(API 级别 22)或更低版本为目标平台的应用,则会看到警告。如果此应用要求用户授予权限,则系统会先向用户提供调整应用权限的机会,然后才会允许此应用首次运行。 由于 Google Play 的目标 API 方面的要求,用户只有在运行最近未更新的应用时才会看到这些警告。对于通过其他商店分发的应用,我们也将于 2019 年引入类似的目标 API 方面的要求。如需详细了解这些要求,请参阅在 2019 年扩展目标 API 级别方面的要求。 移除了 SHA-2 CBC 加密套件 以下 SHA-2 CBC 加密套件已从平台中移除: TLS_RSA_WITH_AES_128_CBC_SHA256 TLS_RSA_WITH_AES_256_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 这些加密套件不如使用 GCM 的类似加密套件安全,并且大多数服务器要么同时支持这些加密套件的 GCM 变体和 CBC 变体,要么二者均不支持。 注意:应用和库应该让其所需的加密套件集与 getSupportedCipherSuites() 中返回的值相交,以便提前防范加密套件日后遭到移除。 应用使用情况 Android 10 引入了与应用使用情况相关的以下行为变更: UsageStats 应用使用情况方面的改进 - 当在分屏或画中画模式下使用应用时,Android 10 现在能够使用 UsageStats 准确地跟踪应用使用情况。此外,Android 10 可以正确地跟踪免安装应用的使用情况。 按应用开启灰度模式 - Android 10 可针对各个应用设置灰度显示模式。 按应用开启干扰模式 - Android 10 可以选择性地将应用设置为“干扰模式”,此时系统会禁止显示其通知,并且不会将其显示为推荐的应用。 暂停和播放 - 在 Android 10 中,暂停的应用无法播放音频。 HTTPS 连接变更 如果在 Android 10 上运行的应用将 null 传递给 setSSLSocketFactory(),则会出现 IllegalArgumentException。在以前的版本中,将 null 传递给 setSSLSocketFactory() 与传入当前的默认 SSL 套接字工厂效果相同。 android.preference 库已弃用 从 Android 10 开始,将弃用 android.preference 库。开发者应该改为使用 AndroidX preference 库,这是 Android Jetpack 的一部分。如需获取其他有助于迁移和开发的资源,请查看经过更新的设置指南以及我们的公开示例应用和参考文档。 ZIP 文件实用程序库变更 Android 10 对 java.util.zip 软件包(用于处理 ZIP 文件)中的类进行了以下变更。这些变更会让库的行为在 Android 和使用 java.util.zip 的其他平台之间更加一致。 Inflater 在以前的版本中,如果在调用 end() 之后调用 Inflater 类中的某些方法,这些方法会抛出 IllegalStateException。在 Android 10 中,这些方法会改为抛出 NullPointerException。 ZipFile 在 Android 10 及更高版本中,如果所提供的 ZIP 文件不包含任何文件,则 ZipFile 的构造函数(采用的参数类型为 File、int 和 Charset)不会抛出 ZipException。 ZipOutputStream 在 Android 10 及更高版本中,如果 ZipOutputStream 中的 finish() 方法尝试为不包含任何文件的 ZIP 文件写入输出流,则此方法不会抛出 ZipException。 摄像头变更 很多使用摄像头的应用都会假定如果设备采用纵向配置,则物理设备也会处于纵向,正如摄像头方向中所述。在过去可以做出这样的假定,但随着可用的设备类型(例如可折叠设备)的扩展,这一情况发生了变化。针对这些设备做出这样的假定可能导致相机取景器的显示产生错误的旋转和/或缩放。 以 API 级别 24 或更高级别为目标平台的应用应该明确设置 android:resizeableActivity,并提供必要的功能来处理多窗口操作。 电池用量跟踪 从 Android 10 开始,只要在发生重大充电事件之后拔下设备电源插头,SystemHealthManager 就会重置其电池用量统计信息。一般来说,重大充电事件指的是设备电池已充满,或者设备电量从几乎耗尽变为即将充满。 在 Android 10 之前,无论何时拔下设备电源插头,无论电池电量有多微小的变化,电池用量统计信息都会重置。 Android Beam 已弃用 在 Android 10 中,我们正式弃用了 Android Beam,这是一项旧版功能,可通过近距离无线通信 (NFC) 在多个设备之间启动数据共享。我们还弃用了一些相关的 NFC API。Android Beam 仍可供需要的设备制造商合作伙伴使用,但它已不再处于积极的开发阶段。不过,Android 仍将继续支持其他的 NFC 功能和 API,并且从标签和付款中读取数据等使用场景仍将继续按预期执行。 面向开发者的 Android 10 目录 创新技术和新体验 可折叠设备 5G 网络 通知中的智能回复 深色主题 手势导航 设置面板 共享快捷方式 用户隐私设置 安全性 摄像头和媒体 照片的动态深度 捕获播放的音频 新的音频和视频编解码器 原生 MIDI API 可缩放的定向麦克风 Vulkan 无处不在 连接性 改进了点对点连接和互联网连接 WLAN 性能模式 Android 基础知识 ART 优化 Neural Networks API 1.2 Thermal API 通过公共 API 实现兼容性 更新速度更快,代码更新频率更高 开始使用 Android 10 围绕三个重要主题构建而成。首先,Android 10 以其先进的机器学习和对新兴设备(如可折叠设备和支持 5G 的手机)的支持走在移动创新领域的前沿。其次,Android 10 的主要关注点之一就是隐私权和安全性,其中近 50 项功能可为用户提供更好的保护、更高的透明度以及让用户更好地控制相关数据。最后,Android 10 可让用户更好地控制数字健康,因此个人和家庭都可以更好地利用此项技术。 下面,我们来介绍一下 Android 10 为开发者提供了哪些功能以及您现在能如何利用这些功能。 创新技术和新体验 借助 Android 10,您可以充分利用最新的硬件和软件创新,从而为用户打造出色的应用体验。 借助 Android 10,您可以针对可折叠设备和其他大屏幕设备优化应用。 可折叠设备 Android 10 基于强大的多窗口支持构建而成,扩展了跨应用窗口的多任务处理能力,还提供了屏幕连续性,可以在设备折叠或展开时维持应用状态。Android 10 在 onResume 和 onPause 中添加了多项改进,用于支持多项恢复,并在应用获得焦点时通知应用。它还更改了 resizeableActivity 清单属性的工作方式,以帮助您管理应用在可折叠设备和大屏幕设备上的显示方式。为帮助针对可折叠设备进行编译,您可以在 Android Studio 中配置可折叠模拟器来用作虚拟设备 (AVD)。如需详细了解如何针对可折叠设备优化应用,请参阅开发者指南。 5G 网络 5G 有望在稳定提升速度的同时降低延迟,Android 10 新增了针对 5G 的平台支持,并扩展了现有 API 来帮助您充分利用这些增强功能。您可以使用连接 API 来检测设备是否具有高带宽连接,还可以检查连接是否按流量计费。借助这些功能,您的应用和游戏可以为使用 5G 的用户量身打造丰富的沉浸式体验。 通知中的智能回复 Android 10 使用设备上的机器学习在通知中提供上下文操作建议,如智能回复消息或在通知中打开某个地址的地图。您的应用可以立即充分利用此功能,而您无需执行任何操作。系统提供的智能回复和操作默认直接插入到通知中。您仍可以根据需要自行提供回复或操作。使用 setAllowGeneratedReplies() 和 setAllowSystemGeneratedContextualActions() 即可针对每则通知选择停用智能回复。 智能回复可以根据通知内容提供操作建议。 深色主题 Android 10 新增了一个系统级的深色主题,非常适合光线较暗的场景并能帮助节省电量。用户转至“设置”进行相应设置或开启“省电模式”即可激活新的系统级深色主题。这会将系统界面更改为深色,并为支持深色主题的应用启用深色主题。您可以为应用构建自定义深色主题,也可以选择使用新的 Force Dark 功能,让系统根据现有主题动态创建深色版本。您还可以充分利用 AppCompat 的 DayNight 功能,为使用早期版本的 Android 的用户提供深色主题。如需了解详情,请参阅开发者指南。 Android 10 可以利用 Force Dark 为应用动态创建深色主题。 手势导航 手势导航可让应用全屏显示内容。 Android 10 引入了全手势导航模式,该模式不显示通知栏区域,允许应用使用全屏来提供更丰富、更让人沉浸的体验。它通过边缘滑动(而不是可见的按钮)保留了用户熟悉的“返回”、“主屏幕”和“最近”导航。要与手势导航无缝融合,您应顺着边缘在导航栏后方绘制,以打造沉浸式体验。要实现这一点,应用应使用 setSystemUiVisibility() API 以全屏模式布局,然后相应地处理 WindowInsets,以确保重要的界面区域未被遮挡。立即开始优化您的应用,并查看我们的博文系列,以了解详情。 设置面板 现在,您可以通过新的设置面板 API 在应用上下文中直接显示关键系统设置。设置面板是浮动界面,您可以通过调用它来显示用户可能需要使用的设置,如互联网连接、NFC 和音量。例如,浏览器可以显示具有飞行模式、WLAN(包括附近网络)和移动数据等连接设置的面板。要显示设置面板,只需发出具有某个新 Settings.Panel 操作的 intent。 共享快捷方式 共享快捷方式功能可使共享更加轻松快捷,让用户能够直接跳转到其他应用来共享内容。开发者可以发布能在应用中启动特定 Activity 的共享目标,同时附上内容;这些共享目标会在共享界面中向用户显示。因为共享目标是提前发布的,所以共享界面会在启动后立即加载它们。共享快捷方式类似于应用快捷方式,都使用同一个 ShortcutInfo API。ShareTarget AndroidX 库也支持此 API。如需了解详情,请参阅示例应用。 共享快捷方式可让用户直接跳转到应用中的特定 Activity,同时附上内容。 用户隐私设置 隐私权是 Android 10 的其中一个主要关注点,相关改进包括在平台中提供更强大的保护措施以及在设计新功能时谨记隐私性。Android 10 基于先前版本构建,并引入了大量变更(如改进了系统界面、让权限授予更加严格以及对应用能够使用哪些数据实施了限制),目的是保护隐私权并赋予用户更多控制权。如需详细了解如何在您的应用中支持这些变更,请参阅隐私权变更。 用户现在可以选择在应用在前台运行时授予其访问位置信息的权限。 赋予用户对位置数据的更多控制权 - 用户可以通过新的权限选项更好地控制他们的位置数据;现在,他们可以允许应用仅在实际使用(在前台运行)时访问位置信息。对于大部分应用来说,这提供了足够的访问级别;而对于用户来说,这在确保透明度和控制权方面是一项重大改进。要详细了解位置信息方面的变更,请参阅开发者指南或我们的博文。 在扫描网络时保护位置数据 - 用于扫描网络的大多数 API 都需要粗略位置权限。Android 10 改为要求精确位置权限,由此来增强对这些 API 的防御。 阻止设备跟踪 - 应用无法再访问不可重置的设备标识符(可用于跟踪),包括设备 IMEI、序列号和类似标识符。设备的 MAC 地址也会默认在连接到 WLAN 网络时随机分配。请阅读最佳做法,其中的内容有助于您为具体使用场景选择合适的标识符;同时点击此处了解详情。 保护外部存储设备中的用户数据 - Android 10 引入了一些变更,目的是让用户更好地控制外部存储设备中的文件以及其中的应用数据。应用可以将自己的文件存储在专用沙盒中,但必须使用 MediaStore 来访问共享媒体文件,并使用系统文件选择器访问新的“下载内容”集合中的共享文件。如需了解详情,请点击此处。 屏蔽意外中断 - Android 10 可阻止应用从后台启动,从后台启动会使应用意外跳转到前台并从其他应用获得焦点。如需了解详情,请点击此处。 安全性 Android 10 引入了多项功能,可通过加密、平台安全强化和身份验证方面的改进为用户提供更高的安全性。请详细阅读此处的 Android 10 安全更新。 存储加密 - 搭载 Android 10 的所有兼容设备都必须加密用户数据;为了提高加密效率,Android 10 引入了我们的新加密模式 Adiantum。 默认启用 TLS 1.3 - Android 10 还默认启用 TLS 1.3,它是 TLS 标准的主要修订版本,具有性能优势和更高的安全性。 平台安全强化 - Android 10 还引入了针对平台几个关键安全区域的安全强化功能。 改进了生物识别功能 - Android 10 扩展了 BiometricPrompt 框架,以支持被动身份验证方法,如人脸识别以及添加隐式和显式身份验证流程。在显式流程中,用户必须在身份验证期间明确确认 TEE 中的事务。对于需要被动身份验证的事务,隐式流程是一种更轻量的替代方案。Android 10 还改进了按需回退设备凭据的流程。如需了解详情,请点击此处。 摄像头和媒体 照片的动态深度 应用现在可以请求动态深度图片,其中包含与深度相关元素有关的 JPEG、XMP 元数据,以及嵌入在同一文件中的深度和置信度映射。这些功能让您可以在应用中提供专用模糊和散景选项。动态深度是用于生态系统的一种开源格式,我们正在与合作伙伴合作,以将其推广到搭载 Android 10 及更高版本的设备。 您可以利用动态深度图片在应用中提供专用模糊和散景选项。 捕获播放的音频 现在,播放音频的任何应用都允许其他应用使用新的音频播放捕获 API 捕获其音频流。除了能够启用字幕之外,此 API 还可让您支持常见的使用场景(如直播游戏)。我们在构建这项新功能时考虑了隐私性和版权保护,因此,应用捕获其他应用音频的功能会受限,这会让应用全权控制其音频流是否可以被捕获。如需了解详情,请阅读这篇博文。 新的音频和视频编解码器 Android 10 新增了对开源视频编解码器 AV1 的支持,这允许媒体提供商使用更少的带宽向 Android 设备流式传输高品质视频内容。此外,Android 10 还支持使用 Opus(一种针对语音和音乐流式传输进行了优化的开放且免版税的编解码器)和 HDR10+(用于支持它的设备上的高动态范围视频)对音频进行编码。MediaCodecInfo API 引入了一种更简便的方法来确定某个 Android 设备的视频渲染功能。对于任何指定的编解码器,您可以获取其支持的大小和帧速率列表。 原生 MIDI API 针对使用 C++ 执行其音频处理的应用,Android 10 引入了原生 MIDI API,以通过 NDK 与 MIDI 设备通信。此 API 允许使用非阻塞读取在音频回调内检索 MIDI 数据,从而以低延迟处理 MIDI 消息。使用示例应用和此处的源代码试试看。 可缩放的定向麦克风 Android 10 可让您通过新的 MicrophoneDirection API 更好地控制音频捕获。您可以使用此 API 指定在录音时麦克风的首选方向。例如,当用户在进行视频“自拍”时,您可以请求前置麦克风(如果有)以进行录音。此外,此 API 还引入了控制可缩放麦克风的标准化方法,允许您的应用控制录音字段大小。 Vulkan 无处不在 Android 10 包含用于绘制高性能 3D 图形的低开销、跨平台 API 实现,扩大了 Vulkan 的影响范围。所有搭载 Android 10 及更高版本的 64 位设备现在都要求使用 Vulkan 1.1,也建议在所有 32 位设备上使用 Vulkan 1.1。我们已经看到整个生态系统大力支持 Vulkan 的强劲势头,在搭载 Android N 或更高版本的设备中,53% 的设备都支持 Vulkan 1.0.3 或更高版本。随着 Android 10 中相关新要求的推出,我们预计未来一年 Vulkan 的采用率将进一步提升。 连接性 改进了点对点连接和互联网连接 我们重构了 WLAN 堆栈,目的是改进隐私设置和性能,同时改进常见使用场景(如管理 IoT 设备以及提供互联网连接建议),而无需请求位置权限。网络连接 API 针对点对点功能(如配置、下载或打印)简化了通过本地 WLAN 管理 IoT 设备的操作。网络建议 API 可让应用向用户显示首选 WLAN 网络以进行互联网连接。 WLAN 性能模式 应用现在可以通过启用高性能和低延迟模式来请求自适应 WLAN。如果低延迟对用户体验(如实时游戏、活跃语音通话以及类似使用场景)至关重要,这些模式会极具优势。平台与设备固件配合使用,可以满足最低耗电量的要求。要使用新的性能模式,请调用 WifiManager.WifiLock.createWifiLock()(使用 WIFI_MODE_FULL_LOW_LATENCY 或 WIFI_MODE_FULL_HIGH_PERF)。在这些模式中,平台与设备固件配合使用,可以满足最低耗电量的要求。 Android 基础知识 ART 优化 在 ART 运行时方面的改进可帮助您的应用更快地启动、占用更少的内存并更顺畅地运行,而您无需执行任何操作。借助 Google Play 提供的 ART 配置文件,ART 在应用运行之前就可以预先编译应用组件。在运行时,Android 10 向 ART 的并发复制 (CC) 垃圾回收器添加了分代垃圾回收功能,以节省垃圾回收的时间并提高 CPU 效率,减少卡顿,同时帮助应用在低端设备上更顺畅地运行。 上图以百分比形式显示了具体应用在使用 Play 配置文件进行测试后启动时间的缩短幅度。 Neural Networks API 1.2 我们新增了 60 项操作(包括 ARGMAX、ARGMIN 和量化 LSTM),并进行了一系列性能优化。这为加速更多模型奠定了基础,比如对象检测模型和图像分割模型。我们与硬件供应商合作,并使用常见的机器学习框架(如 TensorFlow),以针对 NNAPI 1.2 进行优化并提供支持。 Thermal API 当设备过热时,它们可能会限制 CPU 和/或 GPU,而这可能会以意想不到的方式影响应用和游戏。现在,在 Android 10 中,应用和游戏可以使用 Thermal API 监控设备变化情况,并在设备过热时采取措施,使设备恢复到正常温度。例如,影音在线播放应用可以降低分辨率/比特率或减少网络流量;相机应用可以停用闪光灯或密集型图像增强;游戏可以降低帧速率或减少多边形曲面细分。如需了解详情,请点击此处。 通过公共 API 实现兼容性 Android 10 继续增加了对非 SDK 接口的限制,以便应用逐步转为仅使用公共 API。如果您目前使用的接口受到限制,则可以选择针对该接口请求新的公共 API。为了帮助您完成过渡并防止应用中断,我们仅在您的应用以 Android 10 (API 29) 为目标平台时实施这些限制。如需详细了解这些限制,请参阅开发者指南。 更新速度更快,代码更新频率更高 Android 10 可通过 Treble 计划加快更新速度,这可在 Android 与设备制造商和芯片制造商提供的底层设备代码之间提供一致的可测试接口。借助 Treble 计划,设备制造商能够以更快的速度和更低的费用将 Android 10 引入符合 Treble 标准的设备中。 Android 10 也是首个支持 Project Mainline(官方名称为“Google Play 系统更新”)的版本;这是我们用于保护 Android 用户并通过重要的代码变更及时更新设备的新技术,可通过 Google Play 直接获取。借助 Google Play 系统更新,我们能够更新所有搭载 Android 10 及更高版本的设备中的特定内部组件,无需设备制造商全面更新系统。 对于开发者来说,我们希望 Android 10 中的这些更新能够广泛帮助提升设备间平台实现的一致性,并随时间提供更高的统一性,从而降低您的开发和测试费用。