文章目录
一、问题
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