No se puede ejecutar dex: ID de método no en [0, 0xffff]: 65536

344

He visto varias versiones de los dex erros antes, pero esta es nueva. limpiar / reiniciar, etc. no ayudará. Los proyectos de la biblioteca parecen intactos y la dependencia parece estar vinculada correctamente.

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

o

Cannot merge new index 65950 into a non-jumbo instruction

o

java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

tl; dr : ¡La solución oficial de Google finalmente está aquí!

http://developer.android.com/tools/building/multidex.html

Solo un pequeño consejo, es probable que tengas que hacer esto para evitar la falta de memoria al hacer la desintoxicación.

dexOptions {
        javaMaxHeapSize "4g"
}

También hay un modo jumbo que puede solucionar esto de una manera menos confiable:

dexOptions {
        jumboMode true
}

Actualización: si su aplicación es gorda y tiene demasiados métodos dentro de su aplicación principal, es posible que deba reorganizar su aplicación según

http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html

Edison
fuente
1
¿Utiliza una API que no está disponible en su dispositivo actual?
rekire
Está allí, porque otro proyecto construye bien dirigido a la misma versión de API.
Edison
Entonces, ¿usas algún punto API que no está disponible? ¿Comprueba con una línea como if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)esa que no llama a esta función si no está disponible?
rekire
Sí. El proyecto construido bien antes. Además, eso debería ser un error de tiempo de ejecución, incluso si me perdí la línea.
Edison
Es probable que una de las dependencias esté en mal estado. (haciendo una mezcla de maven + project lib ahora mismo)
Edison

Respuestas:

379

Actualización 3 (11/3/2014)
Google finalmente lanzó la descripción oficial .


Actualización 2 (31/10/2014)
El complemento de Gradle v0.14.0 para Android agrega soporte para multi-dex. Para habilitar, solo tiene que declararlo en build.gradle :

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Si su aplicación es compatible con Android anterior a 5.0 (es decir, si minSdkVersiontiene 20 o menos), también debe parchear dinámicamente la aplicación ClassLoader , para que pueda cargar clases desde dexes secundarios. Afortunadamente, hay una biblioteca que hace eso por ti. Agréguelo a las dependencias de su aplicación:

dependencies {
  ...
  compile 'com.android.support:multidex:1.0.0'
} 

Debe llamar al código de parche de ClassLoader lo antes posible. MultiDexApplicationLa documentación de la clase sugiere tres formas de hacerlo (elija una de ellas , la que sea más conveniente para usted):

1 - Declara la MultiDexApplicationclase como la aplicación en tu 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 - Haga que su Applicationclase extienda la clase MultiDexApplication :

public class MyApplication extends MultiDexApplication { .. }

3 - Llama MultiDex#installdesde tu Application#attachBaseContextmétodo:

public class MyApplication {
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
        ....
    }
    ....
}

Actualización 1 (17/10/2014):
Como se anticipó, el soporte multidex se incluye en la revisión 21 de la Biblioteca de soporte de Android. Puede encontrar android-support-multidex.jar en la carpeta / sdk / extras / android / support / multidex / library / libs.


El soporte multi-dex resuelve este problema. dx 1.8 ya permite generar varios archivos dex.
Android L admitirá multi-dex de forma nativa, y la próxima revisión de la biblioteca de soporte cubrirá versiones anteriores a API 4.

Fue declarado en este episodio de podcast de Android Developers Backstage por Anwar Ghuloum. He publicado una transcripción (y una explicación general de multi-dex) de la parte relevante.

Alex Lipov
fuente
2
¡La publicación de blog es un ahorro! : D
nadavfima
39
¿Algo para los usuarios de eclipse?
Muhammad Babar
52
@MuhammadBabar Hay un estudio de Android para usuarios de Eclipse.
VipulKumar
2
@MohammedAli Claro, evite usarlo si puede. Pero, ¿qué debe hacer si realmente tiene demasiados métodos en su aplicación y ya probó todos los trucos como el que mencionó? Con respecto al tiempo de compilación, hay una solución para esto, al menos para las compilaciones de desarrollo: vea mi respuesta aquí: stackoverflow.com/a/30799491/1233652
Alex Lipov
2
En Qt para Android, tenía problemas en el tiempo de ejecución de mi aplicación al integrar los SDK de Facebook + Twitter, incluso después de habilitar el soporte multidex (este error en particular me dio pesadillas java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]). Resultó que mi error fue que no estaba aplicando los pasos adicionales para el soporte de Android antes de 5.0. Dicho esto, la opción # 3 lo resolvió, y no tuve más ClassNotFoundExceptionproblemas. Gracias, @Alex Lipov!
robar
78

Como ya se dijo, tiene demasiados métodos (más de 65k) en su proyecto y libs.

Prevenga el problema: reduzca la cantidad de métodos con Play Services 6.5+ y support-v4 24.2+

Dado que a menudo los servicios de Google Play son uno de los principales sospechosos en los métodos de "desperdicio" con sus más de 20k métodos . Servicios de Google Play versión 6.5 o posterior, es posible que incluya servicios de Google Play en su aplicación utilizando varias bibliotecas de clientes más pequeñas. Por ejemplo, si solo necesita GCM y mapas, puede elegir usar solo estas dependencias:

dependencies {
    compile 'com.google.android.gms:play-services-base:6.5.+'
    compile 'com.google.android.gms:play-services-maps:6.5.+'
}

La lista completa de sub bibliotecas y sus responsabilidades se puede encontrar en el documento oficial de Google .

Actualización : desde Support Library v4 v24.2.0 se dividió en los siguientes módulos:

support-compat, support-core-utils, support-core-ui, support-media-compatYsupport-fragment

dependencies {
    compile 'com.android.support:support-fragment:24.2.+'
}

Sin embargo, tenga en cuenta que si lo usa support-fragment, tendrá dependencias de todos los demás módulos (es decir, si lo usa, android.support.v4.app.Fragmentno hay beneficio)

Consulte aquí las notas de la versión oficial de support-v4 lib


Habilitar MultiDexing

Desde Lollipop (también conocido como herramientas de construcción 21+) es muy fácil de manejar. El enfoque es solucionar los métodos de 65k por problema de archivo dex para crear múltiples archivos dex para su aplicación. Agregue lo siguiente a su archivo de compilación de gradle ( esto está tomado del documento oficial de google en aplicaciones con más de 65k métodos ):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

El segundo paso es preparar su clase de Aplicación o, si no extiende la Aplicación, use el MultiDexApplicationen su Manifiesto de Android:

Agregue esto a su Application.java

@Override
  protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
  }

o use la aplicación provista desde la biblioteca mutlidex

<?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>

Prevenir OutOfMemory con MultiDex

Como consejo adicional, si se encuentra con OutOfMemoryexcepciones durante la fase de construcción, puede ampliar el montón con

android {
    ...
    dexOptions {
        javaMaxHeapSize "4g"
    }
}

que establecería el montón a 4 gigabytes.

Consulte esta pregunta para obtener más detalles sobre el problema de la memoria de almacenamiento dinámico de dex.


Analiza la fuente del problema

Para analizar la fuente de los métodos, el complemento de Gradle https://github.com/KeepSafe/dexcount-gradle-plugin puede ayudar en combinación con el árbol de dependencias proporcionado por Gradle con, p. Ej.

.\gradlew app:dependencies

Consulte esta respuesta y pregunta para obtener más información sobre el recuento de métodos en Android

Patrick Favre
fuente
He usado la solución Play Services 6.5+ y funcionó perfectamente. Increíble punta útil. ¡Muchas gracias!
Hoang Nguyen Huu
Votaría más si pudiera, eliminando todas las demás cosas de Play Services que no estábamos usando solucionó este problema, sin tener que recurrir a multi-dex, que tiene implicaciones negativas de rendimiento al compilar.
Sean Barbeau el
1
Que tanto con lágrimas en mis ojos. Me salvaste
insomne
Usé la biblioteca del cliente para GCM, porque estoy usando solo el servicio gcm del servicio de reproducción, ahora solucionó mi problema con esto. ¡Gracias! para ahorrar mi tiempo
Ankit
57

Tu proyecto es demasiado grande. Tienes demasiados métodos. Solo puede haber 65536 métodos por aplicación. ver aquí https://code.google.com/p/android/issues/detail?id=7147#c6

blobbie
fuente
Veo. Tengo muchas dependencias para este proyecto. Sin embargo, funciona bien antes de mudarme para usar maven, tal vez maven agregó dependencias innecesarias. Verificará dos veces.
Edison
55
Para ser más específicos, solo puede haber 65.536 métodos por archivo ejecutable Dalvik (dex). Y una aplicación (APK) puede tener más de un archivo dex con elementos como la carga personalizada.
Dennis Sheil
77
¡Es un error realmente vergonzoso para Android! De todos modos, en mi caso, eliminé a Jar que estaba en las librerías y no estaba en uso, y la aplicación se compiló
David
Hora de limpiar mi proyecto: /
señuelo
1
Una solución rápida sería usar Proguard también con las compilaciones de depuración
aleb
12

El siguiente código ayuda, si usa Gradle. Le permite eliminar fácilmente los servicios innecesarios de Google (suponiendo que los esté usando) para volver a estar por debajo del umbral de 65k. Todo el crédito a esta publicación: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Editar 2014-10-22 : Ha habido mucha discusión interesante sobre la esencia mencionada anteriormente. TLDR? mira este: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Pegue este código en la parte inferior de su archivo build.gradle y ajuste la lista de servicios de google que no necesita:

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
    }
}
mcm
fuente
¡Quiéralo! Definitivamente es necesario ya que compañías como Google siguen inflando los paquetes.
Edison
1
Agradable, este trabajo fue perfecto. ¡Sin problemas ni preocupaciones!
slott
Nota: esto borró los servicios de Google Play en mi Android SDK en Android Studio. Una mala idea ya que no es fácil volver a los frascos originales. El autor debe modificar el script para cambiar los archivos jar en el directorio de compilación.
Inder
@inder: no tuve ese problema. Sin embargo, tuve que hacer una cleancada vez que hice el mono con las exclusiones (usamos análisis).
JohnnyLambada
¿Cómo excluir esto de las versiones de lanzamiento?
user1324936
6

He compartido un proyecto de muestra que resuelve este problema usando el script de compilación custom_rules.xml y algunas líneas de código.

Lo utilicé en mi propio proyecto y funciona sin problemas en dispositivos 1M + (desde android-8 hasta el último android-19). Espero eso ayude.

https://github.com/mmin18/Dex65536

mmin
fuente
1
Gracias por los guiones. deberías tener cuidado con ART. El dispositivo puede convertir solo su dex predeterminado y no los secundarios. Se deben preferir las soluciones de protección.
Edison
2
Cuando importo los proyectos en Eclipse y lo ejecuto, se produce un error. "No se puede ejecutar dex: ID de método no en [0, 0xffff]: 65536". ¿Puede explicar el uso del proyecto
Karacago
6

Enfrenté el mismo problema y lo resolví editando mi archivo build.gradle en la sección de dependencias, eliminando:

compile 'com.google.android.gms:play-services:7.8.0'

Y reemplazándolo con:

compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0' 
Luis Miguel Ballestas
fuente
¡Perfecto! Solo uso la API de Google Drive y esto funciona.
vedavis
5

Intente agregar el siguiente código en build.gradle, funcionó para mí:

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}
Sunita
fuente
2

La solución perfecta para esto sería trabajar con Proguard. como aleb mencionó en el comentario. Disminuirá el tamaño del archivo dex a la mitad.

shimi_tap
fuente
1
De acuerdo, con un jar de servicios de Google Play cada vez más grande especialmente * (18k métodos por sí mismo)
Edison
2

Puede analizar el problema (referencias de archivos dex) con Android Studio:

Compilación -> Analizar APK ..

En el panel de resultados, haga clic en el archivo classes.dex

Y verás:

ingrese la descripción de la imagen aquí

alexshr
fuente
0

solución 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/**'
            }
        }
    }
  }
}
Oleg Khalidov
fuente
0

Elimine algún archivo jar de la carpeta Libs y cópielo en otra carpeta, y vaya a _Project Properties> Seleccione Java Build Path, Seleccione Libraries, Seleccione Add External Jar, Seleccione el Jar eliminado a su proyecto, haga clic en guardar, esto se agregará en Referenciado Biblioteca en lugar de la carpeta Libs. Ahora limpia y ejecuta tu proyecto. No necesita agregar ningún código para MultDex. Simplemente funcionó para mí.

Lakshmanan
fuente
0

Estaba enfrentando el mismo problema hoy, lo que funcionó es abajo

Para ANDROID STUDIO ... Habilite la ejecución instantánea

En Archivo-> Preferencias-> Compilación, ejecución, implementación-> Ejecución instantánea-> Marque Habilitar ejecución instantánea para intercambio en caliente ...

Espero eso ayude

Abdul Waheed
fuente
1
Esto funcionó para mí: simplemente deshabilité Activar ejecución, hice clic en Aplicar, lo volví a habilitar y funcionó nuevamente.
MrBigglesworth