Open alen252 opened 4 years ago
I have same error
如果已经分包了在主工程的gradle中加入这两句试试 android.enableD8.desugaring = false android.useDexArchive = false
@erge1223 问题解决了吗
已经解决了我的事as 的版本问题 按照我上面的配置就解决了,但是我不知道你的是什么情况
tinker版本 1.9.14.5 gradle 插件版本 3.2.1 as版本 3.5.1 @erge1223 我在工程的gradle.properties 中申明了
android.enableD8.desugaring = false
android.useDexArchive = false
依然会有一下merge jar的异常
Not including classes with runtime retention annotations in the main dex.
This can cause issues with reflection in older platforms.
:main:transformClassesWithDexForRelease FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':main:transformClassesWithDexForRelease'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexException: Too many classes in --main-dex-list, main dex capacity exceeded
请指教。
分包有没有做
分包有没有做
分包指的是 Multidex还是分模块,目前我是多模块,tinker独立模块,也开启 MultiDex
@erge1223 我们minSdk为19,低于5.0要自己干预分包吗
minSdk低于21手动分包大于21自动分包
Multidex分包吧你的tinker 有些优先加载的类要放到主dex文件中 文档中好像有介绍
@erge1223 MultiDex.install 不是会自动兼容吗? 你的意思是在MultiDex.install之上,tinker会把一些类主动放入dex里面,可能出现溢出吗?
是的
是的
好的,感谢答复,我先尝试下。
android.enableD8.desugaring = false android.useDexArchive = false关掉d8试一下其他的我也没有什么好的解决方案
这两个关闭也不好使了。 @erge1223
com.android.dex.DexException: Too many classes in --main-dex-list, main dex capacity exceeded
@erge1223 @alen252 总算可以了,留下踩过坑的记录。 开发环境背景
tinker版本 1.9.14.5
gradle 插件版本 3.2.1
as版本 3.5.1
出现问题
问题1. android所有版本下,项目使用了java8特性,D8处理失败
问题2. 5.0以下版本默认使用官方 MultiDex 处理,出现 “Too mang classes...” 编译失败
解决问题
解决问题1:关闭D8脱糖,关闭增量处理dex
解决问题2:自主删除 maindexlist文件下的classes
具体解决实现: 主工程下 gradle.properties 添加解决问题1的配置
android.enableD8.desugaring = false
android.useDexArchive = false
主模块下目录(与build.gradle 同级,可自主调整)新增文件 “main_dex_split_for_tinker.gradle” 用于修改maindexlist文件内容。 文件内容如下
project.afterEvaluate {
//解决开启tinker时打包失败问题 Too many classes in --main-dex-list, main dex capacity exceeded。 exclude_class.txt中配置排除的类
//一定要验证5.0以下android启动时是否崩溃!
if (android.defaultConfig.minSdkVersion.getApiLevel() >= 21) {
return
}
if (project.hasProperty("tinkerPatch") == false) {
return
}
def configuration = project.tinkerPatch
if (!configuration.tinkerEnable) {
return
}
android.applicationVariants.all { variant ->
def variantName = variant.name.capitalize()
def multidexTask = project.tasks.findByName("transformClassesWithMultidexlistFor${variantName}")
if (multidexTask != null) {
def splitTask = createSplitDexTask(variant);
multidexTask.finalizedBy splitTask
}
}
}
def createSplitDexTask(variant) {
def variantName = variant.name.capitalize()
return task("replace${variantName}MainDexClassList").doLast {
//从主dex移除的列表
def excludeClassList = []
File excludeClassFile = new File("${project.projectDir}/exclude_class.txt")
if (excludeClassFile.exists()) {
excludeClassFile.eachLine { line ->
if (!line.trim().isEmpty() && line.startsWith("#") == false) {
excludeClassList.add(line.trim())
}
}
excludeClassList.unique()
}
def mainDexList = []
File mainDexFile = new File("${project.buildDir}/intermediates/legacy_multidex_main_dex_list/${variant.dirName}/transformClassesWithMultidexlistFor${variantName}/maindexlist.txt")
println "${project.buildDir}/intermediates/legacy_multidex_main_dex_list/${variant.dirName}/transformClassesWithMultidexlistFor${variantName}/maindexlist.txt exist : ${mainDexFile.exists()}"
if (mainDexFile.exists()) {
mainDexFile.eachLine { line ->
if (!line.isEmpty()) {
mainDexList.add(line.trim())
}
}
mainDexList.unique()
if (!excludeClassList.isEmpty()) {
def newMainDexList = mainDexList.findResults { mainDexItem ->
def isKeepMainDexItem = true
for (excludeClassItem in excludeClassList) {
if (mainDexItem.contains(excludeClassItem)) {
isKeepMainDexItem = false
break
}
}
if (isKeepMainDexItem) mainDexItem else null
}
if (newMainDexList.size() < mainDexList.size()) {
mainDexFile.delete()
mainDexFile.createNewFile()
mainDexFile.withWriterAppend { writer ->
newMainDexList.each {
writer << it << '\n'
writer.flush()
}
}
}
}
}
}
}
在同级目录新增文件 “exclude_class.txt” 用于指明哪些class需要剔除。(可自定删减,我只写我需要删除的)
#类路径包含如下的,都会建议打包工具不要打到主dex中,但可能还会被打到主dex中。由于所有的业务代码都会在multidex.install后执行,理论上所有的业务代码都可以不在主dex中
com/facebook/fresco
com/facebook/drawee
com/facebook/imageformat
com/facebook/imagepipeline
#暂时只剔除Facebook下代码
com/alibaba
com/taobao
com/eclipsesource/v8
net/sourceforge/pinyin4j/
com/amitshekhar/
net/sqlcipher/
android/arch/persistence/room/
com/tencent/qqlive/
com/alibaba/
okhttp3/
com/github/mikephil/charting/
com/squareup/haha/
com/github/tony19/
org/jetbrains/anko/
kotlin/
com/squareup/
com/airbnb/
android/support/v
com/facebook/fresco/
com/facebook/stetho/
com/google/android/flexbox/
com/sixgod/pluginsdk/
最后在主目录的build.gradle apply下这个上面的脚本就行了。
apply from: 'main_dex_split_for_tinker.gradle'
经过测试,在5.0以上及5.0以下都正常运行了。
其实你在debug模式删除无用资源开启混淆应该也可以
其实你在debug模式删除无用资源开启混淆应该也可以
目前我测试的都是在release,因为后续项目 jenkins 只针对release版本处理了。 debug模式有区别吗
因为我们项目的release版本与debug版本的配置是不一样的,我们项目只在debug模式下才会出现这种问题
@erge1223 soga。debug模式我们就没有关注了。一般版本回归之后打发布版本的时候留下个母包就可以了。debug模式下加入tinker可能会让编译速度收到影响呢。
可以问题解决了就行
这问题烦躁的很啊...
@YummyLau 我的解决办法是: tinker版本 1.9.14 gradle 插件版本 3.2.1 as版本 3.5.1
android.enableD8.desugaring = true android.useDexArchive = true 编译环境是java8,上面两个需要开启 multiDexKeepProguard file("tinkerMultidexKeep.pro") //keep specific classes using proguard syntax tinkerMultidexKeep.pro里面去除了几个类
//禁掉tinker的自动添加multiDexKeepProguard的task gradle.taskGraph.whenReady { tasks.each { task -> if (task.name.equals("tinkerProcessDebugMultidexKeep") || task.name.equals("tinkerProcessReleaseMultidexKeep")) { task.enabled = false } } }
@alen252 感谢,后续可以试一下
@alen252 tinkerMultidexKeep.pro能提供一下吗
@erge1223 @alen252 总算可以了,留下踩过坑的记录。 开发环境背景
tinker版本 1.9.14.5 gradle 插件版本 3.2.1 as版本 3.5.1
出现问题
问题1. android所有版本下,项目使用了java8特性,D8处理失败 问题2. 5.0以下版本默认使用官方 MultiDex 处理,出现 “Too mang classes...” 编译失败
解决问题
解决问题1:关闭D8脱糖,关闭增量处理dex 解决问题2:自主删除 maindexlist文件下的classes
具体解决实现: 主工程下 gradle.properties 添加解决问题1的配置
android.enableD8.desugaring = false android.useDexArchive = false
主模块下目录(与build.gradle 同级,可自主调整)新增文件 “main_dex_split_for_tinker.gradle” 用于修改maindexlist文件内容。 文件内容如下
project.afterEvaluate { //解决开启tinker时打包失败问题 Too many classes in --main-dex-list, main dex capacity exceeded。 exclude_class.txt中配置排除的类 //一定要验证5.0以下android启动时是否崩溃! if (android.defaultConfig.minSdkVersion.getApiLevel() >= 21) { return } if (project.hasProperty("tinkerPatch") == false) { return } def configuration = project.tinkerPatch if (!configuration.tinkerEnable) { return } android.applicationVariants.all { variant -> def variantName = variant.name.capitalize() def multidexTask = project.tasks.findByName("transformClassesWithMultidexlistFor${variantName}") if (multidexTask != null) { def splitTask = createSplitDexTask(variant); multidexTask.finalizedBy splitTask } } } def createSplitDexTask(variant) { def variantName = variant.name.capitalize() return task("replace${variantName}MainDexClassList").doLast { //从主dex移除的列表 def excludeClassList = [] File excludeClassFile = new File("${project.projectDir}/exclude_class.txt") if (excludeClassFile.exists()) { excludeClassFile.eachLine { line -> if (!line.trim().isEmpty() && line.startsWith("#") == false) { excludeClassList.add(line.trim()) } } excludeClassList.unique() } def mainDexList = [] File mainDexFile = new File("${project.buildDir}/intermediates/legacy_multidex_main_dex_list/${variant.dirName}/transformClassesWithMultidexlistFor${variantName}/maindexlist.txt") println "${project.buildDir}/intermediates/legacy_multidex_main_dex_list/${variant.dirName}/transformClassesWithMultidexlistFor${variantName}/maindexlist.txt exist : ${mainDexFile.exists()}" if (mainDexFile.exists()) { mainDexFile.eachLine { line -> if (!line.isEmpty()) { mainDexList.add(line.trim()) } } mainDexList.unique() if (!excludeClassList.isEmpty()) { def newMainDexList = mainDexList.findResults { mainDexItem -> def isKeepMainDexItem = true for (excludeClassItem in excludeClassList) { if (mainDexItem.contains(excludeClassItem)) { isKeepMainDexItem = false break } } if (isKeepMainDexItem) mainDexItem else null } if (newMainDexList.size() < mainDexList.size()) { mainDexFile.delete() mainDexFile.createNewFile() mainDexFile.withWriterAppend { writer -> newMainDexList.each { writer << it << '\n' writer.flush() } } } } } } }
在同级目录新增文件 “exclude_class.txt” 用于指明哪些class需要剔除。(可自定删减,我只写我需要删除的)
#类路径包含如下的,都会建议打包工具不要打到主dex中,但可能还会被打到主dex中。由于所有的业务代码都会在multidex.install后执行,理论上所有的业务代码都可以不在主dex中 com/facebook/fresco com/facebook/drawee com/facebook/imageformat com/facebook/imagepipeline #暂时只剔除Facebook下代码 com/alibaba com/taobao com/eclipsesource/v8 net/sourceforge/pinyin4j/ com/amitshekhar/ net/sqlcipher/ android/arch/persistence/room/ com/tencent/qqlive/ com/alibaba/ okhttp3/ com/github/mikephil/charting/ com/squareup/haha/ com/github/tony19/ org/jetbrains/anko/ kotlin/ com/squareup/ com/airbnb/ android/support/v com/facebook/fresco/ com/facebook/stetho/ com/google/android/flexbox/ com/sixgod/pluginsdk/
最后在主目录的build.gradle apply下这个上面的脚本就行了。
apply from: 'main_dex_split_for_tinker.gradle'
经过测试,在5.0以上及5.0以下都正常运行了。
@YummyLau 任务名和产物路径貌似有所变动。
我的环境是:
androidx.multidex:multidex
: 2.0.1MultiDex Task 为:
transformClassesWithDexBuilderForDebug
transformClassesAndDexWithShrinkResForRelease
产物路径为:
app/build/intermediates/legacy_multidex_main_dex_list/debug/maindexlist.txt
so, is this bug fix?
@alen252
下面这段 加 哪里 ? // //禁掉tinker的自动添加multiDexKeepProguard的任务 gradle.taskGraph.whenReady {task.each { task-> if(task.name.equals(“ tinkerProcessDebugMultidexKeep”)|| task.name.equals(“ tinkerProcessReleaseMultidexKeep”)) { task.enabled = false } } }
异常类型:app编译异常
手机型号:如:Nexus 5(如是编译异常,则可以不填)
手机系统版本:如:Android 5.0 (如是编译异常,则可以不填)
tinker版本:1.9.14.4
gradle版本:5.6
是否使用热更新SDK: 使用了TinkerPatch SDK
系统:如:Windows
'com.android.tools.build:gradle:3.2.1'
堆栈/日志: AGPBI: {"kind":"error","text":"Cannot fit requested classes in the main-dex file (# methods: 76780 \u003e 65536 ; # fields: 75405 \u003e 65536)","sources":[{}],"tool":"D8"}