Impossibile eseguire dex: ID metodo non in [0, 0xffff]: 65536


344

Ho già visto varie versioni dei dex erros, ma questa è nuova. pulire / riavviare ecc. non aiuta. I progetti di biblioteca sembrano intatti e la dipendenza sembra essere collegata correttamente.

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 soluzione ufficiale di Google è finalmente arrivata!

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

Solo un piccolo suggerimento, sarà probabilmente necessario farlo per evitare di perdere memoria quando si esegue la dexing.

dexOptions {
        javaMaxHeapSize "4g"
}

C'è anche una modalità jumbo che può risolverlo in un modo meno affidabile:

dexOptions {
        jumboMode true
}

Aggiornamento: se l'app è fat e hai troppi metodi all'interno dell'app principale, potrebbe essere necessario riorganizzare l'app secondo

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


1
Usi api che non è disponibile sul tuo dispositivo curioso?
riaccendere il

È lì, perché un altro progetto si adatta perfettamente alla stessa versione dell'API.
Edison,

Quindi usi ad un certo punto API che non è disponibile? Verifichi con una linea del genere if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)che non chiami questa funzione se non è disponibile?
rekire il

Si. Il progetto è stato realizzato ben prima. Inoltre, dovrebbe essere un errore di runtime anche se ho perso la linea.
Edison,

È probabilmente una delle dipendenze è incasinata. (facendo un mix di maven + project lib in questo momento)
Edison

Risposte:


379

Aggiornamento 3 (03/11/2014)
Google ha finalmente rilasciato la descrizione ufficiale .


Aggiornamento 2 (31/10/2014) Il
plug-in Gradle v0.14.0 per Android aggiunge il supporto per multi-dex. Per abilitare, devi solo dichiararlo in build.gradle :

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Se la tua applicazione supporta Android prima della 5.0 (ovvero se hai minSdkVersion20 o meno) devi anche patchare dinamicamente l' applicazione ClassLoader , quindi sarà in grado di caricare classi da dex secondari. Fortunatamente, c'è una biblioteca che lo fa per te. Aggiungilo alle dipendenze della tua app:

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

Devi chiamare il codice patch ClassLoader il prima possibile. MultiDexApplicationla documentazione della classe suggerisce tre modi per farlo (scegline uno , uno più conveniente per te):

1 - Dichiara la MultiDexApplicationclasse come applicazione nel tuo 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 - Chiedi alla tua Applicationclasse di estendere la classe MultiDexApplication :

public class MyApplication extends MultiDexApplication { .. }

3 - Chiama MultiDex#installdal tuo Application#attachBaseContextmetodo:

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

Aggiornamento 1 (17/10/2014):
Come anticipato, il supporto multidex viene fornito nella revisione 21 della Libreria di supporto Android. Puoi trovare la cartella android-support-multidex.jar nella cartella / sdk / extra / android / support / multidex / library / libs.


Il supporto multi-dex risolve questo problema. dx 1.8 consente già di generare diversi file dex.
Android L supporterà il multi-dex in modo nativo e la prossima revisione della libreria di supporto riguarderà le versioni precedenti di API 4.

È stato dichiarato in questo episodio podcast Android Developers Backstage di Anwar Ghuloum. Ho pubblicato una trascrizione (e una spiegazione multi-dex generale) della parte pertinente.


2
post sul blog è un risparmio! : D
nadavfima,

39
Qualcosa per gli utenti di eclissi?
Muhammad Babar,

52
@MuhammadBabar C'è uno studio Android per gli utenti Eclipse.
VipulKumar,

2
@MohammedAli Certo, evita di usarlo se puoi. Ma cosa dovresti fare se hai davvero troppi metodi nella tua app e hai già provato tutti i trucchi come quello che hai menzionato? Per quanto riguarda il tempo di compilazione - c'è una soluzione per questo, almeno per le build di sviluppo - vedi la mia risposta qui: stackoverflow.com/a/30799491/1233652
Alex Lipov

2
Su Qt per Android, avevo problemi di runtime per la mia app durante l'integrazione di SDK di Facebook + Twitter insieme, anche dopo aver abilitato il supporto multidex (questo errore in particolare mi ha dato incubi:) java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]. Si è scoperto che il mio errore era che non stavo applicando i passaggi aggiuntivi per il supporto Android prima della 5.0. Detto questo, l'opzione n. 3 l'ha risolto e non ho avuto più ClassNotFoundExceptionproblemi. Grazie @Alex Lipov!
ruba il

78

Come già detto, hai troppi metodi (più di 65k) nel tuo progetto e librerie.

Prevenire il problema: ridurre il numero di metodi con Play Services 6.5+ e support-v4 24.2+

Poiché spesso i servizi di Google Play sono uno dei principali sospettati di "sprecare" i metodi con i suoi metodi 20k + . Servizi Google Play versione 6.5 o successive, è possibile includere i servizi Google Play nella propria applicazione utilizzando un numero di librerie client più piccole. Ad esempio, se hai solo bisogno di GCM e mappe, puoi scegliere di usare solo queste dipendenze:

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

L'elenco completo delle librerie secondarie e le relative responsabilità sono disponibili nel documento ufficiale di Google .

Aggiornamento : dalla Support Library v4 v24.2.0 è stato suddiviso nei seguenti moduli:

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

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

Si noti tuttavia, se si utilizza support-fragment, avrà dipendenze da tutti gli altri moduli (cioè se si utilizza android.support.v4.app.Fragmentnon ci sono vantaggi)

Vedi qui le note di rilascio ufficiali per support-v4 lib


Abilita MultiDexing

Dal momento che Lollipop (aka build tools 21+) è molto facile da gestire. L'approccio consiste nel risolvere i problemi relativi ai metodi 65k per file dex per creare più file dex per l'app. Aggiungi quanto segue al tuo file build gradle ( questo è tratto dal documento ufficiale di google su applicazioni con più di 65k metodi ):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

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

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

Il secondo passo è preparare la tua classe di applicazione o se non estendi l'applicazione, usa MultiDexApplicationnel tuo manifest Android:

O aggiungi questo al tuo Application.java

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

o utilizzare l'applicazione fornita dalla libreria 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>

Prevenire OutOfMemory con MultiDex

Come ulteriore consiglio, se si verificano OutOfMemoryeccezioni durante la fase di costruzione, è possibile ingrandire l'heap con

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

che imposterebbe l'heap su 4 gigabyte.

Vedi questa domanda per maggiori dettagli sul problema della memoria dell'heap dex.


Analizza la fonte del problema

Per analizzare l'origine dei metodi il plug-in gradle https://github.com/KeepSafe/dexcount-gradle-plugin può aiutare in combinazione con l'albero delle dipendenze fornito da Gradle con ad es.

.\gradlew app:dependencies

Vedi questa risposta e questa domanda per ulteriori informazioni sul conteggio dei metodi in Android


Ho usato la soluzione Play Services 6.5+ e ha funzionato perfettamente. Incredibile consiglio utile. Grazie mille!
Hoang Nguyen Huu,

Voterei di più se potessi - eliminando tutte le altre cose di Play Services che non stavamo usando risolto questo problema, senza dover ricorrere a multi-dex, che ha implicazioni negative sulle prestazioni durante la costruzione.
Sean Barbeau,

1
Di te così tanto con le lacrime agli occhi. Mi hai salvato
insonnia il

Ho usato la libreria client per GCM, perché sto usando solo il servizio gcm dal servizio play, ora ha risolto il mio problema con questo. Grazie! per risparmiare tempo.
Ankit

57

Il tuo progetto è troppo grande. Hai troppi metodi. Ci possono essere solo 65536 metodi per applicazione. vedi qui https://code.google.com/p/android/issues/detail?id=7147#c6


Vedo. Ho molte dipendenze per questo progetto. Si costruisce bene prima che io mi muova per usare Maven, forse Maven ha aggiunto dipendenze non necessarie. Doppio controllo.
Edison,

5
Per essere più specifici, ci possono essere solo 65.536 metodi per file eseguibile (dex) di Dalvik. E un'applicazione (APK) può avere più di un file dex con elementi come il caricamento personalizzato.
Dennis Sheil,

7
È davvero un bug imbarazzante per Android! Ad ogni modo, in me caso ho rimosso Jar che era nelle librerie e non era in uso e l'app compilata
David

Tempo di ripulire il mio progetto: /
Esca

1
Una soluzione rapida sarebbe usare Proguard anche con le build di debug
aleb

12

Il seguente codice aiuta, se si utilizza Gradle. Ti consente di rimuovere facilmente i servizi Google non necessari (presumendo che li stai usando) per tornare sotto la soglia di 65k. Tutto il merito a questo post: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Modifica 22-10-2014 : C'è stata molta discussione interessante sull'essenza citata sopra. TLDR? guarda questo: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Incolla questo codice nella parte inferiore del file build.gradle e modifica l'elenco dei servizi Google che non ti servono:

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

Lo adoro! def necessaria poiché aziende come Google continuano a gonfiare i pacchetti.
Edison,

1
Bello - questo ha fatto il lavoro giusto. Nessuna seccatura e nessuna preoccupazione!
slott

Nota: questo cancellato google gioca i vasetti dei servizi nel mio Android SDK in Android Studio! Una cattiva idea poiché non è facile tornare ai vasetti originali. L'autore dovrebbe modificare lo script per cambiare i vasetti nella directory di compilazione.
inder

@inder: non ho avuto questo problema. Tuttavia, ho dovuto farlo cleanogni volta che mi sono scervellato con gli esclusi (usiamo l'analisi).
JohnnyLambada,

come escluderlo dalle build di rilascio?
user1324936

6

Ho condiviso un progetto di esempio che risolve questo problema utilizzando lo script di build custom_rules.xml e alcune righe di codice.

L'ho usato sul mio progetto e funziona perfettamente su dispositivi 1M + (da Android-8 all'ultimo Android-19). Spero che sia d'aiuto.

https://github.com/mmin18/Dex65536


1
Grazie per gli script. dovresti stare attento a ART. Il dispositivo può convertire solo il tuo dex predefinito e non quelli secondari. Le soluzioni Proguard dovrebbero essere preferite.
Edison,

2
Quando importare i progetti in Eclipse ed eseguirlo, viene visualizzato un errore. "Impossibile eseguire dex: ID metodo non in [0, 0xffff]: 65536". Puoi spiegare l'uso del progetto
Karacago,

6

Ha affrontato lo stesso problema e risolto modificando il mio file build.gradle nella sezione delle dipendenze, rimuovendo:

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

E sostituendolo con:

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

Perfetto! Uso solo l'API di Google Drive e funziona.
vedavis,

5

Prova ad aggiungere il codice seguente in build.gradle, ha funzionato per me -

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}

2

La soluzione perfetta per questo sarebbe lavorare con Proguard. come aleb menzionato nel commento. Ridurrà della metà la dimensione del file dex.


1
D'accordo, con un barattolo sempre più grande di servizi di Google Play in particolare * (18k metodi da solo)
Edison

2

Puoi analizzare il problema (riferimenti ai file dex) usando Android Studio:

Build -> Analizza APK ..

Nel pannello dei risultati fare clic sul file classes.dex

E vedrai:

inserisci qui la descrizione dell'immagine


0

soluzione 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/**'
            }
        }
    }
  }
}

0

Rimuovi alcuni file jar dalla cartella Libs e copia in un'altra cartella, quindi vai a _Project Properties> Seleziona Java Build Path, Seleziona Librerie, Seleziona Aggiungi Jar esterno, Seleziona il Jar rimosso al tuo progetto, Fai clic su Salva, questo verrà aggiunto in Riferimenti Libreria invece della cartella Libs. Ora pulisci ed esegui il tuo progetto. Non è necessario aggiungere alcun codice per MultDex. Ha semplicemente funzionato per me.


0

Stavo affrontando lo stesso problema oggi ciò che ha funzionato è sotto

Per ANDROID STUDIO ... Abilita Instant Run

In File-> Preferenze-> Build, Execution, Deployment-> Instant Run-> Check Enable Instant run for hot swap ...

Spero che sia d'aiuto


1
Questo ha funzionato per me: ho semplicemente disabilitato Abilita Esegui, ho fatto clic su Applica, l'ho riattivato e ha funzionato di nuovo.
MrBigglesworth,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.