Android: mon application est trop grande et donne "impossible d'exécuter dex: method ID not in [0, 0xffff]: 65536"?

j'essaie d'intégrer mon application avec Box, Dropbox, et Google Drive. Ces trois services nécessitent un certain nombre de pots de tierce partie. En outre, ma demande nécessite déjà quelques pots tiers. Maintenant, quand j'essaie de lancer mon application à partir d'eclipse, j'obtiens l'erreur suivante:

impossible d'exécuter dex: ID de méthode pas dans [0, 0xffff]: 65536 Conversion le format Dalvik a échoué: impossible d'exécuter dex: l'ID de la méthode n'est pas dans [0, 0xffff]: 65536

Il semble que cette erreur se produit car ma demande a trop de méthodes. Je suis assez certain que la plupart de ces méthodes sont des pots de tiers, il est donc irréaliste d'essayer de résoudre cela en simplifiant mon code. J'ai trouvé ces deux suggestions en ligne.

  1. ajouter dex.force.jumbo=truepour le projet.propriétés (et utiliser la version 21 de l'adt). Je l'ai fait mais l'erreur persiste.

  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 elle s'applique dans mon cas. Le problème est que les services comme Drive ont trop de dépendances. Cette solution ne nécessiterait-elle pas que je modifie la source du lecteur pour utiliser l'inflexion en se référant à ses dépendances? (ce n'est clairement pas une option).

  3. utiliser proguard pour rétrécir enlever non utilisé code/méthodes. L'exportation de mon application avec proguard fonctionne, et l'intégration du service de documents fonctionne comme prévu sur un appareil >4.0. Cependant, les erreurs non-classefound sont lancées lors d'un test sur un appareil 2.3.

Donc, j'espère pour quelques conseils sur cette question. L'option 2 est-elle une solution pour mon cas? Est-il une autre solution que je devrais envisager?

24
demandé sur danfuzz 2013-03-19 23:16:07
la source

8 ответов

vous pouvez également développer un ou plusieurs de ceux-ci comme un plugin à votre application principale, sous la forme D'un APK séparé disponible pour le téléchargement. Que APK exposerait un composant que l'application principale utiliserait -- puisque je ne connais pas la nature de votre intégration avec ces services, Je ne peux pas faire une recommandation plus spécifique à ce sujet. Vous utilisez votre propre signature - niveau personnalisé <permission> pour sécuriser les communications entre les deux applications. Et, comme bonus, si l'utilisation de la bibliothèque tiers ajoute exigences pour les permissions supplémentaires, vous n'aurez besoin que de ces permissions dans le plugin APK, en gardant votre APK principal plus petit.

14
répondu CommonsWare 2013-03-20 00:09:16
la source

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

Android 5.0 et supérieur

le support Multi-dex est inclus automatiquement. Dans la doc:

Android 5.0 et plus utilise un runtime appelé ART qui nativement prend en charge le chargement de plusieurs fichiers dex à partir des fichiers APK de l'application. ART effectue une pré-compilation au moment de l'installation de l'application qui scanne classe.(.Et.)les dossiers dex et les compile dans un seul. avoine fichier pour l'exécution par l'appareil Android. Pour plus d'informations sur l'Android 5.0 exécution, voir Introduction à L'art.

Sous Android 5.0

il suffit D'ajouter L'outil de prise en charge mult-dex D'Android à votre construction gradle:

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
répondu Jason 2015-01-18 22:00:16
la source

la VM de Dalvik peut avoir un maximum de 65536 méthodes par fichier dex, en raison de l'instruction bytecode jeu n'ayant pas une façon de se référer à des numéros de méthode nécessitant plus de 16 bits (comme souligné par @danfuzz dans les commentaires).

alors qu'il est possible de corriger cela en utilisant plusieurs fichiers dex, Facebook trouvé un autre fix qu'ils pourraient déployer dans leur application pour contourner le problème.

6
répondu Raghav Sood 2013-03-20 00:17:03
la source

voir VM / LinearAlloc.c et vous pouvez trouver ce code: (5MiB sous Android 2.3.3, 8MiB après Android 4.0 comme mon enquête)

#define DEFAULT_MAX_LENGTH (5*1024*1024)--1-->

...

LinearAllocHdr * pHdr;

...

pHdr->mapLength = DEFAULT_MAX_LENGTH;

je suppose que la 'correction Facebook' édite cette mémoire en utilisant le pointeur C natif. Problème LinearAlloc IMHO et ce problème d'identification de méthode est différent chose.

5
répondu Francesco Jo 2013-07-10 06:50:13
la source

j'ai fait face à ce problème récemment. Après avoir épluché le web pour une implémentation 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 a trop de méthodes dans mon code, mais que l' dex de mon code et d'autres bibliothèques était le problème. Donc, si je pouvais compiler mon code contre les bibliothèques mais ne pas les inclure dans le classes.dex et dex les bibliothèques séparément, et puis tout mettre ensemble à l'exécution, il devrait fonctionner. Le seul problème à résoudre est le chargeur de classe, dont Facebook a parlé en passant.

donc avec un peu de réflexion et un peu de code Groovy, je pense que j'ai trouvé une façon relativement stable d'empaqueter les bibliothèques et le code d'application dans desdex fichiers.

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

3
répondu Nick Caballero 2013-10-18 22:33:06
la source

La plupart des problèmes avec l'atteinte de la limite de la méthode 65k sont liés à l'utilisation des services Google Play mastodontiques dans vos applications. Récemment, vous pouvez obtenir plus de granularité en l'utilisant.

Suivant ce guide, vous pouvez utiliser uniquement les pièces que vous souhaitez. Cela réglera probablement le problème, en évitant certains trucs de magie noire, ou en utilisant multiDex. Par exemple, si vous voulez seulement Google Maps dans votre application (et que vous n'utilisez pas les annonces, portefeuille, Google wear, analytics, etc...), utiliser la dépendance entière est une perte de temps/d'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
répondu webo80 2015-02-10 17:54:48
la source

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

une fois que vous avez compté les méthodes, vous pouvez vous concentrer sur le remaniement et la suppression des bibliothèques lourdes.

0
répondu Tom Susel 2014-07-28 13:13:45
la source

vous devez activer le support Dex pour cela. Vous devez donc suivre les étapes suivantes:

  1. Gradle plugin V0.14.0 pour Android ajoute le support pour multi-dex. Pour activer, il suffit de le déclarer dans build.gradle:
android {
   defaultConfig {
      ...
      multiDexEnabled = true
   }
}
  1. si le support de l'application > 5.0 (c'est-à-dire si votre minSdkVersion est inférieur ou égal à 20), vous devez également corriger dynamiquement L'application ClassLoader, de sorte qu'il sera capable de charger des classes à partir de Dex secondaires. pour cela, vous pouvez ajouter cette lib.
 dependencies {
      ...
      compile 'com.android.support:multidex:1.0.0'
    }
  1. activer en code pour que vous ayez cette option. 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 Multi-Application

public class App extends MultiDexApplication { .. }

C. installez-le 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 d'aller à travers ce lien MultiDex.

0
répondu RATHI 2016-05-04 21:44:18
la source

Autres questions sur