兼容性框架工具

Android 11 引入了一些新的开发者工具,供您用于测试和调试自己的应用,检查其是否兼容更高版本的 Android 平台中的行为变更。这些工具属于兼容性框架的一部分,可让应用开发者使用开发者选项或 adb 单独启用或停用各项重大变更。您可以利用这种灵活性做好准备,以便以最新稳定版 API 为目标平台和使用下一个 Android 版本的预览版测试应用。

当您使用兼容性框架工具时,Android 平台会自动调整其内部逻辑,因此您无需更改 targetSDKVersion 或重新编译应用即可执行基本测试。由于各项变更可单独启用/停用,因此您可以一次隔离、测试和调试一项行为变更,或者停用一项在您需要先测试其他变更时会导致出现问题的变更。

如何识别已启用的变更

启用行为变更可能会影响您的应用访问受该变更影响的平台 API 的方式。您可以使用开发者选项、logcat 或 adb 命令查看已启用的行为变更。

使用开发者选项识别已启用的变更

图 1. 开发者选项中的“应用兼容性变更”屏幕

您可以在设备的开发者选项中查看已启用的变更,并且可以开启/关闭这些变更。如需访问这些选项,请按以下步骤操作:

  1. 如果开发者选项尚未启用,请启用开发者选项。
  2. 打开设备的“设置”应用,然后依次导航到系统 > 高级 > 开发者选项 > 应用兼容性变更。
  3. 从列表中选择您的应用。

每项行为变更通常属于以下两种类别之一:

  • 会影响在相应 Android 版本上运行的所有应用的变更,无论应用的 targetSdkVersion 为何。

    默认情况下,这些变更在兼容性框架中处于启用状态,并且会在界面的默认启用的应用兼容性变更部分中列出。

  • 只会影响以特定 Android 版本为目标平台的应用的变更。 由于这些变更只会影响以特定 Android 版本为目标平台的应用,因此它们也称为受 targetSDKVersion 控制的变更。

    如果您的应用以高于所列 API 版本的 Android 版本为目标平台,默认情况下,这些变更会在兼容性框架中处于启用状态。例如,Android 13(API 级别 33)中受 targetSDKVersion 控制的行为变更会在界面中标题为已为 targetSdkVersion >=33 启用的部分中列出。在某些较低版本的 Android 上,此部分标题为“在 SDK API_LEVEL 之后启用”。

在图 1 中,您还会看到一个名为默认停用的应用兼容性变更部分。此部分中的变更可用于各种目的。在启用这些变更之前,请先阅读相应 Android 版本的兼容性框架列表中有关这些变更的说明。

使用 logcat 识别已启用的变更

对于每项行为变更,应用在其进程运行过程中首次调用受影响的 API 时,系统都会输出一条类似如下的 logcat 消息:

D CompatibilityChangeReporter: Compat change id reported: 194833441; UID 10265; state: ENABLED

每条 logcat 消息都包含以下信息:

变更 ID
指明影响到应用的变更。该值映射到应用兼容性变更屏幕中列出的某项行为变更(参见图 1)。在此示例中,194833441 映射到 NOTIFICATION_PERM_CHANGE_ID。
UID
指示受该变更影响的应用。
状态

指示相应变更是否会影响应用。

状态可以是以下值之一:

状态 含义
ENABLED 该变更已启用,如果应用使用已变更的 API,该变更将会影响应用的行为。
DISABLED

该变更已停用,不会影响应用。

注意:如果此变更停用的原因是应用的 targetSDKVersion 低于要求的阈值,那么当应用提高其 targetSDKVersion,从而以更高版本为目标平台时,系统会默认启用此变更。

LOGGED 此变更当前通过兼容性框架记录,但无法启用或停用。虽然无法切换此变更的状态,但它仍然可能影响应用的行为。如需了解详情,请参阅相应 Android 版本的兼容性框架列表中有关此变更的说明。在许多情况下,这些类型的变更是实验性变更,可以忽略。

使用 adb 识别已启用的变更

如需查看整个设备上的所有变更(包括已启用和已停用的变更),请运行以下 adb 命令:

adb shell dumpsys platform_compat

输出内容中会列出每项变更的以下信息:

变更 ID
此行为变更的唯一标识符,例如 194833441。
名称
此行为变更的名称,例如 NOTIFICATION_PERM_CHANGE_ID。
targetSDKVersion 条件

控制此变更是否启用的 targetSDKVersion 值(如果有)。

例如,如果此变更仅对以 SDK 版本 33 或更高版本为目标平台的应用才会启用,系统会输出 enableAfterTargetSdk=32。如果此变更的启用与否不受 targetSDKVersion 控制,则会输出 enableAfterTargetSdk=0。

软件包替换

其中变更的默认状态(启用或停用)已被替换的各个软件包的名称。

例如,如果此变更默认处于启用状态,而您使用开发者选项或 adb 关闭了此变更,应用的软件包名称会在此列出。在这种情况下,输出结果如下:

packageOverrides={com.my.package=false}

受 targetSDKVersion 控制的变更在默认情况下可以处于启用状态,也可以处于停用状态,因此该软件包列表可以同时包含 true 或 false 实例,具体取决于每个应用的 targetSDKVersion。例如:

packageOverrides={com.my.package=true, com.another.package=false}

详细了解具体变更

兼容性框架中的完整行为变更列表包含在每个 Android 版本的文档中。如需了解详情,请访问以下链接(具体取决于您使用哪个 Android 版本测试应用):

何时切换变更的启用/停用状态

兼容性框架的主要目的在于,在您使用更高版本的 Android 测试应用时,为您提供可控性和灵活性。此部分介绍了一些策略,可在测试和调试应用时用来确定何时启用或停用变更。

何时停用变更

确定何时停用变更通常取决于相应变更是否受 targetSDKVersion 控制。

对所有应用启用变更

对于特定的平台版本,影响所有应用(无论应用的 targetSDKVersion 为何)的变更在默认情况下处于启用状态,因此您可以通过在该平台版本上运行应用来了解其是否受到影响。

例如,如果您准备以 Android 16(API 级别 36)为目标平台,则可以先在搭载 Android 16 的设备上安装您的应用,并使用典型的测试工作流测试应用。如果您的应用遇到问题,您可以停用导致出现问题的变更,以便继续测试是否存在其他问题。

这些变更会影响所有应用(无论 targetSDKVersion 为何),因此您应该先针对这些变更测试并更新您的应用,然后再针对受 targetSDKVersion 控制的变更测试和更新您的应用。这有助于确保用户在更新到新的平台版本时,体验不会变差。

您也应该优先测试这些变更,因为在使用 Android 的公开发布 build 时,您无法停用这些变更。理想情况下,您应该在每个 Android 版本处于预览版状态时针对这些变更执行测试。

受 targetSDKVersion 控制的变更

如果您的应用以特定的 targetSDKVersion 为目标平台,则受该版本控制的任何变更都会在默认情况下处于启用状态。因此,当您将应用的 targetSDKVersion 切换到新版本时,该应用会立即开始受到许多新变更的影响。

由于应用可能会受到多项变更的影响,因此在测试和调试应用时,您可能需要逐项停用其中的部分变更。

何时启用变更

对于受特定 targetSDKVersion 控制的变更,当应用的目标 SDK 版本低于该控制版本时,这些变更在默认情况下会处于停用状态。通常,当您准备以新的 targetSdkVersion 为目标平台时,您将获得一个行为变更列表,您需要针对这些变更测试和调试应用。

例如,您可能需要针对下一 targetSdkVersion 中的一系列平台变更测试您的应用。您可以使用开发者选项或 adb 命令逐个启用和测试受 targetSDKVersion 控制的变更,而不是更改应用清单并一次性选择启用所有变更。

这项附加控制可以帮助您单独测试各项变更,避免同时调试和更新应用的多个部分。

启用变更后,您可以使用典型的测试工作流测试和调试应用。如果您遇到问题,请查看日志以帮助确定问题的原因。如果不确定该问题是否由已启用的某项平台变更导致,请尝试停用该变更,然后重新测试应用的相应区域。

启用或停用变更

兼容性框架支持您使用开发者选项或 adb 命令启用或停用各项变更。由于启用或停用变更可能会导致应用崩溃或停用重要的安全变更,因此对于何时可以切换变更的启用/停用状态有一些限制。

使用开发者选项启用或停用变更

您可以使用开发者选项启用或停用变更。如需找到开发者选项,请按以下步骤操作:

  1. 如果开发者选项尚未启用,请启用开发者选项。
  2. 打开设备的“设置”应用,导航到系统 > 高级 > 开发者选项 > 应用兼容性变更。
  3. 从列表中选择您的应用。
  4. 在变更列表中,找到想要开启或关闭的变更,然后点按相应的开关。
可以开启或关闭的变更列表
图 2. 启用或停用变更。

使用 adb 开启或关闭变更

如需使用 adb 开启或关闭变更,请运行以下相应的命令:

adb shell am compat enable (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME
adb shell am compat disable (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME

您需要传递 CHANGE_ID(例如 194833441)或 CHANGE_NAME(例如 NOTIFICATION_PERM_CHANGE_ID)以及应用的 PACKAGE_NAME。

您也可以使用以下命令将变更重置回默认状态,移除您使用 adb 或开发者选项设置的任何替换状态:

adb shell am compat reset (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME

切换变更的启用/停用状态的限制

默认情况下,每项行为变更不是处于启用状态,就是处于停用状态。影响所有应用的变更在默认情况下处于启用状态。其他变更的启用与否受 targetSdkVersion 控制。如果应用以相应的 SDK 版本或更高版本为目标平台,这些变更在默认情况下处于启用状态;如果应用的目标 SDK 版本低于该版本阈值,这些变更在默认情况下将处于停用状态。当您启用或停用某项变更时,会替换其默认状态。

为了避免兼容性框架遭到恶意使用,对于何时可以切换变更的启用/停用状态有一些限制。是否可以切换变更的状态取决于变更的类型、应用的可调试性,以及设备上运行的 build 类型。下表介绍了不同类型的变更的状态切换限制:

build 类型 不可调试的应用 可调试的应用
所有变更 受 targetSDKVersion 控制的变更 所有其他变更
开发者预览版或 Beta 版 build 无法切换 可以切换 可以切换
公开用户 build 无法切换 可以切换 无法切换