web-dev-qa-db-fra.com

Android: mon application est trop volumineuse et donne le message "Impossible d'exécuter dex: l'ID de méthode n'est pas dans [0, 0xffff]: 65536"

J'essaie d'intégrer mon application à Box, Dropbox et Google Drive. Ces 3 services requièrent un certain nombre de pots tiers. De plus, mon application nécessite déjà quelques jars tiers. Désormais, lorsque j'essaie d'exécuter mon application à partir d'Eclipse, l'erreur suivante apparaît:

Impossible d'exécuter dex: l'ID de méthode n'est pas dans [0, 0xffff]: 65536 Conversion échec du format Dalvik: impossible d’exécuter dex: l’ID de la méthode n’est pas dans [0, 0xffff]: 65536

Il semble que cette erreur se produise car mon application a trop de méthodes. Je suis à peu près certain que la plupart de ces méthodes proviennent de fichiers tiers, il est donc irréaliste d'essayer de résoudre ce problème en simplifiant mon code. J'ai trouvé ces deux suggestions en ligne.

  1. ajoutez dex.force.jumbo=trueto project.properties (et utilisez adt version 21). Je l'ai fait mais j'ai toujours l'erreur.

  2. Utilisez plusieurs fichiers dex comme expliqué ici: http://Android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html . Cela semble être la seule option, mais je ne comprends pas comment cela s’applique dans mon cas. Le problème est que les services comme Drive ont trop de dépendances. Cette solution ne nécessite-t-elle pas que je modifie la source Drive pour utiliser l'inflexion en faisant référence à ses dépendances? (ce n'est clairement pas une option).

  3. Utilisez proguard pour réduire les codes/méthodes inutilisés. L'exportation de mon application avec proguard fonctionne et l'intégration du service de document fonctionne comme prévu sur un périphérique> 4.0. Cependant, des erreurs classnotfound sont générées lors des tests sur un périphérique 2.3. 

J'espère donc des conseils sur cette question. L'option 2 est-elle une solution pour mon cas? Existe-t-il une autre solution à envisager?

24
ab11

Vous pouvez également développer un ou plusieurs d'entre eux sous forme de plug-in pour votre application principale, sous la forme d'un fichier APK séparé à télécharger. Cet APK exposerait un composant que l'application principale utiliserait - étant donné que je ne connais pas la nature de votre intégration à ces services, je ne peux pas faire de recommandation plus précise à ce sujet. Vous utiliseriez votre propre <permission> personnalisé signature-level pour sécuriser les communications entre les deux applications. Et, en prime, si l’utilisation de la bibliothèque tierce ajoute des exigences pour des autorisations supplémentaires, vous n’auriez besoin que de ces autorisations dans le plug-in APK, en gardant votre APK principal plus petit.

14
CommonsWare

*** NOUVEAU **** Toutes les autres réponses sont maintenant obsolètes. Voici le nouveau correctif

Android 5.0 et supérieur

Le support multi-dex est inclus automatiquement. À partir de la documentation:

Android 5.0 et versions ultérieures utilisent un environnement d'exécution appelé ART, qui nativement prend en charge le chargement de plusieurs fichiers dex à partir de fichiers d'application APK. ART effectue une pré-compilation au moment de l'installation de l'application, qui recherche classes (.. N) .dex et les compile dans un seul fichier .oat pour exécution par l'appareil Android. Pour plus d'informations sur Android 5.0, voir Présentation de ART.

Sous Android 5.0

Ajoutez simplement l'outil de support multi-dex Android à votre nouvelle version:

Android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

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

dependencies {
  compile 'com.Android.support:multidex:1.0.0'
}
7
Jason

Dalvik VM peut avoir un maximum de 65 536 méthodes par fichier dex, car le jeu d'instructions bytecode n'a pas de moyen de faire référence à des numéros de méthodes nécessitant plus de 16 bits (comme indiqué par @danfuzz dans les commentaires).

Bien qu'il soit possible de résoudre ce problème en utilisant plusieurs fichiers dex, Facebook a trouvé un autre correctif qu'ils pourraient déployer dans leur application pour résoudre le problème.

6
Raghav Sood

Voir vm/LinearAlloc.c et vous pouvez trouver ce code: (5 Mo sous Android 2.3.3, 8 Mo après Android 4.0 en tant que mon enquête)

#define DEFAULT_MAX_LENGTH (5 * 1024 * 1024)

...

LinearAllocHdr * pHdr;

...

pHdr-> mapLength = DEFAULT_MAX_LENGTH;

Je suppose que le «correctif Facebook» est en train de modifier cette mémoire en utilisant un pointeur C natif . Problème IMHO LinearAlloc et le problème de cette méthode est différent.

5
Francesco Jo

J'ai fait face à ce problème récemment. Après avoir parcouru le Web pour une mise en œuvre plus détaillée, j'ai réalisé qu'il n'y avait pas grand chose d'autre que:

J'ai réalisé que le problème n'était pas nécessairement qu'il y avait trop de méthodes dans mon code, mais que la dex complète de mon code et d'autres bibliothèques posait problème. Donc, si je pouvais compiler mon code avec les bibliothèques mais ne pas les inclure dans le classes.dex, puis dex les bibliothèques séparément, puis les regrouper à l'exécution, cela devrait fonctionner. Le seul problème qui reste à résoudre est le chargeur de classe, mentionné par Facebook en passant.

Donc, avec un peu de réflexion et du code Groovy, je pense avoir mis au point un moyen relativement stable de conditionner les bibliothèques et le code de l'application dans des fichiers dex séparés.

https://Gist.github.com/nickcaballero/7045993

3
Nick Caballero

La plupart des problèmes liés au dépassement de la limite de la méthode 65k sont liés à l'utilisation des services mastodontiques Google Play dans vos applications. Récemment, vous pouvez obtenir plus de précision lorsque vous l’utilisez.

En suivant ce guide , vous ne pouvez utiliser que les parties de votre choix. Cela résoudra probablement le problème en évitant certains tours de magie noire ou en utilisant multiDex. Par exemple, si vous souhaitez uniquement Google Maps dans votre application (et que vous n’utilisez pas d’annonces, de portefeuilles, de Google Wear, d’analyses, etc.), utiliser toute la dépendance est une perte de temps/espace. Vous pouvez l'utiliser de cette façon:

compile com.google.Android.gms:play-services-base:6.5.87
compile com.google.Android.gms:play-services-maps:6.5.87

Vous pouvez lire la liste complète des "parties" dans ce lien

1
webo80

Vous devez activer le support Dex pour cela. Donc, vous devez faire ces étapes:

  1. Gradle plugin v0.14.0 pour Android ajoute le support de multi-dex. Pour l'activer, il suffit de le déclarer dans build.gradle:
Android {
   defaultConfig {
      ...
      multiDexEnabled = true
   }
}
  1. si App Support> 5.0 (c'est-à-dire, si votre minSdkVersion est inférieur ou égal à 20), vous devez également appliquer un correctif dynamique à l'application ClassLoader afin qu'il puisse charger des classes à partir dex secondaires. pour cela vous pouvez ajouter cette lib.
 dependencies {
      ...
      compile 'com.Android.support:multidex:1.0.0'
    }
  1. activer dans le code pour que vous ayez ces options. choisissez celui qui vous convient le mieux

A. Ajouter MultiDexApplication dans le manifeste manifeste 

<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.example.Android.multidex.App"> <application
Android:name="Android.support.multidex.MultiDexApplication">
</application>
</manifest>

B. Étendre l'application par MultiDexApplication

public class App extends MultiDexApplication { .. }

C. l'installer dans l'application en attachant le contexte de base.

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

}

Pour plus, cliquez sur ce lien MultiDex .

0
RATHI

Ici est un script que j'ai écrit pour compter le nombre de méthodes dans chaque jar (et au total) pour un dossier spécifique.

Une fois les méthodes comptées, vous pouvez vous concentrer sur la refactorisation et la suppression de bibliothèques volumineuses.

0
Tom Susel