引用超过65,000个方法造成的编译错误
由于字节码文件中的Dalvid执行限制,引用接近65,000个方法的应用在提交到应用商店时会遇到编译错误。
引用超过65,000个方法造成的构建错误
如果向亚马逊应用商店提交的应用引用了接近65,000个方法,在提交之后,您可能会通过电子邮件或在App Status(应用状态)屏幕中收到以下错误消息:
无法执行dex:方法ID不在[0, 0xffff]中: 65536
转换为Dalvik格式失败: 无法执行dex:方法ID不在 [0, 0xffff] 中: 65536
造成此错误的原因是,对于Dalvik可执行(dex)字节码文件,Android的引用方法数限制为65,535个。有关更多信息,请参阅Android文档中的为方法数超过64000的应用启用multidex。
从亚马逊包装器中添加的其他方法
亚马逊会使用代码包装亚马逊应用商店中的每个应用,以便向开发者提供各种报告、分析、DRM和应用更新。此包装器为亚马逊库增加了1627个额外的引用方法,并为每个活动增加了9个额外的方法。由于这些额外的引用方法,如果应用引用了接近65,000个方法,则可能会超过方法限制。
虽然此限制始终存在,但Android 5.0 Lollipop发布后,超过方法引用限制的情况变得司空见惯,因为该版本包含的新特性通常会增加应用可能引用的方法数。
为了避免此限制,请考虑对引用方法计数并减少应用中的引用方法数。
对引用方法计数
要对应用引用的方法进行计数以及确定应用的哪些部分引用了方法,可以使用GitHub提供的dex-method-counts工具:https://github.com/mihaip/dex-method-counts。
减少引用方法的数量
要减少引用方法的数量,请尽可能地删除额外的库和方法。或者,可以在配置中使用ProGuard和-dontoptimize –dontobfuscate
,这会在构建时从DEX文件中移除未使用的方法。
如果这些方法不适用于您的应用,请尝试MultiDex方法,这会将classes.dex
拆分为多个DEX文件。
可以将MultiDex库与Android Gradle插件配合使用。有关更多信息,请参阅为方法数超过64000的应用启用multidex。
使用MultiDex方法时请注意以下事项:
- 必须使用Gradle进行Android开发。
- 您会发现,如果不执行几个额外的步骤(下一部分列出),MultiDex无法删除足够多的方法。
可以使用上述dex-method-counts工具来检查生成的classes.dex
文件的方法计数。
使用MultiDex库
使用Android 5.0 Lollipop时,Android SDK 21.1.x版和Android支持库21.0.3中会显示一个支持库(称为android-support-multidex.jar
)。可在\android-sdk\extras\android\support\multidex\library\libs
中找到该支持库。该支持库包含两个新类:MultiDex
和MultiDexApplication
,并简化了MultiDex加载过程。
如果应用专门面向Android 5.0,则无需使用此库,因为Android 5.0提供对次DEX文件的内置支持。但在早期版本中,Android会在类加载器中添加APK归档中的额外.dex
文件。该库允许档案为应用主DEX文件的一部分,并管理对其他DEX文件的访问。因此,如果应用面向任何早于Android 5.0的版本,应使用此库。
要为Android 5.0之前的应用实施此解决方案,请执行以下操作:
- 确保已将Android构建工具更新到最新版本。至少需要21.1.x或更高版本。
- 将
android-support-multidex.jar
库添加到项目中。可在\android-sdk\extras\android\support\multidex\library\libs
中找到该库。 -
将
multiDexEnabled true
和Multidex dependency添加到build.gradle
文件的buildConfig
中,如以下示例所示。android { compileSdkVersion 21 buildToolsVersion "21.1.2" defaultConfig { ... minSdkVersion 14 targetSdkVersion 21 ... //启用MultiDex支持。 multiDexEnabled true } ... } dependencies { compile 'com.android.support:multidex:1.0.0' }
-
覆盖
android.app.Application
类,或者在AndroidManifest.xml
文件中声明MultiDexApplication
类,如以下代码中所示:<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:name="android.support.multidex.MultiDexApplication"> ... </application>
-
如果项目中有任何其他库,请确保对这些库禁用了预索引功能。遗憾的是,
--multi-dex
选项与已进行DEX预处理的库不兼容。要禁用DEX预处理功能,可以将以下代码添加到
app/build.gradle
文件中:android { // ... dexOptions { preDexLibraries = false } }
注意: 以前,要设置单个DEX文件的最大方法数,可以在dexOptions
下添加一个额外的属性,例如:additionalParameters = ["--set-max-idx-number=55000"]
。但是对于新的Android编译器D8和Android Studio 3.1.2,–set-max-idx-number
不再有效。因此,如果包含了该属性,在应用提交过程中会报错。 -
配置构建指令,以确保MultiDex应用针对亚马逊应用商店和提交流程进行了优化。可执行如下操作:
-
手动创建
main-dex-list
文件。在app/build.gradle文件中,添加以下内容:afterEvaluate { tasks.matching { it.name.startsWith('dex') }.each { dx -> if (dx.additionalParameters == null) { dx.additionalParameters = [] } dx.additionalParameters += '--multi-dex' dx.additionalParameters += "--main-dex-list=$projectDir/<filename>".toString() } }
此代码使用了两个参数:
--multi-dex
:在构建过程中启用拆分机制。--main-dex-list
:包含必须附加到主DEX文件中的类列表的文件。
为了确保MultiDex应用能够正确提交并发布到亚马逊应用商店中,请使用
--main-dex-list
参数将以下内容放在主.dex
文件中:- 自定义应用
- 活动
- 服务
- 接收方
- 提供方
- 工具
- 注释
-
如果使用的是Studio 0.9.0和Gradle 0.14.2,并让构建工具自动将
dx.additionalParameters
参数值限制为60,000
,则忽略multi-dex
和multi-dex-list
参数。这应该适用于大多数应用。但是,如果应用中有大量类,可能需要手动将最大数量设置为小于60,000的值,以便正确提交应用到亚马逊应用商店。
-
确保AndroidX库未混淆
如果使用AndroidX库进行多重索引,请在Proguard文件中添加如下信息以确保AndroidX库未混淆:
-keep class androidx/multidex.** { *; }
其他资源
有关生成main-dex-list
的帮助,请参阅以下内容:
- CreateManifestKeepList.groovy:Gradle自动生成
main-dex-list
所用的源代码。 - 用来自动生成该main-dex-list的工具。
Last updated: 2023年10月2日