行为变更:以 Android 12 为目标平台的应用

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

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

用户体验

画中画行为改进

Android 12 针对画中画 (PiP) 模式引入了行为改进。如需了解详情,请参阅画中画改进

自定义通知

Android 12 更改了完全自定义通知的外观和行为。以前,自定义通知能够使用整个通知区域并提供自己的布局和样式。由此产生的反模式可能会令用户困惑,或在不同设备上引发布局兼容性问题。

对于以 Android 12 为目标平台的应用,包含自定义内容视图的通知将不再使用完整通知区域;相反,系统会应用标准模板。此模板可确保自定义通知在所有状态下都与其他通知相同,例如,在收起状态下的通知图标和展开功能,以及在展开状态下的通知图标、应用名称和收起功能。此行为与 Notification.DecoratedCustomViewStyle 的行为几乎完全相同。

通过这种方式,Android 12 通过为用户提供可看到且熟悉的通知展开功能,使所有通知保持外观一致且易于浏览。

下图显示了标准模板中的自定义通知:

以下示例展示了在收起状态和展开状态下呈现的自定义通知:

Android 12 中的变更会影响某些定义 Notification.Style 的自定义子类的应用,或使用 Notification.Builder 的方法 setCustomContentView(RemoteViews)setCustomBigContentView(RemoteViews)setCustomHeadsUpContentView(RemoteViews) 的应用。

如果您的应用使用的是完全自定义的通知,我们建议您尽快使用新模板进行测试。

  1. 启用自定义通知变更:

    1. 将应用的 targetSdkVersion 变更为 S 以启用新行为。
    2. 重新编译。
    3. 在搭载 Android 12 的设备或模拟器上安装您的应用。
  2. 测试所有使用自定义视图的通知,确保这些通知在通知栏中看起来符合预期。在测试时,请考虑以下注意事项并进行必要的调整:

    • 自定义视图的尺寸已更改。一般来说,提供给自定义通知的高度比之前小。在收起状态下,自定义内容的最大高度已从 106dp 减少到 48dp。此外,水平空间也减小了。

    • 对于以 Android 12 为目标平台的应用,所有通知都是可展开的。通常,这意味着,如果您使用的是 setCustomContentView,则还需要使用 setBigCustomContentView,以确保收起状态和展开状态保持一致。

    • 为了确保“浮动通知”状态看起来符合您的预期,请勿忘记将通知渠道的重要性提升至“高”(在屏幕中弹出)。

对于以 Android 12 为目标平台的应用,系统对 Android App Links 的验证方式进行了一些更改。这些变更可以提升应用链接体验的可靠性,并且能够增强应用开发者和最终用户的控制能力。

如果以 Android 12 为目标平台并且依靠 Android App Links 验证在您的应用中打开网页链接,请更新 Android App Links 声明,以支持更改后的验证流程。您也可以手动调用网域验证来测试声明的可靠性。

隐私设置

大致位置

该对话框包含两组选项,它们上下分布
图 1. 当您的应用以 Android 12 为目标平台并且在单个运行时请求中同时请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 时显示的系统权限对话框。

使用以 Android 12 为目标平台的应用时,用户可以请求应用只能访问大致位置信息。

如果您的应用以 Android 12 为目标平台并且请求 ACCESS_FINE_LOCATION 运行时权限,则您还必须请求 ACCESS_COARSE_LOCATION 权限。您必须在单个运行时请求中包含这两项权限。

当您的应用同时请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 时,系统权限对话框将为用户提供以下新选项,如图 1 所示:

  • 确切:提供 ACCESS_FINE_LOCATION 权限提供的位置精确度。
  • 大致:提供 ACCESS_COARSE_LOCATION 权限提供的位置精确度。

详细了解 Android 12 中的大致位置

应用休眠

Android 12 在 Android 11(API 级别 30)中引入的自动重置权限行为的基础上进行了扩展。如果您的应用以 Android 12 为目标平台并且用户有几个月未与您的应用互动,则系统会自动重置授予的所有权限并将您的应用置于休眠状态。

处于休眠状态的应用具有以下特征:

  • 系统会针对存储空间而非性能进行优化。应用缓存中的任何文件都会被移除。
  • 应用无法从后台运行作业或提醒。
  • 应用无法接收推送通知,包括通过 Firebase Cloud Messaging 发送的高优先级消息。

当用户下次与应用互动时,应用会退出休眠状态,并且可以再次创建作业、提醒和通知。不过,您需要重新调度在应用进入休眠状态之前调度的所有作业、提醒和通知。此工作流与用户从系统设置中手动强行停止应用时的工作流类似。为了更轻松地支持此工作流,请使用 WorkManager。您还可以在 ACTION_BOOT_COMPLETED 广播接收器中添加重新调度逻辑,系统会在您的应用离开休眠状态时以及设备启动后调用它。

请求用户停用休眠

如果您预计应用中的某个用例会受休眠的影响,您可以向用户发送请求,让其准许应用免于休眠和自动重置权限。如果用户希望应用主要在后台运行,即使用户不与应用互动,应用也能正常工作,例如,当应用执行以下一项或多项操作时,这种豁免很有用:

  • 通过定期报告家庭成员的位置来保障家庭安全。
  • 在设备与应用的服务器之间同步数据。
  • 与智能设备(如电视)通信。
  • 与配套设备(如手表)配对。

如需请求豁免,请调用包含 Intent.ACTION_APPLICATION_DETAILS_SETTINGS intent 操作的 intent。在显示的屏幕中,用户可以关闭名为撤消权限并释放空间的选项。

测试休眠行为

如需将应用置于休眠状态以进行测试,请执行以下操作:

  1. 在设备上启用该行为:

    adb shell device_config put app_hibernation app_hibernation_enabled true
    
  2. 更改应用的状态,使其进入休眠状态。包含 --global 标志的命令会强制应用进入“完全休眠”状态,以模拟系统已为多用户设备上的所有用户将应用置于休眠状态的情况。

    adb shell cmd app_hibernation set-state PACKAGE-NAME true && \
      adb shell cmd app_hibernation set-state --global PACKAGE-NAME true
    

移动传感器有采样率限制

为了保护有关用户的潜在敏感信息,如果您的应用以 Android 12 为目标平台,则系统会对来自某些移动传感器和位置传感器的数据的刷新率施加限制。这些数据包括由设备的加速度计陀螺仪地磁场传感器记录的值。

刷新率限制取决于您访问传感器数据的方式:

  • 如果您调用 registerListener() 方法,则传感器采样率限制为 200 Hz。对于 registerListener() 方法的所有过载变体都是如此。
  • 如果您使用 SensorDirectChannel 类,则传感器采样率限制为 RATE_NORMAL,通常约为 50 Hz。

如果您的应用以 Android 12 为目标平台并且需要以较高的采样率收集移动传感器数据,则您必须声明 HIGH_SAMPLING_RATE_SENSORS 权限。否则,如果您的应用尝试在未声明此权限的情况下以较高的采样率收集移动传感器数据,就会发生 SecurityException

数据访问审核

在 Android 11(API 级别 30)中引入的数据访问审核 API 可让您根据应用的用例创建归因标记。这些标记可让您更轻松地确定应用的哪一部分执行特定类型的数据访问。

如果您的应用以 Android 12 为目标平台,您必须使用以下代码段中所示的格式在应用的清单文件中声明这些归因标记。如果您的应用以 Android 12 为目标平台并且您尝试使用未在应用的清单文件中声明的某个归因标记,则系统会为您创建一个 null 标记并在 Logcat 中记录一条消息。


<manifest ...>
    <!-- The value of "android:tag" must be a literal string, and the
         value of "android:label" must be a resource. The value of
         "android:label" should be user-readable. -->
    <attribution android:tag="sharePhotos"
                 android:label="@string/share_photos_attribution_label" />
    ...
</manifest>

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 上的 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 12 为目标平台,且包含使用 intent 过滤器activity服务广播接收器,您必须为这些应用组件显式声明 android:exported 属性。

以下代码段显示了一个服务示例,该服务包含 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>

Android Studio 中的消息

如果您的应用包含使用 intent 过滤器的 activity、服务或广播接收器但未声明 android:exported,系统会显示以下警告消息,具体取决于您使用的 Android Studio 版本:

Android Studio 2020.3.1 Canary 11 或更高版本

系统会显示以下消息:

  1. 清单文件中会显示以下 lint 警告:

    When using intent filters, please specify android:exported as well
    
  2. 当您尝试编译应用时,系统会显示以下 build 错误消息:

    Manifest merger failed : Apps targeting Android 12 and higher are required \
    to specify an explicit value for android:exported when the corresponding \
    component has an intent filter defined.
    
较低的 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'

待处理 intent 可变性

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

如需声明特定 PendingIntent 对象是否可变,请分别使用 PendingIntent.FLAG_MUTABLEPendingIntent.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 的结果。

Kotlin

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

Java

PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE);

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

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

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

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

Warning: Missing PendingIntent mutability flag [UnspecifiedImmutableFlag]

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

不安全的 intent 启动

为了提高平台安全性,Android 12 提供了一种调试功能,如果您的应用以不安全的方式启动 intent,此功能便会发出警告。例如,您的应用可能会以不安全的方式启动从 URI 重新创建的 intent,或者以不安全的方式启动下一部分定义的嵌套 intent。

嵌套 intent 简介

嵌套 intent 是在其他 intent 中作为 extra 传递的 intent。如果您的应用执行以下两项操作,就会发生 StrictMode 违规行为。

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

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

Kotlin

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

Java

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

更负责地使用 intent

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

  • 仅复制 intent 中的必要 extra,并执行任何必要的清理和验证。您的应用可能会将 extra 从一个 intent 复制到用于启动新组件的另一个 intent。当您的应用调用 putExtras(Intent)putExtras(Bundle) 时,就会发生这种情况。如果您的应用执行这些操作其中之一,请仅复制接收组件所期望的 extra。如果另一个 intent(它接收副本)启动一个未导出的组件,请先清理和验证 extra,然后再将其复制到启动该组件的 intent。
  • 嵌套 intent 的内部启动:确保这些组件不会被导出。
  • 嵌套 intent 的跨应用启动:使用 PendingIntent 代替嵌套 intent。如此一来,当 PendingIntent 从包含它的 Intent 中解封时,应用组件可以使用调用进程的身份启动 PendingIntent。该配置允许提供程序应用向调用应用的任何组件(包括未导出的组件)发送回调。

    如需详细了解如何识别这种情况并变更您的应用,请参阅 Medium 上关于 Android 嵌套 intent 的博文。

性能

前台服务启动限制

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

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

精确的闹钟权限

为了鼓励应用节省系统资源,Android 12 要求为以 Android 12 为目标平台且设置精确的闹钟的应用配置“闹钟和提醒”特殊应用访问权限。

如需获取这种特殊应用访问权限,请在清单中请求 SCHEDULE_EXACT_ALARM 权限。

精确的闹钟只能用于面向用户的功能,如可接受的用例部分中所述的某种情况。

用户和系统均可撤消“闹钟和提醒”特殊应用访问权限。为您的应用撤消“闹钟和提醒”特殊应用访问权限后,您的应用会停止,并且将来的所有精确的闹钟都会取消。

向您的应用授予“闹钟和提醒”特殊应用访问权限后,系统会向其发送 ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED 广播。您的应用应实现广播接收器,以便执行以下操作:

  1. 确认您的应用仍具有特殊应用访问权限。为此,请调用 canScheduleExactAlarms()
  2. 根据应用的当前状态,重新调度它所需的任何精确的闹钟。此逻辑应与您的应用接收 ACTION_BOOT_COMPLETED 广播时所执行的操作类似。

如果您的应用尝试使用设置精确的闹钟的 API 但未被授予特殊应用访问权限,会发生 SecurityException

考虑一下应用的用例是否确实需要精确的闹钟,如可接受的用例部分中所述的某种情况。如需执行时间更长的工作或需要接入网络的工作,请使用 WorkManagerJobScheduler。如需在设备处于低电耗模式的同时执行工作,请使用 setAndAllowWhileIdle() 创建不精确的闹钟,并从该闹钟启动作业。

精确的闹钟和不精确的闹钟

您的应用在调用如下方法时设置精确的闹钟:

相比之下,您在调用如下方法时设置不精确的闹钟:

此权限的可接受用例

该选项称为“允许设置闹钟和提醒”
图 2. 系统设置中的“闹钟和提醒”特殊应用访问权限页面,用户可以在该页面中允许您的应用设置精确的闹钟。

只有在应用中面向用户的功能需要精确计时的操作时,例如在以下情况下,应用才应使用精确的闹钟,并声明关联的权限和广播接收器:

  • 您的应用是闹钟应用或计时器应用。
  • 您的应用可让用户调度精确计时的操作,如任务和事件的通知。

Android 12 认为精确的闹钟是对时间敏感的紧急中断。因此,精确的闹钟不受新的前台服务启动限制的影响。

让用户授予应用访问权限

如有必要,您可以将用户引导至系统设置中的闹钟和提醒屏幕,如图 2 所示。为此,请完成以下步骤:

  1. 在应用的界面中,向用户解释为什么您的应用需要调度精确的闹钟。
  2. 调用包含 ACTION_REQUEST_SCHEDULE_EXACT_ALARM intent 操作的 intent。

启用行为变更

如需启用行为变更以进行测试,请执行以下某项操作:

  • 开发者选项设置屏幕中,选择应用兼容性变更。在显示的屏幕上,点按应用的名称,然后开启 REQUIRE_EXACT_ALARM_PERMISSION
  • 在开发机器上的终端窗口中,运行以下命令:

    adb shell am compat enable REQUIRE_EXACT_ALARM_PERMISSION PACKAGE_NAME
    

通知 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

测试您的应用时,点按通知后,您可以识别哪个服务或广播接收器在您的应用中充当通知 trampoline。为此,请查看以下终端命令的输出:

adb shell dumpsys activity service \
  com.android.systemui/.dump.SystemUIAuxiliaryDumpService

输出的某一部分包含文本“NotifInteractionLog”。此部分包含识别因点按通知而启动的组件所需的信息。

更新应用

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

  1. 创建一个与用户点按通知后看到的 activity 关联的 PendingIntent 对象。
  2. 构建通知的过程中,使用您在上一步中创建的 PendingIntent 对象。

如需识别 activity 的来源,例如为了执行日志记录,请在发布通知时使用 extra。对于集中式日志记录,请使用 ActivityLifecycleCallbacksJetpack 生命周期观察器

切换行为

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

备份和恢复

Android 12 更改了在 Android 12 或更高版本中运行且以其为目标平台的应用中备份和恢复的工作方式。如需了解详情,请参阅备份和恢复方面的变更

连接性

并发点对点 + 互联网连接

从 Android 12 开始,支持并发点对点和互联网连接的设备可以保持与对等设备和互联网提供的主要网络的并发 Wi-Fi 连接,从而使用户体验更加顺畅。系统会自动为以 API 级别 31 及更高级别为目标的所有应用启用此功能。以较低 API 级别为目标的应用仍会体验旧行为,即在连接到对等设备之前会断开主要 Wi-Fi 网络。

兼容性

WifiManager.getConnectionInfo() 只能返回一个网络的 WifiInfo。因此,该 API 的行为在 Android 12 中从以下几个方面发生了变化:

  • 如果只有一个 Wi-Fi 网络可用,则返回其 WifiInfo
  • 如果有多个 Wi-Fi 网络可用,并且发起调用的应用触发了点对点连接,则返回与对等设备对应的 WifiInfo
  • 如果有多个 Wi-Fi 网络可用,并且发起调用的应用未触发点对点连接,则返回互联网提供的主要连接的 WifiInfo

为了在支持双并发 Wi-Fi 网络的设备上提供更好的用户体验,我们建议所有应用(特别是触发点对点连接的应用)脱离调用 WifiManager.getConnectionInfo(),而改用 NetworkCallback.onCapabilitiesChanged(),以获取与用于注册 NetworkCallbackNetworkRequest 匹配的所有 WifiInfo 对象。从 Android 12 开始,弃用了 getConnectionInfo()

以下代码示例展示了如何在 NetworkCallback 中获取 WifiInfo

Kotlin

val networkCallback = object : ConnectivityManager.NetworkCallback() {
  ...
  override fun onCapabilitiesChanged(
           network : Network,
           networkCapabilities : NetworkCapabilities) {
    val transportInfo = networkCapabilities.getTransportInfo()
    if (transportInfo !is WifiInfo) return
    val wifiInfo : WifiInfo = transportInfo
    ...
  }
}

Java

final NetworkCallback networkCallback = new NetworkCallback() {
  ...
  @Override
  public void onCapabilitiesChanged(
         Network network,
         NetworkCapabilities networkCapabilities) {
    final TransportInfo transportInfo = networkCapabilities.getTransportInfo();
    if (!(transportInfo instanceof WifiInfo)) return;
    final WifiInfo wifiInfo = (WifiInfo) transportInfo;
    ...
  }
  ...
};

为 NFC 付款启用屏幕关闭

在以 Android 12 及更高版本为目标平台的应用中,您可以通过将 requireDeviceScreenOn 设置为 false,在设备屏幕未打开的情况下启用 NFC 付款。如需详细了解屏幕关闭或锁定状态下的 NFC 付款,请参阅屏幕关闭和锁定屏幕行为

供应商库

供应商提供的原生共享库

如果应用以 Android 12 或更高版本为目标平台,默认情况下无法访问由芯片供应商或设备制造商提供的非 NDK 原生共享库。只有在使用 <uses-native-library> 标记明确请求时,才能访问这些库。

如果应用以 Android 11 或更低版本为目标平台,则无需使用 <uses-native-library> 标记。在这种情况下,任何原生共享库均可访问,而不管它是否为 NDK 库。

更新后的非 SDK 限制

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

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

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

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