之前我见过各种版本的dex erros,但这个版本是新的。清理/重启等无济于事。图书馆项目似乎完好无损,依赖似乎正确联系在一起。
Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
或
Cannot merge new index 65950 into a non-jumbo instruction
或
java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
tl;博士:Google的官方解决方案终于来了!
http://developer.android.com/tools/building/multidex.html
只有一个小提示,您可能需要这样做以防止在执行dex-ing时内存不足。
dexOptions {
javaMaxHeapSize "4g"
}
还有一种巨型模式可以用不太可靠的方式解决这个问题:
dexOptions {
jumboMode true
}
更新:如果你的应用很胖而你的主应用程序中有太多方法,你可能需要按照
重新整理你的应用程序http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html
答案 0 :(得分:370)
更新3(11/3/2014)
谷歌终于发布了official description。
更新2(2014年10月31日)
适用于Android-{3}的Gradle插件v0.14.0 for multi-dex。要启用,您只需在 build.gradle 中声明它:
android {
defaultConfig {
...
multiDexEnabled true
}
}
如果您的应用程序支持5.0之前的Android(即,如果您的minSdkVersion
为20或更低),您还必须动态修补应用程序ClassLoader ,这样它就能够从辅助dexes加载类。幸运的是,有一个adds support可以帮助你做到这一点。将其添加到您应用的依赖项中:
dependencies {
...
compile 'com.android.support:multidex:1.0.0'
}
您需要尽快调用ClassLoader修补程序代码。 MultiDexApplication
班级library提出了三种方法(选择其中一个,一个对您来说最方便的方式):
1 - 将MultiDexApplication
类声明为 AndroidManifest.xml 中的应用程序:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.multidex.myapplication">
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
</manifest>
2 - 让Application
班级延长documentation班级:
public class MyApplication extends MultiDexApplication { .. }
3 - 从MultiDex#install
方法致电Application#attachBaseContext
:
public class MyApplication {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
....
}
....
}
更新1(2014年10月17日):
正如预期的那样,MultiDexApplication在Android支持库的修订版21中提供。你可以在/ sdk / extras / android / support / multidex / library / libs文件夹中找到android-support-multidex.jar。
Multi-dex支持解决了这个问题。 dx 1.8已经允许生成几个dex文件 Android L本身将支持multi-dex,支持库的下一版本将涵盖旧版本返回API 4.
Anwar Ghuloum在multidex support Android开发者Backstage播客节目中说明了这一点。我是相关部分的this(以及一般的多重解释)。
答案 1 :(得分:77)
如前所述,您的项目和库中有太多方法(超过65k)。
由于Google Play服务通常是&#34;浪费&#34;的主要嫌疑人之一。方法及其20k+ methods。 Google Play服务版本6.5或更高版本,您可以包含Google Play services in your application using a number of smaller client libraries.例如,如果您只需要GCM和地图,则可以选择仅使用这些依赖项:
dependencies {
compile 'com.google.android.gms:play-services-base:6.5.+'
compile 'com.google.android.gms:play-services-maps:6.5.+'
}
The full list of sub libraries and it's responsibilities can be found in the official google doc
更新:自Support Library v4 v24.2.0起,它被拆分为以下模块:
support-compat
,support-core-utils
,support-core-ui
,support-media-compat
和support-fragment
dependencies {
compile 'com.android.support:support-fragment:24.2.+'
}
请注意,如果您使用support-fragment
,它将依赖于所有其他模块(即,如果您使用android.support.v4.app.Fragment
则没有任何好处)
See here the official release notes for support-v4 lib
自从Lollipop(又名构建工具21+)以来,它非常容易处理。方法是解决每个dex文件问题的65k方法,为您的应用程序创建多个dex文件。将以下内容添加到您的gradle构建文件(this is taken from the official google doc on applications with more than 65k methods):
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
...
// Enabling multidex support.
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
第二步是准备您的Application类,或者如果您不扩展Application,请使用Android Manifest中的MultiDexApplication
:
将其添加到Application.java
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
或使用mutlidex lib提供的应用程序
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.myapplication">
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
</manifest>
作为进一步的提示,如果在构建阶段遇到OutOfMemory
异常,可以使用
android {
...
dexOptions {
javaMaxHeapSize "4g"
}
}
将堆设置为4千兆字节。
See this question for more detail on the dex heap memory issue.
要分析gradle插件https://github.com/KeepSafe/dexcount-gradle-plugin可以帮助结合Gradle提供的依赖树的方法来源,例如
.\gradlew app:dependencies
See this answer and question for more information on method count in android
答案 2 :(得分:57)
您的项目太大了。你有太多的方法。每个应用程序只能有65536个方法。见https://code.google.com/p/android/issues/detail?id=7147#c6
答案 3 :(得分:12)
如果您使用Gradle,以下代码会有所帮助。允许您轻松删除不需要的Google服务(假设您正在使用它们)以恢复低于65k的阈值。这篇文章的所有功劳:https://gist.github.com/dmarcato/d7c91b94214acd936e42
编辑2014-10-22 :关于上面引用的要点,已经有很多有趣的讨论。 TLDR?看看这个:https://gist.github.com/Takhion/10a37046b9e6d259bb31
将此代码粘贴到build.gradle文件的底部,并调整您不需要的Google服务列表:
def toCamelCase(String string) {
String result = ""
string.findAll("[^\\W]+") { String word ->
result += word.capitalize()
}
return result
}
afterEvaluate { project ->
Configuration runtimeConfiguration = project.configurations.getByName('compile')
ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
// Forces resolve of configuration
ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion
String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir
Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
inputs.files new File(playServiceRootFolder, "classes.jar")
outputs.dir playServiceRootFolder
description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'
doLast {
copy {
from(file(new File(playServiceRootFolder, "classes.jar")))
into(file(playServiceRootFolder))
rename { fileName ->
fileName = "classes_orig.jar"
}
}
tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
destinationDir = playServiceRootFolder
archiveName = "classes.jar"
from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
exclude "com/google/ads/**"
exclude "com/google/android/gms/analytics/**"
exclude "com/google/android/gms/games/**"
exclude "com/google/android/gms/plus/**"
exclude "com/google/android/gms/drive/**"
exclude "com/google/android/gms/ads/**"
}
}.execute()
delete file(new File(playServiceRootFolder, "classes_orig.jar"))
}
}
project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
task.dependsOn stripPlayServices
}
}
答案 4 :(得分:6)
我已经共享了一个示例项目,该项目使用custom_rules.xml构建脚本和几行代码解决了这个问题。
我在我自己的项目中使用它,它在1M +设备上运行完美(从android-8到最新的android-19)。希望它有所帮助。
答案 5 :(得分:6)
面对同样的问题并通过在依赖项部分编辑我的build.gradle文件来解决它,删除:
compile 'com.google.android.gms:play-services:7.8.0'
将其替换为:
compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0'
答案 6 :(得分:5)
尝试在build.gradle中添加以下代码,它对我有用 -
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
multiDexEnabled true
}
答案 7 :(得分:2)
完美的解决方案是与Proguard合作。作为评论中提到的aleb。 它会将dex文件的大小减半。
答案 8 :(得分:2)
答案 9 :(得分:0)
gradle + proguard解决方案:
afterEvaluate {
tasks.each {
if (it.name.startsWith('proguard')) {
it.getInJarFilters().each { filter ->
if (filter && filter['filter']) {
filter['filter'] = filter['filter'] +
',!.readme' +
',!META-INF/LICENSE' +
',!META-INF/LICENSE.txt' +
',!META-INF/NOTICE' +
',!META-INF/NOTICE.txt' +
',!com/google/android/gms/ads/**' +
',!com/google/android/gms/cast/**' +
',!com/google/android/gms/games/**' +
',!com/google/android/gms/drive/**' +
',!com/google/android/gms/wallet/**' +
',!com/google/android/gms/wearable/**' +
',!com/google/android/gms/plus/**' +
',!com/google/android/gms/topmanager/**'
}
}
}
}
}
答案 10 :(得分:0)
从Libs文件夹中删除一些jar文件并复制到其他文件夹,然后转到_Project Properties&gt;选择Java Build Path,选择Libraries,选择Add External Jar,选择Removed jar到你的项目,点击save,这将被添加到Referenced Library而不是Libs文件夹下。现在清理并运行您的项目。您不需要为MultDex添加任何代码。它对我来说很有用。
答案 11 :(得分:0)
我今天面临着同样的问题,那就是下面的工作
对于ANDROID STUDIO ...启用即时运行
在文件 - &gt;偏好设置 - &gt;构建,执行,部署 - &gt;即时运行 - &gt;选中启用即时运行热插拔...
希望有所帮助