兼容性问题:
因在游戏公司项目中,存在大量的多渠道,情况会变得复杂化。
在使用Lancet 修复Toast 问题过程中,发现在抖音直播渠道包中,使用Lance字节编码失败,报错如下所示:
从上面报错可知,Lance 插件无法解析Scope.ALL_SELF
导致编译失败。
定位分析
查看ReceiverRegisterLancet所在的代码,基于字节的com.bytedance.ttgame:gbsdk_common_host
远程库下,详情如下:
在于饿了么的Lancet 库,进行比对,发现: 字节的库使用的基于Lancet二次开发的库,与原有的Lancet对不上,详情如下所示
解决方案:
使用另外的字节编码方案来修复7.1 系统Toast Bug, 比如滴滴出行开源的Booster,更多详情阅读Booster使用文档 。
在Booster 中,也是通过Hook Toast 方式(即 hook TN#Handler)
, 来进行对class 的全局替换,最后生成Apk。
因Lancet 的功能非常强大,可以实现许多功能,因此,只在冲突的渠道包上改用Booster 来处理Toast问题,其他渠道上正常使用Lancet 修复Toast问题。
根据渠道包动态使用Lancet 插件或者Booster插件,为了尽可能避免字节编码导致apk调试不上的问题,只在Release正式包中使用字节编码。
在项目根目录下的build.gradle
:
buildscript {
ext.ams_open=false // 是否开启字节编码
ext.use_booster=false// 是否使用booster
gradle.startParameter.taskNames.any {
//通过判断任务名字,区分当前是打包哪个渠道包。对抖音直播 上Lancet 会冲突,改用booster
// 若是后续还有渠道与lancet冲突,在这里添加变种名字
use_booster=it.contains('douyinzhibo')|| it.contains('Douyinzhibo')
//debug 包下不启用,防止调试断点不上
ams_open=it.contains("release")||it.contains("Release")
println "gradle.ext.ams_open->$ams_open "+" use_booster->$use_booster"
}
repositories {
//......
}
dependencies {
//......
if (ams_open){
if (use_booster){
ext.booster_version = '4.15.0'
classpath "com.didiglobal.booster:booster-gradle-plugin:$booster_version"
classpath "com.didiglobal.booster:booster-transform-toast:$booster_version"
}else{
//lancet 字节编码
classpath 'com.bytedance.tools.lancet:lancet-plugin-asm6:1.0.2'
}
}
}
}
在app Module中的build.gradle
:动态加载对应的plugin插件
apply plugin: 'com.android.application'
if (ams_open){
//动态加载plugin插件
if (use_booster) {
apply plugin: 'com.didiglobal.booster'
}else{
apply plugin: 'me.ele.lancet'
}
}
关于Lancet 修复Toast 问题,请阅读上篇Android Lancet Aop 字节编码修复7.1系统Toast问题(WindowManager$BadTokenException)
验证:
当编译渠道包时,可看到字节编码开关是否开启,和是否使用Booster 。
当最终生成apk 后,可查看,是否已经全局替换成功:
从apk看的结果,可知已经替换换成Booster 中hook Toast 方案,详情如下: