Unity打包apk报错: Cannot fit requested classes in a single dex file (# methods: 73376 > 65536)的解决办法

一、问题

Unity打包apk时报了如下的错

D8: Cannot fit requested classes in a single dex file (# methods: 73376 > 65536)
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
The number of method references in a .dex file cannot exceed 64K
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html

在这里插入图片描述

二、原因

Android 5.0之前的版本(API level < 21)使用Dalvik runtime来执行代码认限制每个APK只能使用一个classes.dex文件,而DEX规范又将单个DEX文件内引用的方法总数限制为65536个,所以如果游戏中使用了较多的第三方SDK,很容易就会超过这个限制。

三、测试,生成超过65535个函数

如果你工程中没有这么多java函数,可以自己写个python脚本生成超过65535函数,例:

import random
import os

letters = 'ABCDEFGHIJKLMnopQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'

func_tamplate='''
    public void FUNC_NAME()
    {
        Log.d("LOG_TEST","FUNC_NAME");
    }

'''

def rand_name():
    letter_cnt = random.randint(8,20)
    func_name = ''
    for letter_cnt in range(letter_cnt):
        func_name += random.choice(letters)
    return func_name

def gen_func():
    return func_tamplate.replace('FUNC_NAME', rand_name())

def gen_java_class_file():
    java_file_txt='''
package com.linxinfa.javatest;
import android.util.Log;

public class CLASS_NAME 
{
    FUNC_TEXT
}
'''
    
    funcs = ''
    # 一个java文件含7000个方法
    for i in range(7000):
        funcs += gen_func()
    class_name = rand_name()
    java_file_txt = java_file_txt.replace('CLASS_NAME', class_name)
    java_file_txt = java_file_txt.replace('FUNC_TEXT', funcs)
    with open(class_name + '.java', 'w') as f:
        f.write(java_file_txt)

if '__main__' == __name__:
    # 生成10个java文件一个java文件含7000个方法,这样就超过65535个方法
    for i in range(10):
        gen_java_class_file() 

四、解决办法

办法1:在Player Settings中将支持的最低Android API级别设定为21及以上。Android API Level 21及更高版本支持APK文件中加载多个DEX文件,因此不会受64K的限制。

办法2:使用Custom Gradle配置文件并启用MultiDex支持(在PlayerSettings > Publish Settings > Build设置中勾选Custom Launcher Gradle Template,然后修改项目目录Assets/Plugins/Android/launcherTemplate.gradle启用MultiDex支持

办法3修改Unity Editor认的Gradle配置文件并启用MultiDex支持Unity安装目录/PlaybackEngines/Androidplayer/Tools/GradleTemplates/mainTemplate.gradle

本文介绍方法2的做法。

1、勾选Custom Gradle Template

PlayerSettings > Publish Settings > Build设置中勾选Custom Launcher Gradle Template

在这里插入图片描述

此时Assets/Plugins/Android/目录中会自动创建一个launcherTemplate.gradle文件

在这里插入图片描述

3、添加multiDexEnabled true

打开launcherTemplate.gradle,在defaultConfig配置块中,增加multiDexEnabled true

android {
        defaultConfig {
            ...
            multiDexEnabled true
            ...
        }
        ...
    }

4、添加multidex依赖

如果你的项目没有使用AndroidX

dependencies {
      implementation 'com.android.support:multidex:1.0.3'
}

如果项目使用了AndroidX,那么添加下面的支持库依赖项

dependencies {
        implementation 'androidx.multidex:multidex:2.0.1'
}

如下,是我的mainTemplate.gradle

// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN

apply plugin: 'com.android.application'

dependencies {
    implementation project(':unityLibrary')
	implementation 'com.android.support:multidex:1.0.3'
    }

android {
    compileSdkVersion **APIVERSION**
    buildToolsversion '**BUILDTOOLS**'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
		multiDexEnabled true
        minSdkVersion **MINSDKVERSION**
        targetSdkVersion **TARGETSDKVERSION**
        applicationId '**APPLICATIONID**'
        ndk {
            abiFilters **ABIFILTERS**
        }
        versionCode **VERSIONCODE**
        versionName '**VERSIONNAME**'
    }

    aaptOptions {
        noCompress = ['.unity3d', '.ress', '.resource', '.obb'**STREAMING_ASSETS**]
        ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
    }**SIGN**

    lintOptions {
        abortOnError false
    }

    buildTypes {
        debug {
            minifyEnabled **MINIFY_DEBUG**
            proguardFiles getDefaultProguardFile('proguard-android.txt')**SIGNCONfig**
            jniDebuggable true
        }
        release {
            minifyEnabled **MINIFY_RELEASE**
            proguardFiles getDefaultProguardFile('proguard-android.txt')**SIGNCONfig**
        }
    }**PACKAGING_OPTIONS****SPLITS**
**BUILT_APK_LOCATION**
    bundle {
        language {
            enableSplit = false
        }
        density {
            enableSplit = false
        }
        abi {
            enableSplit = true
        }
    }
}**SPLITS_VERSION_CODE****LAUNCHER_SOURCE_BUILD_SETUP**

5、修改AndroidManifest.xml

修改位于项目目录Asset/Plugins/Android/AndroidManifest.xml文件,给application添加MultiDexApplication

android:name="android.support.multidex.MultiDexApplication"

如下

在这里插入图片描述

6、Application类,继承MultiDexApplication

如果你没有自己实现Application类,则跳过此步。

public class MyApplication extends MultiDexApplication { ... }

五、打包测试

打包apk,解压后,可以看到有多个dex

在这里插入图片描述

相关文章

前言 本文记录unity3D开发环境的搭建 unity安装 unity有中文...
前言 有时候我们希望公告牌跟随镜头旋转永远平行面向屏幕,同...
前言 经过一段时间的学习与实际开发,unity3D也勉强算是强行...
前言 在unity中我们常用的获取鼠标点击的方法有: 1、在3D场...
前言 在之前的例子中,我们都没有用到unity的精髓,例如地形...
这篇文章将为大家详细讲解有关Unity3D中如何通过Animator动画...