测试备份和恢复

本页介绍了如何测试应用的云端备份和设备到设备 (D2D) 传输过程。请务必对应用的每个主要版本执行这两项测试,以确保用户能在新设备上继续使用您的应用。虽然备份与传输类似,但在 Android 12(API 级别 31)及更高版本中,两者之间存在重大差异;最值得注意的是,传输的数据大小上限为 2 GB,云端备份的数据大小上限则为 25 MB,前者远大于后者。

本指南将为您介绍如何在整个开发周期中对云端备份/恢复以及 D2D 传输进行高效测试。

测试备份的运作方式

本部分介绍了 Android 备份框架中的各个部分,以及它们如何与支持自动备份和键值对备份的应用交互。在应用开发阶段,由于该框架的大部分内部运作机制都隐藏在抽象出来的接口之后,因此您无需了解这些具体机制。但是,在测试阶段,了解这些概念变得愈发重要。

下图说明了在云端备份和恢复期间数据会如何流动。如果是进行测试,可使用同一设备进行云端备份和恢复。

备份框架数据流

下图说明了在 D2D 传输期间数据会如何流动:

传输框架数据流

与云端备份和恢复测试不同,D2D 测试是在来源设备和目标设备之间复制数据,因此需要使用这两类设备。

Backup Manager Service 是一项 Android 系统服务,可以编排并启动备份和恢复操作。您可以通过 Backup Manager API 访问该服务。

在执行备份操作的过程中,该服务会查询您的应用以获取备份数据,然后将其传递给备份传输服务,后者随后会将数据归档到云端。在执行恢复操作的过程中,Backup Manager Service 会从备份传输服务检索备份数据,然后将该数据恢复到设备。如果是 D2D 传输,Backup Manager Service 会查询您的应用以获取备份数据,并将其直接传递给新设备上的 Backup Manager Service,由该服务将数据加载到您的应用中。

备份传输服务是负责存储和检索备应用数据的 Android 组件。Android 设备可以有零个或更多个备份传输服务,但只能将其中一个备份传输服务标记为有效。由于设备制造商和服务提供商所做的定制,可用的备份传输服务可能因设备而异,但大多数支持 Google Play 的设备都会搭载以下传输服务:

  • GMS 传输服务:大多数设备上搭载的有效云端备份传输服务,是 Google 移动服务的一部分。此传输服务会将数据存储在 Android Backup Service 中。
  • D2D 传输服务:用于 D2D 迁移,可将数据从一个设备直接传输到另一个设备。

工具

如需测试备份和恢复操作,您需要对以下工具有一定了解。

  • adb:用于在设备或模拟器上运行命令。
  • bmgr:用于执行各种备份和恢复操作。
  • logcat:用于查看备份和恢复操作的输出。

测试云端备份

您只需按照本部分列出的步骤,便可使用单一设备执行云端备份和恢复。

准备设备或模拟器进行云端备份

请参照以下核对清单准备您的设备或模拟器,以进行备份测试:

  1. 对于自动备份,请检查您使用的是否是搭载 Android 6.0(API 级别 23)或更高版本的设备或模拟器。
  2. 对于键值对备份,请检查您使用的是否是搭载 Android 2.2(API 级别 8)或更高版本的设备或模拟器。
  3. 必须连接到互联网,才能测试云端备份。
  4. 使用 Google 账号登录设备,然后依次前往设置 -> Google -> 备份,将该账号设为备份账号。

若要测试云端备份,请先触发云端备份功能,然后卸载并重新安装应用。如果您希望能够重复执行这些步骤,可以使用 test_cloud_backup.sh 脚本来备份应用、在本地下载 APK、卸载以及重新安装 APK:

#!/bin/bash -eu
: "${1?"Usage: $0 package name"}"

# Initialize and create a backup
adb shell bmgr enable true
adb shell bmgr transport com.android.localtransport/.LocalTransport | grep -q "Selected transport" || (echo "Error: error selecting local transport"; exit 1)
adb shell settings put secure backup_local_transport_parameters 'is_encrypted=true'
adb shell bmgr backupnow "$1" | grep -F "Package $1 with result: Success" || (echo "Backup failed"; exit 1)

# Uninstall and reinstall the app to clear the data and trigger a restore
apk_path_list=$(adb shell pm path "$1")
OIFS=$IFS
IFS=$'\n'
apk_number=0
for apk_line in $apk_path_list
do
    (( ++apk_number ))
    apk_path=${apk_line:8:1000}
    adb pull "$apk_path" "myapk${apk_number}.apk"
done
IFS=$OIFS
adb shell pm uninstall --user 0 "$1"
apks=$(seq -f 'myapk%.f.apk' 1 $apk_number)
adb install-multiple -t --user 0 $apks

# Clean up
adb shell bmgr transport com.google.android.gms/.backup.BackupTransportService
rm $apks

echo "Done"

测试步骤

  1. 打开所需应用,登录并修改所有设置。
  2. 运行脚本并传入软件包名称,例如 test_cloud_backup.sh com.example.myapp
  3. 重新打开该应用,验证其是否能正常运作并保留所有数据。

最好取消用户登录步骤,且对方的所有设置、进度和应用数据都必须与之前相同。如果测试结果不符合这些标准,请确保您已正确配置了备份,没有遗漏关键数据,并且务必要重新创建备份中排除的任何缓存数据。您可以针对每次测试迭代重复第 1-3 步。

测试 D2D 传输

测试 D2D 传输最全面的方法是将整个手机内容传输到已恢复出厂设置的新设备上,并验证其是否能正常运作。但是,如果您需要多次重复该过程,可能会觉得麻烦,而且非常耗时。下面的步骤将向您展示,在不对设备重复执行恢复出厂设置的情况下,如何使用单一设备模拟传输。

准备设备进行 D2D 测试

若要在单一设备上测试 D2D 传输,请按以下说明做好准备:

  1. 您的设备必须搭载 Android 12(API 级别 31)或更高版本的系统。
  2. 若要测试最新版本的 D2D,请在您的应用中指定以 Android 12(API 级别 31)或更高版本为目标平台。
  3. 创建 test_d2d.sh 脚本,以便重复执行测试:
#!/bin/bash -eu
: "${1?"Usage: $0 package name"}"

# Initialize and create a backup
adb shell bmgr enable true
adb shell settings put secure backup_enable_d2d_test_mode 1
adb shell bmgr transport com.google.android.gms/.backup.migrate.service.D2dTransport
adb shell bmgr init com.google.android.gms/.backup.migrate.service.D2dTransport
adb shell bmgr list transports | grep -q -F "  * com.google.android.gms/.backup.migrate.service.D2dTransport" || (echo "Failed to select and initialize backup transport"; exit 1)
adb shell bmgr backupnow "$1" | grep -F "Package $1 with result: Success" || (echo "Backup failed"; exit 1)

# Uninstall and reinstall the app to clear the data and trigger a restore
apk_path_list=$(adb shell pm path "$1")
OIFS=$IFS
IFS=$'\n'
apk_number=0
for apk_line in $apk_path_list
do
    (( ++apk_number ))
    apk_path=${apk_line:8:1000}
    adb pull "$apk_path" "myapk${apk_number}.apk"
done
IFS=$OIFS
adb shell pm uninstall --user 0 "$1"
adb shell bmgr transport com.google.android.gms/.backup.BackupTransportService
apks=$(seq -f 'myapk%.f.apk' 1 $apk_number)
adb install-multiple -t --user 0 $apks

# Clean up
adb shell bmgr init com.google.android.gms/.backup.migrate.service.D2dTransport
adb shell settings put secure backup_enable_d2d_test_mode 0
adb shell bmgr transport com.google.android.gms/.backup.BackupTransportService
rm $apks

echo "Done"

测试步骤

  1. 在设备上安装要测试的应用。
  2. 打开应用并登录,然后修改该应用的设置。
  3. 在设备上运行脚本,传入软件包名称,例如 test_d2d.sh com.example.myapp
  4. 脚本运行完毕后,在设备上打开应用,验证其是否能正常运作并保留所有数据。

最好取消用户登录步骤,且对方的所有设置、进度和应用数据都必须与运行脚本之前相同。如果测试结果不符合这些标准,请确保您已正确配置了传输,没有遗漏关键数据,并且务必要重新创建传输中排除的任何缓存数据。您可以针对每次测试迭代重复第 2-4 步。

对备份和恢复进行问题排查

本部分将帮助您排查一些常见问题。

超出传输配额

如果 Logcat 中出现以下消息,则表明您的应用已超出传输配额:

I/PFTBT: Transport rejected backup of <PACKAGE>, skipping

--- or ---

I/PFTBT: Transport quota exceeded for package: <PACKAGE>

请减少备份数据量,然后重试。例如,确认您是否仅将数据缓存到应用的缓存目录中。缓存目录并未包含在备份范围内。

无法执行完整备份

如果 Logcat 中出现以下消息,则表明完整备份操作失败,原因是设备上尚未发生任何键值对备份操作:

I/BackupManagerService: Full backup not currently possible -- key/value backup
not yet run?

请使用命令 bmgr run 触发键值对备份,然后重试。

等待代理超时

如果 Logcat 中出现以下消息,则表明您的应用启动备份所用的时间超过 10 秒:

12-05 18:59:02.033  1910  2251 D BackupManagerService:
    awaiting agent for ApplicationInfo{5c7cde0 com.your.app.package}
12-05 18:59:12.117  1910  2251 W BackupManagerService:
    Timeout waiting for agent ApplicationInfo{5c7cde0 com.your.app.package}
12-05 18:59:12.117  1910  2251 W BackupManagerService:
    Can't find backup agent for com.your.app.package

请注意日志输出中的时间戳差异。在无 ProGuard 的情况下,您的应用如果使用 MultiDex 配置,通常会发生此错误。

备份账号未初始化

如果 Logcat 中出现以下消息,则表明备份操作已暂停,原因是备份数据集未初始化:

01-31 14:32:45.698 17280 17292 I Backup: [GmsBackupTransport] Try to backup for
an uninitialized backup account.
01-31 14:32:45.699  1043 18255 W PFTBT: Transport failed; aborting backup: -1001
01-31 14:32:45.699  1043 18255 I PFTBT: Full backup completed with status: -1000

请使用命令 adb shell bmgr run 运行备份管理器,然后再次尝试执行备份。

应用方法未被调用

由于自动备份功能使用 Application 的基类启动应用,应用的设置方法可能不会被调用。自动备份功能也不会启动应用的任何 activity,因此如果应用在一个 activity 中执行了设置操作,系统可能会显示错误。如需了解详情,请阅读实现 BackupAgent

相反,键值对备份会使用您在应用清单文件中声明的任何 Application 子类启动您的应用。

没有数据要备份

如果 Logcat 中出现以下消息,则表明您的应用没有数据要备份:

I Backup  : [FullBackupSession] Package com.your.app.package doesn't have any backup data.

--- or ---

I Backup  : [D2dTransport] Package com.your.app.package doesn't have any backup data.

如果您实现了自己的 BackupAgent,这可能表示您没有在备份中添加任何数据或文件。