AndFix(续) - MultiDex

来源:互联网 发布:数据库应用有什么用 编辑:程序博客网 时间:2024/05/17 06:58

前言:
刚跌进了几个坑,又呛过了几条河,怎么程序bug它就这么多….


问题描述:
之前集成了AndFix,一路毫无障碍的过去了,可以看我的Android 热修复 - AndFix 使用心得,这是基本使用。然后搭档在MainActivity里面加了几个新类,我打完补丁,看到了一些奇怪的log,不过补丁确实是打出来了,正确的log是如前面介绍AndFix使用的文章中的log,就只会告诉你 add Modified method:……,其它什么都不会有,,结果在测试的时候,bugApk在loadPatch之后,再次打开APP,报错了,恩,没错 ClassNotFoundException & IllegaleAccessException,大写的蒙蔽!!!

沉思了一会儿,我把问题定位在 MultiDexApplication ,不知道这个的童鞋Google一下就出来,简而言之这个类的添加就是为了解决android 中 dex文件方法超出65536限制的情况。


分析:
既然之前的demo成功了,那么问题就不该是在AndFix上面,就只有可能是AndFix的patch机制和我的代码冲突了,于是我找到了关于AndFix的具体运作原理的博文:Android热补丁之AndFix原理解析。仔细阅读这篇博文后,对于我的问题简单的描述下:
1.使用 MultiDexApplication 之后,超出主dex限制的类会被打包成另外一个辅dex,而且除了一些比较重要的类也就是和APP启动有关的类会被优先打到主dex中,一些不影响APP启动的类的优先级次之,而且不是固定的。
2.AndFix制作patch补丁包的时候,仅仅比较了主dex文件,没有去比较其它的dex文件
那么问题就很明显了,我的问题就出在,我的bug.apk和fix.apk,dex都是不一定的,或者说我要修复的类都不一定在要比对的相应的dex包中,那么一定就会出问题。


思路一:
修改AndFix的patch机制,以及修改加载补丁的机制。这一定是可以实现的,而且我顺着这个思路也确实从网上找到了相应的牛人写的分享博文:AndFix支持Multidex的解决方案。他的思路非常明确,就是通过改变patch的比较机制,然后代码注入,最后修改相应的补丁机制。虽然思路我看明白了,而且这也是一劳永逸的方法,但是是需要大量的时间成本和测试的,项目一直赶着上线,我只能默默放弃(PS:而且感觉真的好复杂啊)。

思路二:
思路一至少目前不能投入那么大的精力去使用,那么针对项目如此着急的情况下,只能想想别的:
1.因为程序方法太多导致必须使用 MultiDexApplication ,要么就使用 dex 分包的技术,事实上都是一样的。
2.类找不是因为我打包的时候主dex中的类,或者说我需要的类没有被指定的打包到主dex中,导致了ClassNotFoundException。
那么,很显然,要解决的问题就是我需要指定我需要的类必须被打包到主dex文件中,简而言之:我要控制 dex 打包的部分流程,也就是控制那些类必须在主dex中。


解决:
参考博客:Android 分Dex (MultiDex)
思路:在build.gradle中配置和打包相关的配置文件,dex 文本,其中放入的类就会被打包到classes.dex中。
上具体图和代码:
build.gradle:

android {    compileOptions {        sourceCompatibility JavaVersion.VERSION_1_8        targetCompatibility JavaVersion.VERSION_1_8    }    compileSdkVersion 23    buildToolsVersion "24"    defaultConfig {        applicationId "com.xxx.xxx"        minSdkVersion 14        targetSdkVersion 23        versionCode 14        versionName "2.1.5"        multiDexEnabled = true        ndk {            abiFilter "armeabi"        }    }    lintOptions {        abortOnError false    }    productFlavors {        ...    }    packagingOptions {        exclude 'META-INF/DEPENDENCIES'        exclude 'META-INF/NOTICE'        exclude 'META-INF/LICENSE'        exclude 'META-INF/LICENSE.txt'        exclude 'META-INF/NOTICE.txt'        exclude 'META-INF/ASL2.0'        exclude 'META-INF/notice.txt'    }    dexOptions {        javaMaxHeapSize "2g"    }    useLibrary 'org.apache.http.legacy'    sourceSets.main {        assets.srcDirs = ['src/main/assets', 'src/assets/']        jni.srcDirs = []    }    afterEvaluate {        tasks.matching {            it.name.startsWith('dex')        }.each { dx ->            if (dx.additionalParameters == null) {                dx.additionalParameters = []            }            dx.additionalParameters += '--multi-dex'            dx.additionalParameters += "--main-dex-list=$projectDir/dex".toString()        }    }}

要贴加的就是

afterEvaluate {        tasks.matching {            it.name.startsWith('dex')        }.each { dx ->            if (dx.additionalParameters == null) {                dx.additionalParameters = []            }            dx.additionalParameters += '--multi-dex'            dx.additionalParameters += "--main-dex-list=$projectDir/dex".toString()        }    }

配置贴的比较全,相信看一下都会懂了。
再贴下 dex 的 txt 文本的位置:
这里写图片描述
dex和build.gradle同级。
dex 文件的具体内容:

android/support/multidex/CoreApiHelper/classandroid/support/multidex/UpdateAppEntity/classandroid/support/multidex/ISuccessBaseData/classandroid/support/multidex/HawkUtils/classandroid/support/multidex/NaviBottomBar/class...

亲测是可以用,感谢以上两篇博主的帮助,还有一些没有列出来的博文。
至此,AndFix线下就已经OK了,不会有乱七八糟的问题,当然我这个方法其实也是有隐患的,如果你是插件化的APP,那么我这个方法直接忽略,看思路一中介绍的方法,另外,事实上我这个方法也只是指标不治本,这是无奈之举,项目集成了太多类库,而且有点积重难反,刚刚接手的时候已经花了很大的力气删掉一些无用的类和方法、类库,期待公司给出时间重构吧。

如果,有朋友使用了思路一中的方法,希望能写一篇博客分享出来,毕竟那才是一劳永逸的正确方法。

1 0
原创粉丝点击