20、备份与恢复:adb backup、adb restore 与 adb shell bmgr

说实话,做 Android 开发这么多年,我见过太多开发者因为数据丢失而抓狂的场景。我自己就曾经在调试一个社交应用时,不小心把测试账号的本地数据库给清了,里面全是模拟的好友关系链……那叫一个欲哭无泪。

从那以后,我养成了一个习惯:每次做重大操作前,先备份。今天我们就来聊聊 Android 上的三把数据保护利器——adb backupadb restoreadb shell bmgr

20.1 为什么需要备份与恢复?

你想想看,应用数据有多重要?用户的登录状态、本地缓存、数据库、SharedPreferences……这些东西一旦丢了,轻则重新登录,重则用户直接卸载你的 App。

备份与恢复的核心场景有三个:

  • 调试前保护:在修改数据库结构或测试新功能前,先备份当前数据
  • 设备迁移:换手机时把应用数据完整迁移过去
  • 故障恢复:应用崩溃导致数据损坏时,用备份恢复

核心原则:备份不是可选项,而是开发流程中的必备环节。我见过太多人因为省这一步,最后花了两天时间重新造数据。

20.2 adb backup:把应用数据打包带走

adb backup 是 Android 提供的一个命令行工具,它能把指定应用的数据打包成一个 .ab 文件。说白了,就是把应用的私有目录(/data/data/包名)整个压缩出来。

20.2.1 基本用法

# 备份单个应用的数据
adb backup -f myapp_backup.ab com.example.myapp

# 备份所有应用的数据(需要 root)
adb backup -all

# 备份时包含 APK 本身
adb backup -apk -f myapp_with_apk.ab com.example.myapp

参数说明:

参数 含义
-f 指定输出文件名,默认是 backup.ab
-apk 同时备份 APK 文件
-noapk 只备份数据,不备份 APK
-shared 备份共享存储(SD 卡)中的数据
-all 备份所有已安装的应用

我的习惯:我一般只用 -f 和包名,不备份 APK。因为 APK 随时可以重新安装,但数据丢了就真没了。而且不带 -apk 的话,备份文件会小很多。

20.2.2 备份文件长什么样?

.ab 文件其实是一个加密的 tar 包。你可以用 dd 命令把它转换成普通的 tar 文件:

# 跳过前 24 字节的文件头
dd if=myapp_backup.ab bs=24 skip=1 | openssl zlib -d > backup.tar
tar -xvf backup.tar

嗯,这里要注意:如果备份时设置了密码,那这个转换就没用了,因为数据是加密的。

20.3 adb restore:把数据还回去

有备份就得有恢复。adb restore 就是干这个的。用法极其简单:

adb restore myapp_backup.ab

执行后,手机会弹出一个确认对话框,让你确认是否要恢复数据。点击「恢复我的数据」即可。

我曾经踩过的坑:有一次我恢复数据时,忘记先卸载旧版本的应用。结果恢复后,应用直接闪退。原因是备份里的数据库版本和当前 APK 的数据库版本不一致。所以,恢复前最好先卸载应用,再重新安装,最后恢复数据

20.3.1 恢复的注意事项

  • 版本匹配:备份和恢复时的应用版本最好一致,否则可能出兼容性问题
  • 签名一致:如果应用签名变了,恢复会失败
  • Android 版本:高版本 Android 对备份恢复的限制更严格,Android 12+ 需要应用显式声明支持备份

20.4 adb shell bmgr:备份管理器的高级玩法

bmgr 是 Backup Manager 的缩写,它是 Android 系统内部管理备份服务的工具。说实话,这个工具平时用得不多,但在调试备份逻辑时特别好用。

20.4.1 基本命令

# 查看当前备份传输方式
adb shell bmgr list transports

# 触发指定应用的备份
adb shell bmgr backupnow com.example.myapp

# 触发指定应用的恢复
adb shell bmgr restore com.example.myapp

# 查看备份状态
adb shell bmgr status

20.4.2 实际应用场景

我记得有一次,我在测试应用的 BackupAgent 实现是否正确。用 adb backup 太慢了,每次都要手动确认。后来发现 bmgr backupnow 可以直接触发备份,而且不需要用户交互,非常适合自动化测试。

# 强制备份,跳过用户确认
adb shell bmgr backupnow --all

# 只备份指定包
adb shell bmgr backupnow com.example.myapp

小技巧:如果你在开发自定义的 BackupAgent,可以用 bmgr 来反复测试备份和恢复流程,而不需要每次都卸载重装应用。这能节省大量时间。

20.5 知识体系总览

下面这张图总结了本章的核心内容,你可以把它当作一个快速参考:

Android 备份与恢复知识体系 adb backup adb restore adb shell bmgr -f 指定文件 -apk 含APK -all 全部应用 版本匹配 签名一致 先卸载再恢复 backupnow restore status 状态 核心原则:先备份,再操作;版本匹配,签名一致 使用场景:调试保护 | 设备迁移 | 故障恢复 Android ADB 从入门到精通 · 第20章

20.6 实战:完整备份与恢复流程

说了这么多,我们来走一遍完整的流程。假设你要调试一个叫 com.example.myapp 的应用:

步骤一:备份当前数据

adb backup -f myapp_before_debug.ab com.example.myapp

手机会弹出确认框,点击「备份我的数据」。等待几秒钟,备份完成。

步骤二:进行调试操作

随便你怎么折腾,改数据库、清缓存、测试新功能……反正数据丢了也不怕。

步骤三:恢复数据

# 先卸载应用
adb uninstall com.example.myapp

# 重新安装
adb install app-debug.apk

# 恢复数据
adb restore myapp_before_debug.ab

为什么先卸载再安装? 因为如果直接恢复,系统可能会因为数据库版本号冲突而拒绝恢复。卸载后重新安装,相当于给应用一个「干净」的环境,恢复成功率更高。

20.7 常见问题与避坑指南

  • 备份文件太大怎么办? 可以用 -noapk 参数,只备份数据,不备份 APK。我见过有人备份一个游戏,APK 就 2GB,数据才 50MB……
  • 恢复时提示「设备不支持」? 检查一下 Android 版本。Android 12 以后,应用必须在 Manifest 中声明 android:allowBackup="true" 才能被备份。
  • bmgr 命令没反应? 确保你的设备已经 root,或者至少是 userdebug 版本。普通用户设备上 bmgr 的权限有限。

我曾经犯过的错:有一次我备份了一个应用,然后升级了系统,再恢复数据。结果应用直接崩溃,因为备份里的数据库是旧版本的,而新系统上的应用已经升级了数据库结构。从那以后,我每次恢复前都会检查版本号。

好了,关于备份与恢复的内容就这些。记住一句话:备份不是浪费时间,而是在为未来的自己买保险。下次做重大操作前,花 10 秒钟备份一下,能省下好几个小时的痛苦。

公众号:蓝海资料掘金营,微信deep3321