报错:
java.lang.RuntimeException: Unable to instantiate application com.tencent.bugly.beta.tinker.TinkerPatchReflectApplication: java.lang.IllegalStateException: java.lang.ClassNotFoundException: com.like.baseapplication.BaseApplication (主Application)
原因:
集成热更新后,运行的包未必一定是debug包,也可能是release包,运行开了混淆的release包时,主Application名称被混淆了,热更新库无法反射拿到主Application而报错崩溃。(未开启 enableProxyApplication 的同理)
解决:
如果你开了混淆,那我们的错误原因可能一样,因为主Application被混淆所导致,加上主Application的防混淆就行了。样板: -keep public class com.like.baseapplication.BaseApplication
如果你没开混淆,那么抱歉,我也不知道怎么解。
排查过程:
1、首先当然是百度了,我在闪退后立马搜索相关信息,希望找到很简单的修改方法,加一行代码就能好的那种,大家说的有 升级依赖版本、下官方Demo比较依赖版本 之类的,我下了个官方Demo却发现版本号相同,官方Demo能运行,我的却闪退,没解决问题。
2、我怀疑是不是哪里集成错了,于是新建了个测试项目,把集成代码都拷过去,结果正常运行,那就是这个项目的问题咯。于是我又拷过去依赖库,so文件,发现仍然能运行,我就蒙了,不是依赖问题也不是ndk问题,可剩下的这么多项目配置不好排查啊。
3、我放弃了,改为 enableProxyApplication = false 的继承方式,结果还是一样,在测试项目上正常,当前项目上就闪退。
4、我出门转了转,想到了可能是分包时把两个类分到不同的dex文件了,虽然我不懂这块,但有这个可能,可我搜 ClassNotFoundException 的时候发现有人说 ClassNotFoundException 和 NoClassDefFoundException 的区别在于 前者是在编译和运行阶段都找不到类,后者是编译时找得到,运行时找不到,而我想的分包问题网上说报的错只会是后者。
5、于是我开始反编译,发现apk中确实没有主Application的类文件,而且有很多被混淆的类,我惊了,我是直接运行的啊,应该是debug包才对,怎么被混淆了!我这才发现在 build/bakApk 中生成的包文件名都是 release,并配上了 mapping 文件。
6、我关闭了混淆,却还是报错,一阵忙活之后发现仍然被混淆了,坑啊!我连指定混淆文件的代码都注释后才自动换成 debug 包。
7、最终发现,运行debug包没事,运行release包加上防混淆后也没事。此外,我实验发现能通过Studio左下角的Build Variants改打的包类型,但不是一定能切成功的,坑。
此外,还发现了以下一些坑(个人排坑记录):
1、开发文档中说的“并启动上报过联网”,意思是集成了热更新的App(release包)必须先启动一次,这次启动会上报版本号,bugly会记录这个版本号,之后去bugly后台加更新补丁的时候会查询这个版本号,如果查不到就会报错。
我第一次看他的描述,还以为需要去bugly后台上传个release包。
2、bugly 热更新 SDK 更新慢,目前不兼容 Gradle 5.0 以上(1.3.6版)。
3、下发热更新补丁时一定要选择全量设备,选择开发设备是没用的。
4、补丁不是立即生效的,要等5分钟。