以 Android 12 为目标编译程序错误问题

 与早期版本一样,Android 12 包含一些行为变更,这些变更可能会影响您的应用。以下行为变更仅影响以 Android 12 或更高版本为目标平台的应用。如果您的应用以 Android 12 为目标平台,您应该修改自己的应用以适当地支持这些行为(如果适用)。

下表总结了影响以 Android 12 为目标平台的应用的重要变更。请注意,此表并不包含全部变更。

重要变更受影响的应用
前台服务启动限制除少数例外情况,应用再也无法在后台运行时启动前台服务。否则,系统会抛出异常。在后台运行时启动前台服务的应用。
包含 intent 过滤器的应用组件必须声明导出的属性包含 intent 过滤器的应用组件必须显式设置 android:exported 属性。 未设置该属性的应用无法安装在 Android 12 上。在清单文件中声明 <intent-filter> 属性的应用。
以不安全的方式启动嵌套 intent严格模式测试现在会检测您的应用何时以不安全的方式使用嵌套 intent。启动另一个应用并期望通过内部 intent 回调的应用。

此外,请务必查看对 Android 12 上运行的所有应用都有影响的行为变更列表。

隐私设置

WebView 中的现代 SameSite Cookie 行为

Android 的 WebView 组件基于为 Google 的 Chrome 浏览器提供支持的开源项目 Chromium。在过去一年中,Chromium 变更了对第三方 Cookie 的处理方式,目的是为了更好地保护用户的安全和隐私,并赋予用户更高的透明度和控制权。这些变更已面向很多 Chrome 用户发布,从 Android 12 开始,这些变更将应用于 WebView 中。

Cookie 的 SameSite 属性决定了它是可以与任何请求一起发送,还是只能与同站点请求一起发送。Android 12 中的 WebView 基础版本(版本 89.0.4385.0)包含以下隐私保护方面的变更,旨在改善对第三方 Cookie 的默认处理方式,并帮助防止意外跨站点共享:

  • 没有 SameSite 属性的 Cookie 被视为 SameSite=Lax。
  • 带有 SameSite=None 的 Cookie 还必须指定 Secure 属性,这意味着它们需要安全的上下文,并应通过 HTTPS 发送。
  • 站点的 HTTP 版本和 HTTPS 版本之间的链接现在被视为跨站点请求,因此除非将 Cookie 正确标记为 SameSite=None; Secure,否则 Cookie 不会被发送。

对于开发者而言,一般指导意见是识别关键用户流中的跨站点 Cookie 依赖项,并确保在需要时使用适当的值显式设置 SameSite 属性。您必须显式指定允许在不同网站上运行的 Cookie,或适用于从 HTTP 切换到 HTTPS 进行同站点导航的 Cookie。

如需了解有关这些变更的网站开发者完整指南,请参阅 SameSite Cookie 说明和 Schemeful SameSite。

在您的应用中测试 SameSite 行为

如果您的应用使用 WebView,或者您需要管理使用 Cookie 的网站或服务,我们建议您在 Android 12 WebView 上测试您的数据流。 如果发现问题,您可能需要更新 Cookie 以支持新的 SameSite 行为。

留意登录和嵌入式内容中存在的问题,以及用户从不安全的页面启动并转到安全页面的登录流、购买和其他身份验证流。

如需使用 WebView 测试应用,您必须完成以下任一步骤,为需要测试的应用启用新的 SameSite 行为:

  • 在 WebView devtools 中切换界面标志 webview-enable-modern-cookie-same-site,在测试设备上手动启用 SameSite 行为。
    此方法允许您在任何运行 Android 5.0(API 级别 21)或更高版本(包括 Android 12)和 WebView 版本 89.0.4385.0 或更高版本的设备上进行测试。
  • 通过 targetSdkVersion 编译您的应用,使其以 Android 12 为目标平台。
    如果您使用此方法,则必须使用运行 Android 12 和 WebView 版本 89.0.4385.0 或更高版本的设备。

注意:由于 Android 12 开发者预览版 1 中存在一个已知会影响 WebView 的问题,您目前无法在 Android 12 上启用或测试Schemeful Same-Site 变更。 我们已在内部解决这个问题,并将在未来的开发者预览版中添加此解决措施。在此期间,您仍可以针对其他 SameSite 变更在 Android 12 上测试您的应用(请参阅默认 SameSite=LaxSameSite=None 必须是安全的)。

如需了解有关 Android 上的 WebView 远程调试的信息,请参阅 Android 设备的远程调试入门。

其他资源

如需详细了解 SameSite 现代行为及其在 Chrome 和 WebView 中的部署,请访问 Chromium SameSite 更新页面。如果您在 WebView 或 Chromium 中发现了错误,则可以在公开的 Chromium 问题跟踪器中报告错误。

adb 备份限制

为了保护私有应用数据,Android 12 变更了 adb backup 命令的默认行为。对于以 Android 12 为目标平台的应用,用户运行 adb backup 命令时,从设备导出的任何其他系统数据都不包含应用数据。

如果您的测试或开发工作流程依赖于使用 adb backup 的应用数据,现在您可以选择通过在应用的清单文件中将 android:debuggable 设置为 true 来导出应用数据。

注意:为了帮助保护应用数据,请务必在发布应用前将android:debuggable设置为false。

安全性

更多权限需要显式向用户请求权限

例如:

1.TelephonyManager.listen监听来电,需要显式请求Manifest.permission.READ_PHONE_STATE

2.BluetoothHeadset.getConnectedDevices()获取蓝牙设备权限,需要显式请求Manifest.permission.BLUETOOTH_CONNECT

更安全地导出组件

如果您的应用以 Android 12 为目标平台,且包含使用 intent 过滤器的 activity、服务或广播接收器,您必须为这些应用组件显式声明 android:exported 属性。

警告:如果 activity、服务或广播接收器使用 intent 过滤器,并且未显式声明 android:exported 的值,则您的应用将无法在搭载 Android 12 的设备上进行安装。
如果您在使用 Android Studio 时尝试安装此类应用,Logcat 将显示以下错误消息:

Installation did not succeed. The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE List of apks: [0] '.../build/outputs/apk/debug/app-debug.apk' Installation failed due to: 'null'

如果您的应用在需要声明 android:exported 的值时未进行此声明,则 Logcat 会提供以下错误消息:

Targeting S+ (version 10000 and above) requires that an explicit value for \
android:exported be defined when intent filters are present

以下代码段显示了一个服务示例,该服务包含 intent 过滤器并针对 Android 12 进行了正确配置:

<service android:name="com.example.app.backgroundService"
         android:exported="false">
    <intent-filter>
        <action android:name="com.example.app.START_BACKGROUND" />
    </intent-filter>
</service>

待处理 intent 必须声明可变性

如果您的应用以 Android 12 为目标平台,您必须为您的应用创建的每个 PendingIntent 对象指定可变性。这项额外的要求可提高应用的安全性。

如需声明特定 PendingIntent 对象是否可变,请分别使用 PendingIntent.FLAG_MUTABLE 或 PendingIntent.FLAG_IMMUTABLE 标志。如果您的应用试图在不设置任何可变标志的情况下创建 PendingIntent 对象,系统会抛出 IllegalArgumentException,并在 Logcat 中显示以下消息:

PACKAGE_NAME: Targeting S+ (version 10000 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.

尽可能创建不可变的待处理 intent

在大多数情况下,您的应用应创建不可变的 PendingIntent 对象,如以下代码段所示。如果 PendingIntent 对象不可变,则应用无法修改 intent 来调整调用 intent 的结果。

val pendingIntent = PendingIntent.getActivity(applicationContext,
REQUEST_CODE, intent,
/* flags */ PendingIntent.FLAG_IMMUTABLE)

然而,某些应用需要创建可变的 PendingIntent 对象:

  • 通知中的直接回复操作需要变更与回复关联的 PendingIntent 对象中的剪辑数据。通常,您可以通过将 FILL_IN_CLIP_DATA 作为标志传递给 fillIn() 的方法请求此变更。
  • 如果您的应用使用 PendingIntent 将对话放在气泡中,则 intent 应该可变,以便系统可以应用正确的标志,例如 FLAG_ACTIVITY_MULTIPLE_TASK 和 FLAG_ACTIVITY_NEW_DOCUMENT。

如果您的应用创建了可变的 PendingIntent 对象,强烈建议您使用显式 intent 并填写 ComponentName。如此一来,每当另一个应用调用 PendingIntent 并将控制权传回您的应用时,应用中的相同组件都会启动。

测试待处理的 intent 可变性变更

如需确定您的应用是否缺少可变性声明,请在 Android Studio 中查找以下 lint 警告:

Warning: Missing PendingIntent mutability flag [UnspecifiedImmutableFlag]

在开发者预览版计划期间,您可以通过关闭 PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED 应用兼容性标志来停用此系统行为以进行测试。

以不安全的方式启动嵌套 intent

为了提高平台安全性,Android 12 提供了一种调试功能,如果您的应用以不安全的方式启动嵌套 intent,此功能便会发出警告。嵌套 intent 是在其他 intent 中作为 extra 传递的 intent。如果您的应用同时执行以下两项操作,就会发生 StrictMode 违规行为。

  1. 您的应用从已传递的 intent 的 extra 中解封嵌套 intent。
  2. 您的应用立即使用该嵌套 intent 启动应用组件,例如将 intent 传递给 startActivity()、startService() 或 bindService()。

配置应用以检测嵌套 intent 的不安全启动

如需检查您的应用中是否会以不安全的方式启动嵌套 intent,请在配置 VmPolicy 时调用 detectUnsafeIntentLaunch(),如以下代码段所示。如果您的应用检测到 StrictMode 违规行为,您可能需要停止应用的执行以保护潜在的敏感信息。

注意:如果您的应用以 Android 12 为目标平台,并在其VmPolicy定义中使用detectAll()方法,系统将自动调用detectUnsafeIntentLaunch()方法。

fun onCreate() {
StrictMode.setVmPolicy(VmPolicy.Builder()
// Other StrictMode checks that you've previously added.
// ...
.detectUnsafeIntentLaunch()
.penaltyLog()
// Consider also adding penaltyDeath()
.build())
}

更负责地使用 intent

您的应用可能会启动嵌套 intent,以便在应用的各个组件之间导航,或代表其他应用执行操作。如需在这两种情况下最大限度地降低出现 StrictMode 违规行为的可能性,请执行以下操作:

  • 嵌套 intent 的内部启动:确保这些组件不会被导出。
  • 嵌套 intent 的跨应用启动ref="https://developer.android.google.cn/reference/android/app/PendingIntent">:使用 PendingIntent 代替嵌套 intent。如此一来,当 PendingIntent 从包含它的 Intent 中解封时,应用组件可以使用调用进程的身份启动 PendingIntent。该配置允许提供程序应用向调用应用的任何组件(包括未导出的组件)发送回调。
    如需详细了解如何识别这种情况并变更您的应用,请参阅 Medium 上关于 Android 嵌套 intent 的博文。

性能

前台服务启动限制

以 Android 12 为目标平台的应用再也无法在后台运行时启动前台服务,但一些特殊情况除外。如果应用尝试在后台运行时启动前台服务,则会引发异常(少数特殊情况除外)。当您的应用在后台运行时,请考虑使用 WorkManager 来计划和启动工作。

如需详细了解您的应用会受到什么影响,以及如何根据这些变更来更新您的应用,请参阅前台服务启动限制指南。您还可以浏览 GitHub 上的 WorkManagerSample。

无法通过服务或广播接收器创建通知 trampoline

当用户与通知互动时,某些应用会启动应用组件来响应通知点按操作,此应用组件最终会启动用户最终看到并与之互动的 activity。此应用组件被称为通知 trampoline。

为了改进应用性能和用户体验,以 Android 12 为目标平台的应用无法从用作通知 trampoline 的服务或广播接收器中启动 activity。换言之,当用户点按通知或通知中的操作按钮时,您的应用无法在服务或广播接收器内调用 startActivity()。

当您的应用尝试从充当通知 trampoline 的服务或广播接收器启动 activity 时,系统会阻止启动该 activity 启动,并在 Logcat 中显示以下消息:

Indirect notification activity start (trampoline) from PACKAGE_NAME, \
this should be avoided for performance reasons.

更新应用

如果您的应用从充当通知 trampoline 的服务或广播接收器启动 activity,请完成以下迁移步骤:

  1. 创建与一个下列 activity 关联的 PendingIntent 对象:
  • 用户点按通知后会看到的 activity(首选)。
  • Trampoline activity 或用于启动用户在点按通知后可以看到的 activity 的 activity。
  1. 在构建通知的过程中,请使用您在上一步中创建的 PendingIntent 对象。

切换行为

在开发者预览版计划期间测试您的应用时,您可以使用 NOTIFICATION_TRAMPOLINE_BLOCK 应用兼容性标志启用和停用此限制。

限制非 SDK 接口

Android 12 包含更新后的受限制非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。在限制使用非 SDK 接口之前,我们会尽可能确保有可用的公开替代方案。

如果您的应用并非以 Android 12 为目标平台,其中一些变更可能不会立即对您产生影响。然而,虽然您目前仍可以使用一些非 SDK 接口(具体取决于应用的目标 API 级别),但只要您使用任何非 SDK 方法或字段,终归存在导致应用出问题的显著风险。

如果您不确定自己的应用是否使用了非 SDK 接口,则可以测试您的应用来进行确认。如果您的应用依赖于非 SDK 接口,您应该开始计划迁移到 SDK 替代方案。然而,我们知道某些应用具有使用非 SDK 接口的有效用例。如果您无法为应用中的某项功能找到使用非 SDK 接口的替代方案,应请求新的公共 API。

如需详细了解此 Android 版本中的变更,请参阅 Android 12 中有关限制非 SDK 接口的更新。如需全面了解有关非 SDK 接口的详细信息,请参阅对非 SDK 接口的限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

turbocc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值