Android P 行为变更

1,253 阅读14分钟

Android P 引入一系列有关 Android 系统的变更。不论应用针对的是哪个 Android 版本,其中大部分变更会影响所有应用;不过部分变更仅影响针对 Android P 开发的应用。为清楚起见,本文将分成两部分:针对所有 API 等级 开发的应用以及 针对 Android P 开发的应用  (详见下文内容)。

针对所有运行在 Android P 上的应用

这些行为变更适用于所有在 Android P 平台上运行的应用,无论它们是针对哪个 API 等级开发的。所有开发者都应该查看这些变更,并对其应用作出相应修改,从而正确支持这些变更 (若变更可适用于应用)。

后台应用程序用户输入以及数据隐私

Android P 将增强个人隐私方面保护,限制后台应用程序访问用户输入以及传感器数据。若您的应用在Android P 设备上后台运行,将会受到来自系统的以下限制:

若您的应用须在 Android P 设备上检测传感器事件,请使用 前台服务

*注意:调用 SensorManager flush() 方法 的应用不受此变更影响。

设备安全变更

运行 Android P 的设备提供密钥轮替以及系统调用保护。不论您的应用针对哪个级别的 API,此类变更都能显著提升应用安全性

加密变更

Android P 就加密算法的实现及处理引入了几项变更。

参数和算法的 Conscrypt 实现

Android P 在 Conscrypt 中对算法参数加入额外实现,适用参数包括 AES、DESEDE、OPEP 和 EC;此外 Android P 中已弃用以上参数以及许多算法的 Bouncy Castle 版本。

*注意:EC 参数的 Conscrypt 实现仅支持命名的曲线。

若您的应用面向 Android 8.1 (API 等级 27) 或更低版本进行开发,在您请求调用 Bouncy Castle 用以实现已弃用的算法时,您将收到警告信息。若应用开发目标平台为 Android P,这些请求将抛出NoSuchAlgorithmException 异常。

其余变更

Android P 还引入了其它加密变更:

  • 在使用 PBE 密钥的情况下,若您的应用未能提供 Bouncy Castle 要求的初始化向量,那么您将收到警告信息;

  • ARC4的 Conscrypt 实现允许您指定 ARC4/ECB/NoPadding 或者ARC4/NONE/NoPadding

  • Android P 移除了 Crypto Java Cryptography Architecture (以下简称 JCA) 加密服务提供商。因此,若您的应用调用 SecureRandom.getInstance("SHA1PRNG", "Crypto"),将会引发 NoSuchProviderException 异常;

  • 应用从大于密钥结构的缓冲区中解析 RSA 密钥时,不再会引发异常。

应用兼容性变更

为了保障应用的稳定性与兼容性,平台将限制使用非 SDK 接口。不论开发者是直接还是间接 (如通过反射、JNI 等) 试图访问这些接口都会受到限制。在开发者预览版 1 (DP1) 中,您的应用可以继续访问此类限制接口,不过平台会通过显示 Toast 以及记录日志消息引起开发者注意。若您的应用显示此类 Toast,您必须弃用限制接口并改用另一种实现策略。若您认为没有可行的替代接口,请在本文下方留言,要求我们重新考虑该限制是否合理

更新 ICU 库

平台使用的 ICU 库已更新至 ICU 58 版本;Android 8.0 (API 版本 26) 和8.1 (API 等级 27) 使用的 ICU 库则更新至 ICU 60 版本。

ICU 可将公开 API 迁移至 android.icu 软件包,同时 ICU 也供 Android 平台内部使用,用于支持国际化开源项目,譬如说,开发者可以利用 ICU 在 java.util、 java.text 和 android.text.format 中实现 Android 类。此版本 ICU 包括一系列小而实用的更改项,如 Emoji 5.0 数据支持、日期 / 时间格式优化 (详情可阅读 ICU 59 和 ICU 60 发布说明)。开发者们须要尤其注意以下几点:

  • 平台时区处理方式更变

- 平台更好地处理 GTM (格林威治标准时间) 以及 UTC (协调世界时); UTC 不再等同于 GMT;

ICU 现提供 GMT 和 UTC 时区译名。该变更会影响 android.icu 转化并解析 GMT、Etc / GMT、UTC、Etc / UTC 以及 Zulu 等字符串格式。

- java.text.SimpleDateFormat 现使用 ICU 为 UTC 和 GMT 提供显示名称,即:

-- 格式化 zzzz 会在很多本地环境中产生本地化长字符串。在此之前,UTC 的时区信息显示为“UTC”;而 GMT 的时区信息则显示为字符串 “GMT+00:00”;

-- 解析 zzzz 能识别诸如 "Universal Coordinated Time" 和 "Greenwich Mean Time" 的字符串。

-- 若应用假设在所有语言内,"UTC" 或 "GMT+00:00" 均为 zzzz 输出项,那么应用可能会遇到兼容性问题。

- java.text.DateFormatSymbols.getZoneStrings() 行为发生变更:

-- 和 SimpleDateFormat 一样,UTC 和 GMT 命名较长。在命名缺失的情况下,作为回退方案,UTC 时区 (如 “UTC”、“Etc / UTC” 以及 “Zulu” ) 的 DST 变体会显示为 GMT+00:00,而非硬编码字符串 UTC;

-- Android 能准确将某些时区的 ID 等同于其它时区的 ID,因此 Android 可以辨认古时区 ID 的字符串,如 Eire,这是之前版本无法解决的。

- Asia/Hanoi 不再属于被认可的时区。因此 java.util.TimeZones.getAvailableIds() 不返回该值;java.util.TimeZone.getTimeZone() 无法辨认出该时区。该行为与现行的 android.icu 行为一致。

  • 即使在解析合法 CURRENCY 文本时,android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String) 方法可能抛出 ParseException 异常。开发者可以调用NumberFormat.parseCurrency 规避该问题。Android 7.0 (API 等级 24) 版本开始引入NumberFormat.parseCurrency 函数,用于处理类似 PLURALCURRENCYSTYLE 的 CURRENCY 文本。

不再支持 Android 安全加密文件

  • Android 加密文件 (ASEC) 最早在 Android 2.2 (API 等级 8) 引入,用于支持 apps-on-SD-card 功能。Android 6.0 (API 等级 23) 已替换并弃用了安全加密文件,同时引入了 “可采用的 SK 卡 (adoptable SD card)” 功能;

  • Android 8.0 (API 等级 26) 阻止往安全加密文件中安装新应用。Android P 的开发者预览版则彻底移除了安全加密文件功能。

测试套件构建行为变更

Android P 移除了  TestSuiteBuilder  类中的 addRequirements() 方法,并且将 TestSuiteBuilder 类标记为弃用。此 addRequirements() 方法要求开发者提供隐藏 API 类型的参数,使得 API 无效。

测试从平台中移除的库

在 Android 8.1 (API 等级 27) 或更低版本系统中,Android 平台提供一系列类,如ActivityInstrumentationTestCase2,供开发者在应用内创建测试。进行编译时,开发者可以在构建android.jar 文件时可以获取这些类。内置测试架构尽管十分简便,但它要求开发者针对 android.jar 提供的 JUnit 版本进行测试,因此会对依赖其它版本 JUnit 进行的构建和测试造成一定困难。

为了让开发者能够灵活地构建以及测试定制化或三方逻辑,Android P 从平台中移除了测试类。不过,将测试库仍然作为可选依赖项提供。您可前往 “Android Developers 官方文档” 阅览 “ Legacy 测试库 ” 页面,查看如何在 Android P 中使用测试库。

Java UTF 解码器

UTF-8 是 Android 的默认字符集。开发者可利用类似 String(byte[] bytes) 的字符串构造函数解码 UTF-8字节串。Android P 中 UTF-8 解码器更为严格,同时遵循 Unicode 标准,即:

  • 非最短形式编码的 UTF-8, 如 <C0, AF>,现在属于不规范编码;

  • 代理形式编码的 UTF-8,如 U+D800..U+DFFF,现在属于不规范编码;

  • 最大字节部分由 U+FFFD 代替,拿字节串 “41 C0 AF 41 F4 80 80 41” 为例,该字节串最大字节为 “C0”,“AF” 和 “F4 80 80” 。字节串 “F4 80 80 80” 的起始部分可以是 “F4 80 80”,但是任何规范字节串都不能以 “C0” 开头。因此,输出应为 “A\ufffd\ufffdA\ufffdA”;

  • 若要在 Android P 上解码修正 UTF-8 / CESU-8 代码,请调用 DataInputStream.readUTF()  方法或者 NewStringUTF() JNI 方法。

使用证书验证主机名称

RFC 2818 描述了两种方法匹配主机名与证书:使用 subjectAltName (SAN) 扩展中的已有名称;若无 SAN 扩展,则使用 commonName (CN)。

不过,RFC2818已弃用 CN;因此 Android 也不再支持使用 CN。要验证一个主机名,服务器必须提供含有匹配 SAN 的证书;若证书中的 SAN 和主机名不匹配,该证书不再被信任。

网络地址查找可能导致网络违规

涉及域名解析的网络地址查找可能须要使用网络 I / O,因而属于阻塞操作 (blocking operation);而阻塞造作是导致中断和卡顿 (jank) 的主要元凶。

StrictMode 类是一款帮助开发者检测代码问题的开发工具,它能够检测到由涉及域名解析的网络地址查找导致的网络违规。

开发者不可以在 StrictMode 激活状态下待机应用,否则,应用可能产生新的异常,比如:使用 detectNetwork()  detectAll()  方法获取策略来侦测网络违规时,会产生NetworkOnMainThreadException 异常。

解析数字 IP 地址不属于阻塞操作,且 Android P 和更低版本 Android 系统采用同样的解析方法。

Socket 标记

在版本低于 Android P 的平台中,如果用 setThreadStatsTag()  方法标记某个 socket,那么通过 ParcelFileDescriptor  容器使用 binder IPC 将该 socket 传送到其它线程时,该 socket 会被取消标记。

从 Android P 开始,即使使用 binder IPC 将标记的 socket 传送到其它线程中,此标记也不会被取消。该变更会影响网络流量统计数据,比如,在调用 queryDetailsForUidTag()  方法时。您可以在传送 socket 标记到其它线程之前,调用 untagSocket() 来保留以前的行为。

报告 socket 中可用字节数量

触发shutdownInput() 方法后,调用 available() 方法会返回 0 值。

更详细的 VPN 网络能力报告

在低于 Android P 版本的平台中, NetworkCapabilities 类仅报告部分 VPN 信息,如包含TRANSPORT_VPN  但不含 NET_CAPABILITY_NOT_VPN。这让应用开发者难以确定 VPN 的使用是否对用户产生费用。比如说,检测 NET_CAPABILITY_NOT_METERED  并不能确定应用使用的网络是否按流量计费。

从 Android P 起,当 VPN 调用 setUnderlyingNetworks() 方法时,系统会合并所有底层网络的传输以及能力,并将合并后的结果作为 “VPN 网络的有效能力” 返回。

已经设定过 NET_CAPABILITY_NOT_METERED 的开发者们从 Android P 开始就可以接收到 VPN 以及底层网络的能力。

应用不再能访问 xt_qtaguid 文件夹中的文件

应用不再能直接读取 /proc/net/xt_qtaguid 文件夹中的文件,这一举措是为了与部分发售时就运行 Android P 的设备保持一致,而这些设备根本没有此类文件。

诸如 TrafficStatsNetworkStatsManager  此类依赖这些文件的公开 API 不会受到影响。但是,不受支持的 cutils 功能,如 qtaguid_tagSocket() ,可能无法在不同的设备上按预期工作 (或者完全不能工作)。

强制性 FLAG_ACTIVITY_NEW_TASK 要求

在 Android P 中,除非使用了 FLAG_ACTIVITY_NEW_TASK intent flag,您不能在非 Activity 场景下启动 Activity。若您未使用这个 intent flag 就尝试启动 Activity,系统无法正常开启活 Activity,并会在日志中留下相应信息。

*注意:FLAG_ACTIVITY_NEW_TASK 标签的要求属为预期行为,并且从 Android N 就对此作了强制要求。但是 Android N 系统中的错误暂时导致此要求没有被强制执行。

屏幕旋转变更

Android O 用户可在快速设定或屏幕设定界面进行操作,在自动旋转和固定竖屏模式之间进行选择。Android P 对竖屏旋转模式引入几大重要变更。竖屏模式更名为 “旋转锁定”,并且只有当自动旋转模式关闭情况下,该模式才能被激活。自动旋转模式暂无变更。

当设备处于旋转锁定模式时,用户可以将屏幕锁定在顶层可见 Activity 支持的任何方向。Activity 不能假定屏幕永远处于竖屏状态。如果顶层 Activity 在自动旋转模式下支持多个方向,旋转锁定模式也应给予相同选项,但可根据 Activity 的 screenOrientation 设置规定列外情况 (详情见下表)。

请求特定方向 (如,screenOrientation=landscape) 的 Activity 会忽略用户锁定偏好,并与 Android O 行为一致。

可在 Android Manifest 中的 Activity 级别的选项中设置屏幕方向偏好,或者调用setRequestedOrientation() 来设定。

WindowManger 在处理 Activity 旋转时会使用用户屏幕旋转偏好设置,而 “旋转锁定模式” 也是通过设置该偏好来工作的。在下列情况中,用户屏幕旋转偏好可能会发生更改。请注意,Activity 倾向于回到竖屏状态:

  • 当用户接受旋屏建议时,屏幕旋转偏好会更改至建议状态;

  • 当用户跳转到只支持竖屏的应用时 (包括锁屏或者桌面启动器),屏幕旋转偏好会更改至竖屏状态。

下表为常见屏幕旋转行为总结:

针对 Android P 开发的应用

以下行为变更仅适用于针对 Android P 或更高平台开发的应用。针对 Android P 或更高版本编译的应用,或将 targetSdkVersion 设定为 Android P 或更高版本系统的应用,必须进行修改以支持以下行为 (若变更适用于应用)。

前台服务

针对 Android P 或更高平台开发的应用必须请求 FOREGROUND_SERVICE 权限才能使用前台服务。 FOREGROUND_SERVICE 属于普通级别请求,因此提出请求后,系统会自动授予。

若应用未提出 FOREGROUND_SERVICE 请求就试图创建前台服务,系统会抛出 SecurityException 异常。

设备序列号访问限制

Android 8.0 (API等级26) 已弃用 Build.SERIAL 字段;从 Android P 开始,Build.SERIAL 始终设定为 "UNKNOWN"。此项变更能够保护用户隐私。

若您的应用须要访问设备硬件序列号,您应该请求 READ_PHONE_STATE 权限,然后调用getSerial()

平台安全性变更

若您的应用目标平台为 Android P,系统将执行更严格的网络与文件系统安全性方面要求。您可前往 “Android Developers 官方文档” 阅览 “安全性行为变更” 文档中针对 Android P 应用的详细信息。

视图焦距

零区域视图 (即长或宽的值为 0) 不再能够设定焦点。

另外,在 touch-mode 下 Activity 不再隐式分配初始焦点,而是要求开发者在需要的情况下对初始焦点提出显式要求。

Android P 应用允许 CSS Color Module Level 4 行为,用于操作 4 位和 8 位十六进制 CSS 颜色。

Chrome 从 52 版本开始支持 CSS Color Module Level 4,但是 WebView 目前暂时禁用该功能,因为存在现有 Android 应用在 Android ordering (ARGB) 中包含 32 位十六进制颜色,这可能会导致渲染错误。

比如说,在针对 Android P 之前的 SDK 开发的应用中,色号 #80ff8080 在 WebView 目前呈现为不透明浅红色 (#ff8080)。主要颜色组件 (即 Android 称为 alpha 组件的元素) 目前被忽略。若应用的目标平台为 Android P 或更高版本,该色号会被解释为透明度50%的浅绿色 (#80ff80)。

文档滚动元素

在 Android P 之前,滚动位置被设置在 body 元素上,而根元素的滚动值为 0。Android P 支持符合标准的行为,即滚动元素为根元素。

此外,根据目标 SDK 不同,直接访问 document.body.scrollTop, document.body.scrollLeft, document.documentElement.scrollTop 或 document.documentElement.scrollLeft 会产生不同行为。要访问视口滚动值,请使用 document.scrollingElement (如果可用)。

国内测试平台

WeTest 限时免费开放 Android P Preview 版本的远程调试标准兼容功能,供开发者进行体验。让开发者们能够及时了解 Android P 的新功能特性,提前为您的 app 进行良好适配。

了解 WeTest 更多 Android P 开发者预览版测试相关信息请访问下方链接:

> wetest.qq.com/cloud/help/…

同样的 Android,不同的体验。我们鼓励开发者们多做测试,完善您的应用和游戏以早日获得更大的成功。

您可查看文中蓝色字体的相应链接及其详细说明