测试备份和恢复

此页面介绍如何测试应用的云备份和设备到设备 (D2D) 传输流程。务必在每次主要应用版本发布时都测试这两项功能,以帮助确保用户能够继续在新设备上使用您的应用。虽然备份和传输都比较相似,但在 Android 12(API 级别 31)及更高版本中,两者之间存在重要差异——最值得注意的是,传输的数据大小限制更大,为 2 GB,而云备份的数据大小限制为 25 MB。

本指南介绍如何在整个开发周期中有效地测试云备份和恢复以及 D2D 传输。

备份测试的工作原理

本部分介绍 Android 备份框架中的各个部分以及它们如何与支持自动备份和键值备份的应用交互。在应用开发阶段,框架的大部分内部工作都被抽象化了,因此您无需了解这些信息。但是,在测试阶段,了解这些概念变得更加重要。

下图说明了云备份和恢复期间数据流向。出于测试目的,同一设备可用于云备份和恢复。

Backup Framework Data Flow

下图说明了 D2D 传输期间数据流向

Transfer Framework Data Flow

与云备份和恢复测试不同,D2D 测试需要源设备和目标设备来进行复制。

备份管理器服务是 Android 系统服务,用于协调和启动备份和恢复操作。可以通过 Backup Manager API 访问此服务。

在备份操作期间,服务会查询您的应用以获取备份数据,然后将其传递给备份传输,然后备份传输将数据存档到云端。在恢复操作期间,备份管理器服务从备份传输中检索备份数据,并将数据恢复到设备。对于 D2D 传输,备份管理器服务会查询您的应用以获取备份数据,并将其直接传递到新设备上的备份管理器服务,后者会将其加载到您的应用中。

备份传输是 Android 组件,负责存储和检索您的应用数据。Android 设备可以具有零个或多个备份传输,但只有一个传输可以标记为活动状态。由于设备制造商和服务提供商的自定义,可用备份传输因设备而异,但大多数支持 Google Play 的设备都附带以下传输

  • GMS 传输:大多数设备上的活动云备份传输,是 Google 移动服务 的一部分。此传输将数据存储在 Android 备份服务中。
  • 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 的情况下使用多 dex 配置时。

备份帐户未初始化

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,这可能意味着您尚未向备份添加任何数据或文件。