昨天发布的版本,在老板的手机上崩溃了!
程序员经常扬言,"这个 Bug 你能复现,我就能改"。
但是又有多少 Bug 是可以必现的?大部分难以解决的 Bug,都是偶现的,只在特定场景下才会出现。
如果是一个导致崩溃的 Bug,我们可以通过搜集崩溃现场信息,例如崩溃栈、内存情况、各种资源使用情况,来从侧面分析这个 Bug 发生的原因。
但如果是不会引发崩溃的 Bug 呢?它只是让业务逻辑不正常。
这类 Bug,问题十有八九出自数据,可能数据量到达一定量级之后,出现的问题;也可能是因为在某些逻辑下,持久化了一些脏数据导致的。总之,这类 Bug,保留现场的数据,对于我们复现 Bug 现场,是非常重要的。
我们持久化数据的手段,比较常用的就是 SharePreferences、SQLite、File 等,为了保证这些数据的安全,这些数据还都存在 App 的私有目录下。
那现在的问题,就变成了,如何保留现场的数据的同时,构造一个方便我们调试的环境。这里面的难点在于,出现问题的场景,是 Release 版本,我们需要把它变成 Debug 的环境。
这种场景,有两个方案可以选择:
1. 备份后还原
如果你的 App 开启了允许备份(android:allowBackup=true),就可以通过 ADB 命令 adb backup
将其数据备份,再通过 adb restore
命令,在一台新设备上对数据进行还原。
但是这种方案有缺陷,就是需要依赖 Android 的自动备份功能,这个功能会有安全隐患,一般在发布的 App 中,都建议关掉。不了解的看看这篇文章《Android 的备份和还原》。
2. 将 Release 替换成 Debug
如果我们可以在保留数据的情况下,将手机上安装的 Apk 从 Release 版本,切换到 Debug 版本,就可以方便我们进行调试了。
这就需要一些技巧了。正常我们覆盖安装 Apk 的时候,会经历一系列的校验。
例如:
签名要一致。
版本号要大于安装的版本。
targetSdkVersion 不能低于当前安装的版本。
而通过正常的手段,我们无法直接使用 Debug-Apk 覆盖安装一个 Release-Apk,Android 的安装器会提示失败。
这种时候,就需要借助 ADB 命令。我们常用的 adb install
也无法对此类场景进行覆盖安装,需要额外添加参数 -r
。
查看 ADB 命令的帮助文档,发现 -r
会强制替换 App,而不会清理 App 持久化的数据,这正是我们需要的。
是不是很简单,核心就是 adb install -r
命令,但是这也有一些前提条件。
1、Debug 包,需要使用 Release 签名。
如果签名不对,使用 ADB 命令,也无法覆盖,所以需要我们在 Debug 包上,使用 Release 签名。
Gradle 提供了很好的构建服务,直接在 build.gradle 文件中,配置 singingConfig 即可。
2、不要使用 run 起来的包。
虽然这里说的是使用 Debug 包,但是也需要使用 Gradle 命令,通过打包流程生成的 Apk,命令:./gradlew assembleDebug
。
那是不是 run 出来的包,一定不能用呢?
其实不然,再在 ADB 命令上加个参数 -t,adb install -r -t a.apk
,就可以允许使用 test 的包。
不过,在这种场景下,依然建议使用正常的打包流程生成的 Apk。
到这里,就可以直接替换一个 Release 包,使其变成可以可调试的 Debug 版本。
小结时刻
最后再小结一下。
针对脏数据出现异常的情况,我们需要保留数据场景进行调试。有两种方案:
1. 利用 allowBackup 备份数据再还原,使用前提是开启了允许备份。
2. 使用 adb install -r 替换应用。前提是需要保证 Debug 和 Release 包的签名一致,并且使用打包流程生成 Debug 包。
本文对你有帮助吗?留言、转发、点好看是最大的支持,谢谢!
「」👈推荐我的知识星球,一年 50 个优质问题,上桌联机学习。
公众号后台回复成长『成长』,将会得到我准备的学习资料,也能回复『加群』,一起学习进步。