DexOverflowException: Cannot fit requested classes in the main-dex file

后端 未结 4 1628
春和景丽
春和景丽 2021-01-15 19:23

I have quite big multi module, multi flavor multidex project, but recently I got error when trying to do command line build (assemble{flavor}Release)

Message is:

相关标签:
4条回答
  • 2021-01-15 19:26

    What actually happening here is you are crossing the dex method count 65536 (which means you can use only 65536 methods in your apk) and you are just 12 methods ahead

    0 讨论(0)
  • 2021-01-15 19:38

    For release build you should try to fix that with proguard. For debug you can try to fix it by excluding some classes from main dex file.

    Add this to the application module

       import your.awesome.app.MainDexGenerator
    
       tasks.whenTaskAdded {
                if (it.name.contains('transformDexArchiveWithDexMergerFor') && it.name.contains('Debug')) {
                    it.doFirst(new MainDexGenerator([
                            'io/reactivex/annotations',
                            'kotlin',
                            'com/fasterxml'
                            //....and other you think could work 
                    ]))
                }
            }
    

    you can find classes that gradle wants to add to main dex in: intermeditates/legacy_multidex_main_dex_list/. For example you can exclude unused models or something else, basically everything you don't need when Application class is starting. Do not forget to check that you didn't broke anything on API 19 or lower

    set up buildSrc with build.gradle with groovy plugin.

    At buildSrc/main/groovy/your/awesome/app add your action:

    @CompileStatic
    class MainDexGenerator implements Action<Task> {
    
        private static final String MAIN_DEX_FILE = 'mainDexList.txt'
    
        // list we want to exclude frome MainDex
        private List<String> excludedList
        MainDexGenerator(List<String> excludedPackages) {
            excludedList = excludedPackages;
        }
    
        @Override
        void execute(Task task) {
            for (File inputFile : task.inputs.files.files) {
                if (inputFile.absolutePath.endsWith(MAIN_DEX_FILE)) {
                    List<String> result = Files.lines(inputFile.toPath())
                            .filter { isNotMatch(it) }
                            .collect(Collectors.toList())
                    Files.write(inputFile.toPath(), result, WRITE, TRUNCATE_EXISTING)
                    break
                }
            }
        }
    
        private boolean isNotMatch(String line) {
            for (String item : excludedList) {
                if (line.contains(item)) {
                    return false
                }
            }
            return true
        }
    }
    

    Too see the resulting method count you can use apkAnalyzer tool. Look for first dex.

    Also you can try to refactor your code and extract some responsibilities from application class.

    You can also try to increase minApi to 21.

    This answer has some more details on the problem Too many classes in --main-dex-list, main dex capacity exceeded

    0 讨论(0)
  • 2021-01-15 19:49

    Disabling keeping runtime annoted classes may help. Just put it in android{} section of every module gradle file

    dexOptions {
            preDexLibraries = false
            keepRuntimeAnnotatedClasses false
        }
    

    Usually this happens when in project heavely used dagger2

    0 讨论(0)
  • 2021-01-15 19:50

    I tried Alexander Bratusenko answer, didn't help but its a nice clue. What actually helped - I downgraded gradle plugin to

    classpath 'com.android.tools.build:gradle:3.1.4'
    
    0 讨论(0)
提交回复
热议问题