20、备份与恢复:adb backup、adb restore 与 adb shell bmgr
说实话,做 Android 开发这么多年,我见过太多开发者因为数据丢失而抓狂的场景。我自己就曾经在调试一个社交应用时,不小心把测试账号的本地数据库给清了,里面全是模拟的好友关系链……那叫一个欲哭无泪。
从那以后,我养成了一个习惯:每次做重大操作前,先备份。今天我们就来聊聊 Android 上的三把数据保护利器——adb backup、adb restore 和 adb 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 知识体系总览
下面这张图总结了本章的核心内容,你可以把它当作一个快速参考:
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 秒钟备份一下,能省下好几个小时的痛苦。