我以前见过不同版本的dex错误,但这一个是新的。清洁/重新启动等不会有帮助。库项目似乎完好无损,依赖项似乎正确链接。
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
or
Cannot merge new index 65950 into a non-jumbo instruction
or
java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
tl;dr:谷歌的官方解决方案终于来了!
http://developer.android.com/tools/building/multidex.html
只有一个小提示,您可能需要这样做,以防止在进行索引时内存不足。
dexOptions {
javaMaxHeapSize "4g"
}
还有一个超大模式可以以一种不太可靠的方式解决这个问题:
dexOptions {
jumboMode true
}
更新:如果你的应用程序很胖,你有太多的方法在你的主应用程序,你可能需要重新组织你的应用程序
http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html
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/**'
}
}
}
}
}
如果你使用Gradle,下面的代码会有所帮助。允许您轻松删除不需要的谷歌服务(假设您正在使用它们),以恢复到低于65k阈值。所有的功劳都来自这个帖子:https://gist.github.com/dmarcato/d7c91b94214acd936e42
关于上面提到的要点有很多有趣的讨论。TLDR吗?看看这个:https://gist.github.com/Takhion/10a37046b9e6d259bb31
将此代码粘贴到构建的底部。Gradle文件,调整你不需要的谷歌服务列表:
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
}
}
更新三(11/3/2014)
谷歌终于发布了官方描述。
更新2 (10/31/2014)
Gradle插件v0.14.0 for Android增加了对multi-dex的支持。要启用,你只需要在build.gradle中声明它:
android {
defaultConfig {
...
multiDexEnabled true
}
}
如果你的应用程序支持5.0之前的Android(也就是说,如果你的minSdkVersion是20或更低),你还必须动态地修补应用程序的ClassLoader,这样它将能够从辅助索引加载类。幸运的是,有一个库可以帮你做到这一点。将它添加到应用程序的依赖项中:
dependencies {
...
compile 'com.android.support:multidex:1.0.0'
}
您需要尽快调用ClassLoader补丁代码。MultiDexApplication类的文档建议了三种方法(从中选择一种最方便的方法):
1 -在AndroidManifest.xml中声明MultiDexApplication类:
<?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类扩展MultiDexApplication类:
public class MyApplication extends MultiDexApplication { .. }
3 -从你的application# attachBaseContext方法调用MultiDex#install:
public class MyApplication {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
....
}
....
}
更新1 (10/17/2014):
正如预期的那样,在Android支持库的第21版中提供了multidex支持。你可以在/sdk/extras/android/support/multidex/library/libs文件夹中找到android-support-multidex.jar。
多索引支持解决了这个问题。Dx 1.8已经允许生成几个dex文件。
Android L将原生支持多索引,支持库的下一个版本将覆盖API 4的旧版本。
这是Anwar Ghuloum在Android开发者后台播客中提到的。我已经发布了相关部分的文字记录(和一般的多索引解释)。
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/**'
}
}
}
}
}