兼容性框架工具

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

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

如何识别已启用的变更

您可以使用开发者选项、logcat 或 adb 命令查看当前已启用的行为变更。

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

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

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

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

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

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

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

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

    如果您的应用以高于所列 API 版本的 Android 版本为目标平台,默认情况下,这些变更会在兼容性框架中处于启用状态。例如,Android 11(API 级别 30)中受 targetSDKVersion 控制的行为变更会在界面的在 SDK 29 之后启用的应用兼容性变更部分中列出。

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

使用 logcat 识别已启用的变更

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

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

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

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

指示该变更当前是否正在影响应用。

状态可以是以下值之一:

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

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

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

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

使用 adb 识别已启用的变更

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

adb shell dumpsys platform_compat

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

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

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

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

软件包替换

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

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

packageOverrides={com.my.package=false}

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

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

详细了解具体变更

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

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

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

何时停用变更

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

对所有应用启用变更

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

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

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

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

targetSDKVersion 控制的变更

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

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

何时启用变更

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

例如,您可能需要针对下一 targetSdkVersion 中的一系列平台变更测试您的应用。您可以使用开发者选项或 adb 命令逐个启用和测试受 targetSDKVersion 控制的变更,而不是更改应用清单并一次性选择启用所有变更。这项附加控制可以帮助您单独测试各项变更,避免同时调试和更新应用的多个部分。

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

启用或停用变更

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

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

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

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

    可以开启或关闭的变更列表

使用 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(例如 119147584)或 CHANGE_NAME(例如 CALLBACK_ON_CLEAR_CHANGE)以及应用的 PACKAGE_NAME

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

adb shell am compat reset (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME

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

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

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

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