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

82 篇文章 12 订阅
15 篇文章 3 订阅

一、问题

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
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林新发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值