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


170

Si è verificato un problema con la libreria v7 dell'appcompat per Android sui dispositivi Samsung con Android 4.2. Continuo a ricevere arresti anomali con la seguente traccia dello stack nella mia Console per gli sviluppatori:

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)

Questa è la riga 215 di CustomActivity.java:

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

Gli arresti anomali provengono da una serie di dispositivi, ma sempre Samsung e sempre Android 4.2.

Una rapida ricerca sul Web mi porta a credere che molte persone abbiano lo stesso problema, alcuni dei passaggi che ho provato a risolvere il problema sono:

  • Controlla le proprietà del progetto Android, assicurati che la libreria appcompat sia stata aggiunta correttamente.
  • Controlla l'ordine del percorso build Java ed esporta le proprietà del progetto, assicurati che le dipendenze Android e le librerie private Android siano selezionate.
  • Verifica che la classe sia inclusa nella libreria (android.support.v7.internal.view.menu.MenuBuilder).
  • Conferma che R.java si trova nella directory gen per android.support.v7.appcompat.
  • Verificare che il tema AppCompat sia incluso nell'attività Manifest.xml.
  • Progetto pulito e ricostruito.

Nonostante questi passaggi e nonostante funzioni su tutti gli altri dispositivi e versioni Android, i rapporti sugli arresti anomali continuano ad arrivare.


4
Nota: ho anche visto che ciò si verifica sul QMobile X25, un telefono di fascia bassa proveniente dal Pakistan. Quindi sembra che le oythers abbiano lo stesso approccio o la stessa ROM della ROM Samsung fallita.
William,

Poiché sia ​​Google che Samsung non sono utili per risolvere questo enorme problema, qualcuno può pensare a una soluzione che non coinvolga Proguard (che solleva altri problemi)?
lista di controllo

Google non ha intenzione di fare nulla al riguardo, poiché è Samsung che sembra aver apportato ulteriori modifiche che causano una collisione di nomi tra le librerie. Proguard evita la collisione. Non ho visto nessuna soluzione migliore sul forum Android Issue Tracker .
Matt K,

Posso aggiungere un QMobile A290, anche dal Pakistan.
sstn

2
stesso problema [QMobile X30 - Android 4.4.2]
shanraisshan,

Risposte:


100

MODIFICARE:

La soluzione che ha funzionato per me è stata (utilizzando Proguard) per sostituire questo:

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

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

con questo:

# 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.** {*;}

Il merito va al gruppo google, n . 138 .

Vecchia risposta (soluzione temporanea): succede in un progetto in cui utilizzo un filatore in ActionBar. La mia soluzione era quella di verificare tali condizioni e modificare il flusso dell'app:

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");
}

Quindi nel metodo onCreate dell'attività:

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

Come sottolineato, questa non è una soluzione definitiva, è solo un modo per consentire agli utenti di accedere a funzionalità limitate mentre viene trovata una soluzione più permanente.


2
Qualcun altro può verificare questa risposta? Non ho accesso a un Samsung e l'app a cui stavo lavorando non è più attiva, quindi non posso provarlo.
Matt K,

3
@JaredBurrows Non rimuovi la libreria, dici semplicemente a proguard di ignorarla per impostazione predefinita, con la correzione ignori tutto sotto android.support tranne android.support.v7.internal.view.menu
unify

2
Sto usando una soluzione da quel rapporto sul problema ormai da mesi e all'improvviso dopo l'aggiornamento alle ultime librerie di supporto e sdk 23 ho iniziato a ricevere questo nuovo rapporto su crashlytics:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
casolorz,

3
Il problema è tornato nella mia app quando ho eseguito l'aggiornamento a AppCompat v23. Ho analizzato il file jar AppCompat v.23.1.1 e ho visto che hanno rimosso la directory "interna" all'interno di v7, quindi sembra che la riga di istruzioni Proguard dovrebbe essere ora: [-keep class! Android.support.v7.view. menu. **, android.support. ** {*;}] Non ho ancora una conferma dai test su un dispositivo reale in cui si è verificato il problema. Qualcuno con un dispositivo del genere potrebbe testarlo? O forse la rimozione della directory 'interna' è in realtà la soluzione del problema e non abbiamo più bisogno di fare casini con la ridenominazione della classe Proguard?
Gregko,

7
Aggiungilo alle tue impostazioni proguard, risolverà il problema: PER APPCOMPAT 23.1.1: -keep class! Android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -keep interface android.support.v7. * { ; } PER VECCHIE VERSIONI APPCOMPAT: -keep class! Android.support.v7.internal.view.menu. * MenuBuilder , android.support.v7. ** { ; } -keep interface android.support.v7. * {*; }
Andrea Bellitto,

26

Come # 150 da gruppi google detto

Attenzione con la classe -keep! Android.support.v7.internal.view.menu. **. Ci sono un certo numero di classi che fanno riferimento alle risorse dell'appcompat.

La soluzione migliore è invece aggiungere le seguenti righe:

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

Nei miei test, basato su una revisione del file di mappatura proguard generato, questa configurazione proguard suggerita non comporta l'offuscamento del nome della classe MenuBuilder, sebbene offusca SubMenuBuilder.
Andy Dennie,

3
@William Qualcuno l'ha cancellato, non so perché. Comunque, ecco la mia soluzione: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
Andy Dennie,

3
Questo ha funzionato per me dove -keep class !android.support.v7.internal.view.menu.**,** {*;} non funzionava più con v23 di app compat .
Quentin Klein,

1
-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; }come risposta :)
Quentin Klein,

2
sulla libreria di supporto 23.1.1 sono stati modificati i percorsi dei pacchetti interni, quindi ora l'impostazione proguard corretta è: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -keep interface android.support.v7. * {*; }
Andrea Bellitto,

23

Su quale dispositivo stai affrontando questo problema? (Samsung / HTC ecc.)

Se è Samsung,

Vari telefoni Samsung sono inclusi versioni precedenti della libreria di supporto Android nel framework o nel percorso di classe. Se usi la nuova libreria di supporto materiale, vedrai questo arresto anomalo su quei dispositivi Samsung:

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

Per risolvere questo problema, è necessario rinominare quella classe. Il modo più semplice per farlo è eseguire proguard. Se non vuoi offuscare, ecco un 1 liner per rinominare solo le classi offensive:

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

C'è un problema nel tracciare questo problema, ma dal momento che è davvero un bug Samsung, non verrà mai risolto dalla loro parte. L'unico modo per risolverlo sul lato Google / AOSP è rinominare queste classi interne.

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


Usi proguard per il supporto v4?
Jared Burrows,

@JaredBurrows Ho provato per il supporto v7. Ma anche per v4 funzionerà.
Ganesh AB - Android

2
@ Android007: grazie per aver indicato quella soluzione che funziona davvero. Tuttavia, nessuno sembra essere in grado di spiegare perché le ROM difettose che incorporano la vecchia libreria di supporto Android nel proprio bootclasspath causino questa eccezione poiché la classe "android.support.v7.internal.view.menu.MenuBuilder" mancante è disponibile nella. codice DEX apk dell'applicazione che soffre di questo problema. Avresti qualche puntatore a portata di mano che spieghi come il runtime di Android carica le classi prese dai file jar / dex bootclasspath e dall'applicazione, per favore? O qualche spiegazione precisa, per favore?
Édouard Mercier,

@ ÉdouardMercier Ci scusiamo per la risposta tardiva. Al momento non ho alcuna risposta per la tua domanda, ma ti contatterò al più presto. :)
Ganesh AB - Android

Grazie @ Android007, come qualsiasi programmatore, non mi piace molto la stregoneria;) Un suggerimento: il bootclasspath incorporato conterrebbe .jar / .dex "sigillato", che spiegherebbe il comportamento?
Édouard Mercier,

15

Questo problema si è verificato in AppCompat 23.1.1cui il .internalpacchetto è stato rimosso dal jar della libreria.

Come suggerito nei commenti sopra (crediti per le persone che lo hanno suggerito lì), ora anche la configurazione di proguard deve cambiare.

Per ottenere di nuovo la risposta suggerita sopra, prova ad aggiungere queste righe ai tuoi file proguard:

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

Al posto della vecchia correzione:

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

!android.support.v7.view.menu.**è più sicuro a causa di altre classi come SubMenuBuilder
JaredBanyard

12

Secondo gli ultimi post del bug report, questo dovrebbe essere corretto sulla nuova versione della libreria di supporto (24.0.0): https://code.google.com/p/android/issues/detail?id=78377 # c374

Qualcuno ha persino affermato che è stato risolto.

Questa versione è disponibile dallo scorso mese , quindi è necessario aggiornarla.


I nostri test confermano che 24.0.0 risolve il problema. Abbiamo aggiornato la libreria di supporto alla 24.0.0 (non alfa), rimosso l'offuscamento che stavamo usando come soluzione alternativa e non abbiamo riscontrato arresti anomali su un dispositivo di test Samsung in cui in precedenza abbiamo riscontrato l'incidente.
Mark McClelland,

4

Sì. Samsung conosce già questo problema. Posso suggerire di provare a utilizzare la stessa implementazione di Popup da GitHub . Non è il modo migliore, ma funzionerà.


1
Sì, l'ho visto sul forum Samsung, ma non sembra che siano interessati poiché nessuno dei loro rappresentanti o supporto ha risposto.
Matt K,

4

Stavo avendo lo stesso problema di questa classe MenuBuilder non trovata in modalità debug USB. Ho risolto questo problema semplicemente impostando minifyEnabled su true sia nel blocco buildTypes di debug che build.gradle . come questo:

buildTypes {

    debug {

        minifyEnabled true
    }

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

Ho impostato minifyEnabled su true nel tipo di debug per impedire il crash dell'app tramite debug USB su un portatile.


0

Ho abilitato proguard con le proprietà proguard predefinite fornite con un progetto eclipse e il problema è stato risolto per me. Sulla base di alcuni commenti qui https://code.google.com/p/android/issues/detail?id=78377 , alcune persone potrebbero dover riconfezionare utilizzando: -repackageclasses "android.support.v7"


Sembra che non funzioni per la maggior parte delle persone nel forum. Sembra che tornare ad appcompat-20 sia un'opzione più affidabile.
Matt K,

Ciò è stato presumibilmente risolto nel supporto v23.1.1
Tim Malseed,

0

Ho avuto lo stesso errore durante il tentativo di eseguire un'app 'Hello World' sul mio tablet Samsung Galaxy Tab 3 tramite Android Studio. L'app sembra avviarsi e quindi si bloccherebbe all'istante e tale errore verrà visualizzato nella console in Android Studio. Ho fatto un aggiornamento del sistema sul tablet e ora sono in grado di eseguire l'app "Hello World" e non ricevo più l'errore. Spero che questo aiuti qualcuno a risolvere il problema.

Nota: l'aggiornamento di sistema che ho eseguito sul tablet non ha aggiornato la versione del sistema operativo Android, poiché dice ancora che la versione è 4.2.2.


-4

Cambia la versione di compilazione Sdk del tuo progetto in "API 18: (JellyBean)"

L'impostazione predefinita è "Lecca-lecca

PASSI

  1. Fare clic con il tasto destro sul progetto e selezionare Apri le impostazioni del modulo (o premere F4)
  2. Nella scheda Proprietà Versione SDK compilata
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.