NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder

170

Il y a un problème avec la bibliothèque Android appcompat v7 sur les appareils Samsung exécutant Android 4.2. Je reçois des plantages avec la trace de pile suivante dans ma Developer Console:

java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder
    at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:66)
    at com.[my-package-name].CustomActivity$5.onClick(CustomActivity.java:215)
    at android.view.View.performClick(View.java:4222)
    at android.view.View$PerformClick.run(View.java:17620)
    at android.os.Handler.handleCallback(Handler.java:800)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:194)
    at android.app.ActivityThread.main(ActivityThread.java:5391)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
    at dalvik.system.NativeStart.main(Native Method)

Il s'agit de la ligne 215 de CustomActivity.java:

PopupMenu popup = new PopupMenu(CustomActivity.this, mImageViewMenu);

Les plantages proviennent d'un large éventail d'appareils, mais toujours Samsung, et toujours Android 4.2.

Une recherche rapide sur le Web me porte à croire que de nombreuses personnes ont le même problème, certaines des étapes que j'ai essayées pour résoudre le problème sont:

  • Vérifiez les propriétés du projet Android, assurez-vous que la bibliothèque appcompat est correctement ajoutée.
  • Vérifiez l'ordre du chemin de construction Java et les propriétés du projet d'exportation, assurez-vous que les dépendances Android et les bibliothèques privées Android sont cochées.
  • Confirmez que la classe est incluse dans la bibliothèque (android.support.v7.internal.view.menu.MenuBuilder).
  • Vérifiez que R.java se trouve dans le répertoire gen pour android.support.v7.appcompat.
  • Confirmez que le thème AppCompat est inclus dans l'activité Manifest.xml.
  • Projet de nettoyage et de reconstruction.

Malgré ces étapes, et bien que cela fonctionne sur tous les autres appareils et versions d'Android, les rapports de plantage sont toujours disponibles.

Matt K
la source
4
Remarque: j'ai également vu cela se produire sur le QMobile X25, un téléphone bas de gamme en provenance du Pakistan. Il semble donc que les autres ont adopté la même approche ou la même ROM que la ROM Samsung défaillante.
William
Étant donné que Google et Samsung ne sont pas utiles pour résoudre ce problème ÉNORME, quelqu'un peut-il penser à une solution qui n'implique pas Proguard (ce qui soulève d'autres problèmes)?
liste de contrôle du
Google ne va rien y faire puisque c'est Samsung qui semble avoir apporté des modifications supplémentaires provoquant une collision de noms entre les bibliothèques. Proguard évite la collision. Je n'ai pas non plus vu de meilleures solutions sur le forum Android Issue Tracker .
Matt K
Je peux également ajouter un QMobile A290, hors du Pakistan.
sstn
2
même problème [QMobile X30 - Android 4.4.2]
shanraisshan

Réponses:

100

ÉDITER:

La solution qui a fonctionné pour moi était (Utiliser Proguard) pour remplacer ceci:

-keep class android.support.v4.** { *; } 
-keep interface android.support.v4.** { *; }

-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }

avec ça:

# Allow obfuscation of android.support.v7.internal.view.menu.**
# to avoid problem on Samsung 4.2.2 devices with appcompat v21
# see https://code.google.com/p/android/issues/detail?id=78377
-keep class !android.support.v7.internal.view.menu.**,android.support.** {*;}

Le mérite revient au groupe Google, n ° 138 .

Ancienne réponse (solution de contournement temporaire): cela se produit dans un projet où j'utilise une flèche dans l' ActionBar. Ma solution était de vérifier ces conditions et de modifier le flux de l'application:

public static boolean isSamsung_4_2_2() {
    String deviceMan = Build.MANUFACTURER;
    String deviceRel = Build.VERSION.RELEASE;
    return "samsung".equalsIgnoreCase(deviceMan) && deviceRel.startsWith("4.2.2");
}

Ensuite, dans la méthode onCreate de l'activité:

if (isSamsung_4_2_2()) {
    setContentView(R.layout.activity_main_no_toolbar);
} else {
    setContentView(R.layout.activity_main);
}

Comme indiqué, ce n'est pas une solution définitive, c'est juste un moyen de permettre aux utilisateurs d'avoir accès à des fonctionnalités limitées pendant qu'une solution plus permanente est trouvée.

unifier
la source
2
Quelqu'un d'autre peut-il vérifier cette réponse? Je n'ai pas accès à un Samsung et l'application sur laquelle je travaillais n'est plus active, je ne peux donc pas la tester.
Matt K
3
@JaredBurrows Vous ne supprimez pas la bibliothèque, vous dites simplement à proguard de l'ignorer par défaut, avec le correctif, vous ignorez tout sous android.support sauf pour android.support.v7.internal.view.menu
unify
2
J'utilise une solution de ce rapport de problème depuis des mois maintenant et tout d'un coup après la mise à jour vers les dernières bibliothèques de support et sdk 23, j'ai commencé à obtenir ce nouveau rapport sur crashlytics:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
casolorz
3
Le problème est revenu dans mon application lorsque II est passé à AppCompat v23. J'ai analysé le fichier jar AppCompat v.23.1.1, et j'ai vu qu'ils ont supprimé le répertoire "interne" dans la v7, il semble donc que la ligne d'instruction Proguard devrait être maintenant: [-keep class! Android.support.v7.view. menu. **, android.support. ** {*;}] Je n'ai toujours pas de confirmation des tests sur un appareil réel où le problème est survenu. Quelqu'un avec un tel appareil pourrait-il tester cela? Ou peut-être que la suppression du répertoire `` interne '' est en fait la solution au problème et que nous n'avons plus besoin de modifier le nom de la classe Proguard?
gregko
7
Ajoutez ceci à vos paramètres proguard, cela résoudra le problème: POUR APPCOMPAT 23.1.1: -keep class! Android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -keep interface android.support.v7. * { ; } POUR LES PLUS ANCIENNES VERSION APPCOMPAT: -keep class! Android.support.v7.internal.view.menu. * MenuBuilder , android.support.v7. ** { ; } -keep interface android.support.v7. * {*; }
Andrea Bellitto
26

Comme # 150 des groupes Google dit

Car attention avec -keep class! Android.support.v7.internal.view.menu. **. Il y a un certain nombre de classes qui sont référencées à partir des ressources de l'appcompat.

La meilleure solution consiste à ajouter les lignes suivantes à la place:

-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }
Pongpat
la source
Dans mes tests, basés sur un examen du fichier de mappage proguard généré, cette configuration de proguard suggérée ne conduit pas à masquer le nom de la classe MenuBuilder, bien qu'elle masque SubMenuBuilder.
Andy Dennie
3
@William Quelqu'un l'a supprimé, je ne sais pas pourquoi. Bref, voici ma solution: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
Andy Dennie
3
Cela a fonctionné pour moi où le -keep class !android.support.v7.internal.view.menu.**,** {*;} ne fonctionnait plus avec la v23 de la compatibilité de l' application .
Quentin Klein
1
-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; }comme réponse :)
Quentin Klein
2
sur la bibliothèque de support 23.1.1, les chemins de paquet internes ont été modifiés, donc maintenant le paramètre proguard correct est: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -keep interface android.support.v7. * {*; }
Andrea Bellitto
23

Sur quel appareil vous rencontrez ce problème? (Samsung / HTC etc.)

Si c'est Samsung,

Divers téléphones Samsung sont inclus dans les anciennes versions de la bibliothèque de support Android dans le framework ou le classpath. Si vous utilisez la nouvelle bibliothèque de support matériel, vous verrez ce plantage sur ces appareils Samsung:

java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder

Pour résoudre ce problème, vous devez renommer cette classe. Le moyen le plus simple de le faire est d'exécuter proguard. Si vous ne voulez pas obscurcir, voici une ligne 1 pour renommer uniquement les classes incriminées:

-keep class !android.support.v7.internal.view.menu.**,** {*;}

Il y a un problème pour suivre ce problème, mais comme il s'agit vraiment d'un bogue Samsung, il ne sera jamais résolu de leur côté. Le seul moyen de résoudre ce problème du côté Google / AOSP est de renommer ces classes internes.

https://code.google.com/p/android/issues/detail?id=78377

Ganesh AB - Android
la source
Utilisez-vous proguard pour le support v4?
Jared Burrows
@JaredBurrows J'ai essayé le support v7. Mais pour la v4, cela fonctionnera également.
Ganesh AB - Android
2
@ Android007: merci d'avoir indiqué cette solution de contournement qui fonctionne réellement. Cependant, personne ne semble être en mesure d'expliquer pourquoi les ROM défectueuses intégrant l'ancienne bibliothèque de support Android dans leur bootclasspath provoquent cette exception car la classe manquante "android.support.v7.internal.view.menu.MenuBuilder" est disponible dans le. apk DEX code de l'application qui souffre de ce problème. Auriez-vous un pointeur à portée de main qui explique comment le runtime Android charge les classes extraites des fichiers jar / dex bootclasspath et de l'application, s'il vous plaît? Ou une explication précise, s'il vous plaît?
Édouard Mercier
@ ÉdouardMercier Désolé pour la réponse tardive. Actuellement, je n'ai pas de réponse à votre question mais je vous répondrai bientôt. :)
Ganesh AB - Android
Merci @ Android007, comme tout programmeur, je n'aime pas beaucoup la sorcellerie;) Un indice: le bootclasspath intégré contiendrait-il "scellé" .jar / .dex, ce qui expliquerait le comportement?
Édouard Mercier
15

Ce problème est revenu à l' AppCompat 23.1.1endroit où le .internalpackage a été supprimé du fichier jar de la bibliothèque.

Comme suggéré dans les commentaires ci-dessus (merci aux personnes qui l'ont suggéré), la configuration proguard doit maintenant changer.

Pour que la réponse suggérée ci-dessus fonctionne à nouveau, essayez d'ajouter ces lignes à vos fichiers proguard:

#FOR APPCOMPAT 23.1.1:
-keep class !android.support.v7.view.menu.*MenuBuilder*, android.support.v7.** { *; }
-keep interface android.support.v7.* { *; }

Au lieu de l'ancien correctif:

#FOR OLDER APPCOMPAT VERSION:
-keep class !android.support.v7.internal.view.menu.*MenuBuilder, android.support.v7.** { ; }
-keep interface android.support.v7.* { *; }
RWIL
la source
!android.support.v7.view.menu.**est plus sûr grâce à d'autres classes telles que SubMenuBuilder
JaredBanyard
12

Selon les derniers messages du rapport de bogue, cela devrait être corrigé sur la nouvelle version de la bibliothèque de support (24.0.0): https://code.google.com/p/android/issues/detail?id=78377 # c374

Quelqu'un a même prétendu que c'était réglé.

Cette version est disponible depuis le mois dernier , vous devriez donc la mettre à jour.

développeur android
la source
Nos tests confirment que 24.0.0 résout le problème. Nous avons mis à niveau la bibliothèque de support vers 24.0.0 (pas alpha), supprimé l'obfuscation que nous utilisions comme solution de contournement et n'avons constaté aucun crash sur un appareil de test Samsung où nous avons déjà vu le crash.
Mark McClelland
4

Oui. Samsung connaît déjà ce problème. Je peux vous suggérer d'essayer d'utiliser la même implémentation de Popup de GitHub . Ce n'est pas la meilleure façon, mais ce sera des œuvres.

Eldar Miensutov
la source
1
Oui, j'ai vu cela sur le forum Samsung, mais il ne semble pas qu'ils soient intéressés car aucun de leurs représentants ou de l'assistance n'a répondu.
Matt K
4

J'avais le même problème de cette classe MenuBuilder introuvable en mode de débogage USB. J'ai résolu ce problème en définissant simplement le minifyEnabled sur true dans les blocs buildTypes release et debug de build.gradle . comme ça:

buildTypes {

    debug {

        minifyEnabled true
    }

    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

J'ai défini minifyEnabled sur true dans le type de débogage pour empêcher l'application de planter via le débogage USB sur un combiné en direct.

FAQi
la source
0

J'ai activé proguard avec les propriétés proguard par défaut fournies avec un projet eclipse et le problème a été résolu pour moi. Sur la base de quelques commentaires ici https://code.google.com/p/android/issues/detail?id=78377 , certaines personnes pourraient devoir reconditionner en utilisant: -repackageclasses "android.support.v7"

u2tall
la source
Il semble que cela ne fonctionne pas pour la plupart des utilisateurs du forum. On dirait que revenir à appcompat-20 est une option plus fiable.
Matt K
Cela aurait été résolu dans le support v23.1.1
Tim Malseed
0

J'ai eu la même erreur en essayant d'exécuter une application «Hello World» sur ma tablette Samsung Galaxy Tab 3 via Android Studio. L'application semblerait se lancer, puis elle planterait instantanément et cette erreur s'afficherait dans la console d'Android Studio. J'ai fait une mise à jour du système sur la tablette et maintenant je suis capable d'exécuter l'application 'Hello World' et je ne reçois plus l'erreur. J'espère que cela aidera quelqu'un à résoudre son problème.

Remarque: la mise à jour du système que j'ai effectuée sur la tablette n'a pas mis à jour la version du système d'exploitation Android, car elle indique toujours que la version est 4.2.2.

JulianDavid
la source
-4

Changez la version Compile Sdk de votre projet en "API 18: (JellyBean)"

La valeur par défaut est "Lollipop

PAS

  1. Faites un clic droit sur votre projet et sélectionnez Ouvrir les paramètres du module (ou appuyez sur F4)
  2. Dans l'onglet Propriétés Version Sdk compilée
Jazib Hasan
la source