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。特别是,应用应确保,如果系统解析器正在执行 DNS-over-TLS,则任何内置 DNS 客户端要么使用加密 DNS 到与系统相同的主机名,要么被禁用以支持系统解析器。
框架安全变更
Android 9 包含多项可提高应用安全性的行为变更,但这些变更仅在您的应用面向 API 级别 28 或更高版本时才生效。
网络 TLS 默认启用
如果您的应用面向 Android 9 或更高版本,isCleartextTrafficPermitted()
方法默认返回 false
。如果您的应用需要为特定域启用明文,则必须在应用的网络安全配置中,将这些域的 cleartextTrafficPermitted
明确设置为 true
。
基于 Web 的数据目录按进程分离
为了提高 Android 9 中应用的稳定性和数据完整性,应用不能在多个进程之间共享单个 WebView
数据目录。通常,此类数据目录存储与 Web 浏览相关的 Cookie、HTTP 缓存以及其他持久性和临时存储。
在大多数情况下,您的应用应仅在一个进程中使用 android.webkit
包中的类,例如 WebView
和 CookieManager
。例如,您应将所有使用 WebView
的 Activity
对象移动到同一个进程中。您可以通过在应用的其他进程中调用 disableWebView()
来更严格地执行“仅一个进程”规则。此调用可防止 WebView
在其他进程中因意外而初始化,即使它是从依赖库中调用的。
如果您的应用必须在多个进程中使用 WebView
实例,则必须在使用给定进程中的 WebView
实例之前,使用 WebView.setDataDirectorySuffix()
方法为每个进程分配唯一的临时数据目录后缀。此方法将每个进程的 Web 数据放置在应用数据目录中的其自己的目录中。
每个应用的 SELinux 域
面向 Android 9 或更高版本的应用不能使用世界可访问的 Unix 权限与其他应用共享数据。此项变更提高了 Android 应用沙盒的完整性,特别是应用私有数据只能由该应用访问的要求。
要与其他应用共享文件,请使用内容提供程序。
连接变更
连接数据计数和多路径
在面向 Android 9 或更高版本的应用中,系统会统计非当前默认网络(例如设备处于 Wi-Fi 连接状态时的蜂窝流量)上的网络流量,并在 NetworkStatsManager
类中提供查询该流量的方法。
特别是,getMultipathPreference()
现在会根据上述网络流量返回一个值。从 Android 9 开始,该方法对蜂窝数据返回 true
,但当一天中累积的流量超过一定量时,它开始返回 false
。在 Android 9 上运行的应用必须调用该方法并遵守此提示。
ConnectivityManager.NetworkCallback
类现在将有关 VPN 的信息发送到应用。此项变更使应用更容易监听连接事件,而无需混合同步和异步调用以及使用有限的 API。此外,这意味着当设备同时连接到多个 Wi-Fi 网络或多个蜂窝网络时,信息传输按预期工作。
Apache HTTP 客户端弃用
随着 Android 6.0 的发布,我们移除了对 Apache HTTP 客户端的支持。从 Android 9 开始,该库已从启动类路径中移除,并且默认情况下不适用于应用。
要继续使用 Apache HTTP 客户端,面向 Android 9 及更高版本的应用可以在其 AndroidManifest.xml
中添加以下内容:
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
作为使用运行时 Apache 库的替代方案,应用可以在其 APK 中捆绑自己的 org.apache.http
库版本。如果这样做,您必须重新打包该库(使用 Jar Jar 等实用程序),以避免与运行时提供的类发生类兼容性问题。
UI 变更
视图焦点
面积为 0 的视图(宽度或高度为 0)不再可聚焦。
此外,Activity 不再在触摸模式下隐式分配初始焦点。相反,如果需要,您需要明确请求初始焦点。
CSS RGBA 十六进制值处理
面向 Android 9 或更高版本的应用必须启用草案 CSS 颜色模块级别 4 的行为来处理 4 位和 8 位十六进制 CSS 颜色。
CSS 颜色模块级别 4 自 Chrome 52 版本以来一直受支持,但 WebView 目前禁用了该功能,因为发现现有 Android 应用包含 Android 顺序 (ARGB) 的 32 位十六进制颜色,这会导致渲染错误。
例如,对于面向 API 级别 27 或更低版本的应用,颜色 #80ff8080
当前在 WebView 中渲染为不透明的浅红色 (#ff8080
)。前导组件(将被 Android 解释为 alpha 组件)目前被忽略。如果应用面向 API 级别 28 或更高版本,#80ff8080
将被解释为 50% 透明的浅绿色 (#80ff80
)。
文件:URI 的 MIME 类型嗅探
Android 9 之前的 Android 版本可以从文件内容推断 MIME 类型。从 Android 9(API 级别 28)开始,应用在 WebView 中加载 file:
URI 时必须使用正确的文件扩展名。
使用文件内容推断 MIME 类型可能是安全漏洞的来源,现代浏览器通常不允许这样做。
如果文件具有可识别的文件扩展名,例如 .html
、.txt
、.js
或 .css
,则 MIME 类型将由扩展名确定。如果文件没有扩展名或具有无法识别的扩展名,则 MIME 类型将是纯文本。
例如,像 file:///sdcard/test.html
这样的 URI 将渲染为 HTML,但像 file:///sdcard/test
这样的 URI 将渲染为纯文本,即使文件包含 HTML 数据也是如此。
文档滚动元素
Android 9 正确处理了文档的根元素是滚动元素的情况。在早期版本中,滚动位置设置在 body 元素上,而根元素具有零滚动值。Android 9 启用了符合标准的行为,其中滚动元素就是根元素。
此外,直接访问 document.body.scrollTop
、document.body.scrollLeft
、document.documentElement.scrollTop
或 document.documentElement.scrollLeft
将根据目标 SDK 的不同而表现不同。要访问视口滚动值,如果可用,请使用 document.scrollingElement
。
来自暂停应用的通知
在 Android 9 之前,来自暂停应用的通知会被取消。从 Android 9 开始,来自暂停应用的通知会被隐藏,直到应用恢复。