Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

行为变更:以 API 级别 28 及更高级别为目标的应用

Android 9(API 级别 28)向 Android 系统引入了多项变更。以下行为变更仅影响以 API 级别 28 或更高级别为目标平台的应用。将 targetSdkVersion 设为 API 级别 28 或更高级别的应用必须进行修改,以便适当地支持这些行为(如果适用于相应应用)。

要了解会影响在 Android 9 上运行的所有应用的变更(无论这些应用以哪个 API 级别为目标平台),请参阅行为变更:所有应用

前台服务

如果应用以 Android 9 或更高版本为目标平台并使用前台服务,则必须请求 FOREGROUND_SERVICE 权限。这是普通权限,因此,系统会自动为请求权限的应用授予此权限。

如果以 Android 9 或更高版本为目标平台的应用尝试创建前台服务且未请求 FOREGROUND_SERVICE,则系统会抛出 SecurityException

隐私权变更

如果您的应用以 Android 9 为目标平台,则您应牢记以下行为变更。这些针对设备序列信息和 DNS 信息做出的更新可增强用户隐私保护。

构建序列号弃用

在 Android 9 中,Build.SERIAL 始终设为 "UNKNOWN",以保护用户隐私。

如果您的应用需要访问设备的硬件序列号,您应改为请求 READ_PHONE_STATE 权限,然后调用 getSerial()

DNS 隐私权

以 Android 9 为目标平台的应用应采用私有 DNS API。具体而言,应用应确保,当系统解析器正在通过传输层安全协议 (TLS) 执行 DNS 时,任何内置的 DNS 客户端均使用加密的 DNS 查找与系统相同的主机名,或停用它而改用系统解析器。

框架安全性变更

Android 9 包含多项可提升应用安全性的行为变更,但这些变更仅在应用以 API 级别 28 或更高级别为目标平台时才会生效。

默认启用网络传输层安全协议 (TLS)

如果您的应用以 Android 9 或更高版本为目标平台,则 isCleartextTrafficPermitted() 方法默认返回 false。如果您的应用需要针对特定网域启用明文,则您必须在应用的网络安全配置中,针对这些网域明确将 cleartextTrafficPermitted 设置为 true

按进程分设基于网络的数据目录

在 Android 9 中,为改善应用稳定性和数据完整性,应用无法再让多个进程共享一个 WebView 数据目录。通常情况下,此类数据目录会存储 Cookie、HTTP 缓存以及其他与网络浏览有关的持久性和临时性存储。

在大多数情况下,您的应用应仅在一个进程中使用 android.webkit 软件包中的类(如 WebViewCookieManager)。例如,您应该将使用 WebView 的所有 Activity 对象移入同一进程。您可以通过在应用的其他进程中调用 disableWebView(),更严格地执行“仅限一个进程”规则。该调用可防止 WebView 在这些其他进程中被错误地初始化,即使是从依赖内容库进行的调用也能防止。

如果您的应用必须在多个进程中使用 WebView 实例,则您必须先使用 WebView.setDataDirectorySuffix() 方法为每个进程指定唯一的数据目录后缀,然后再在相应进程中使用 WebView 的给定实例。该方法会将每个进程的网络数据放入应用数据目录内其自己的目录中。

按应用划分的 SELinux 域

以 Android 9 或更高版本为目标平台的应用无法使用所有人都可访问的 Unix 权限与其他应用共享数据。这项变更可提高 Android 应用沙盒的完整性,尤其是对于应用的私有数据仅能由相应应用访问这一要求而言。

要与其他应用共享文件,请使用内容提供方

网络连接变更

网络连接数据计数和多路径

在以 Android 9 或更高版本为目标平台的应用中,系统会统计并非当前默认网络的网络流量(例如,当设备连接到 WLAN 时的蜂窝流量),并在 NetworkStatsManager 类中提供查询该流量的方法。

具体而言,getMultipathPreference() 现在会返回一个基于上述网络流量的值。自 Android 9 开始,此方法会针对蜂窝数据返回 true,但当一天内累积的流量超过特定数量时,它会开始返回 false。在 Android 9 上运行的应用必须调用此方法并遵守该提示。

ConnectivityManager.NetworkCallback 类现在会将有关 VPN 的信息发送到应用。此项变更可以让应用更轻松地侦听连接事件,而无需混用同步和异步调用,也无需使用有限的 API。此外,它还意味着将设备同时连接至多个 WLAN 网络或多个蜂窝网络时,信息传输可按预期工作。

Apache HTTP 客户端弃用

在 Android 6.0 中,我们移除了对 Apache HTTP 客户端的支持。从 Android 9 开始,该内容库已从 bootclasspath 中移除,且默认情况下应用无法使用它。

要继续使用 Apache HTTP 客户端,以 Android 9 及更高版本为目标平台的应用可以向其 AndroidManifest.xml 添加以下内容:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>
    

除了使用运行时 Apache 库,应用还可以将自己的 org.apache.http 库版本打包到其 APK 中。如果要进行此操作,您必须重新打包该库(使用一个类似于 Jar Jar 的实用程序),以避免运行时中提供的类存在类兼容性问题。

界面变更

视图焦点

0 面积的视图(即宽度或高度为 0)无法再被聚焦。

此外,Activity 不会再在轻触模式下隐式分配初始焦点,而是需要由您根据需要显式请求初始焦点。

CSS RGBA 十六进制值处理

以 Android 9 或更高版本为目标平台的应用必须支持草稿版 CSS 颜色模块级别 4 行为,以便处理 4 位和 8 位十六进制数字 CSS 颜色。

Chrome 自版本 52 以来便一直支持 CSS 颜色模块级别 4,但 WebView 目前停用了此功能,因为现有 Android 应用被发现包含 Android ordering (ARGB) 中的 32 位十六进制颜色,而这会导致呈现错误。

例如,对于以 API 级别 27 或更低版本为目标的应用,颜色 #80ff8080 目前在 WebView 中呈现为不透明的浅红色(#ff8080)。先导组件(Android 将其解读为 Alpha 组件)目前被忽略。如果某个应用以 API 级别 28 或更高级别为目标,则 #80ff8080 会被解读为 50% 透明的浅绿色 (#80ff80)。

文件的 MIME 类型嗅探:URI

低于 Android 9 的 Android 版本可以通过文件内容推断出 MIME 类型。从 Android 9(API 级别 28)开始,在 WebView 中加载 file: URI 时,应用必须使用正确的文件扩展名。

使用文件内容推断 MIME 类型可能会导致出现安全错误,现代浏览器通常不允许这样做。

如果文件具有可识别的文件扩展名(例如,.html.txt.js.css),则 MIME 类型将由扩展名决定。如果文件没有扩展名或者扩展名无法识别,则 MME 类型将为纯文本。

例如,file:///sdcard/test.html 等 URI 将以 HTML 形式呈现,但 file:///sdcard/test 等 URI 将以纯文本形式呈现,即使相应文件中包含 HTML 数据也是如此。

文档滚动元素

Android 9 可以正确处理文档的根元素为滚动元素的情况。在之前的版本中,滚动位置在正文元素上设置,根元素的滚动值为零。Android 9 支持符合标准的行为,在这种行为中,滚动元素是根元素。

此外,直接访问 document.body.scrollTopdocument.body.scrollLeftdocument.documentElement.scrollTopdocument.documentElement.scrollLeft 的行为会因目标 SDK 的不同而异。要访问视口滚动值,请使用 document.scrollingElement(如果有)。

来自已暂停应用的通知

在 Android 9 之前,已暂停的应用发出的通知会被取消。从 Android 9 开始,已暂停的应用发出的通知会被隐藏,直到应用恢复运行。