查看原文
其他

昨天发布的版本,在老板的手机上崩溃了!

承香墨影 承香墨影 2022-04-23

程序员经常扬言,"这个 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 个优质问题,上桌联机学习。

公众号后台回复成长『成长』,将会得到我准备的学习资料,也能回复『加群』,一起学习进步。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存