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

170

Es gibt ein Problem mit der Android Appcompat v7-Bibliothek auf Samsung-Geräten mit Android 4.2. Ich bekomme immer wieder Abstürze mit dem folgenden Stack-Trace in meiner Entwicklerkonsole:

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)

Dies ist Zeile 215 von CustomActivity.java:

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

Die Abstürze kommen von einer Reihe von Geräten, aber immer von Samsung und immer von Android 4.2.

Eine schnelle Websuche lässt mich glauben, dass viele Menschen das gleiche Problem haben. Einige der Schritte, die ich versucht habe, um das Problem zu lösen, sind:

  • Überprüfen Sie die Eigenschaften des Android-Projekts und stellen Sie sicher, dass die Appcompat-Bibliothek ordnungsgemäß hinzugefügt wurde.
  • Überprüfen Sie die Projekteigenschaften für Java Build Path Order und Export, stellen Sie sicher, dass Android Dependencies und Android Private Libraries aktiviert sind.
  • Bestätigen Sie, dass die Klasse in der Bibliothek enthalten ist (android.support.v7.internal.view.menu.MenuBuilder).
  • Bestätigen Sie, dass sich R.java im Verzeichnis gen für android.support.v7.appcompat befindet.
  • Vergewissern Sie sich, dass das AppCompat-Thema in der Aktivität Manifest.xml enthalten ist.
  • Projekt reinigen und neu erstellen.

Trotz dieser Schritte und obwohl es auf allen anderen Geräten und Android-Versionen funktioniert, werden die Absturzberichte immer noch angezeigt.

Matt K.
quelle
4
Hinweis: Ich habe dies auch beim QMobile X25 gesehen, einem Low-End-Telefon aus Pakistan. Es sieht also so aus, als hätten andere den gleichen Ansatz oder das gleiche ROM wie das ausgefallene Samsung-ROM gewählt.
William
Kann sich jemand eine Lösung vorstellen, bei der Proguard nicht involviert ist (was andere Probleme aufwirft), da sowohl Google als auch Samsung bei der Lösung dieses RIESIGEN Problems nicht hilfreich sind?
Checkliste
Google wird nichts dagegen unternehmen, da Samsung anscheinend zusätzliche Änderungen vorgenommen hat, die zu einer Namenskollision zwischen Bibliotheken führen. Proguard vermeidet die Kollision. Ich habe auch im Android Issue Tracker-Forum keine besseren Lösungen gesehen .
Matt K
Ich kann auch ein QMobile A290 aus Pakistan hinzufügen.
sstn
2
gleiche Ausgabe [QMobile X30 - Android 4.4.2]
Shanraisshan

Antworten:

100

BEARBEITEN:

Die Lösung, die für mich funktioniert hat, war (Verwenden von Proguard), um dies zu ersetzen:

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

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

mit diesem:

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

Das Guthaben geht an die Google-Gruppe Nr. 138 .

Alte Antwort (vorübergehende Problemumgehung): Dies geschieht in einem Projekt, in dem ich einen Spinner in der ActionBar verwende. Meine Lösung bestand darin, diese Bedingungen zu überprüfen und den App-Ablauf zu ändern:

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

Dann in der onCreate-Methode der Aktivität:

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

Wie bereits erwähnt, handelt es sich hierbei nicht um eine endgültige Lösung, sondern lediglich um eine Möglichkeit, Benutzern den Zugriff auf eingeschränkte Funktionen zu ermöglichen, während eine dauerhaftere Lösung gefunden wird.

vereinheitlichen
quelle
2
Kann jemand diese Antwort überprüfen? Ich habe keinen Zugriff auf ein Samsung und die App, an der ich gearbeitet habe, ist nicht mehr aktiv, sodass ich sie nicht testen kann.
Matt K
3
@JaredBurrows Sie entfernen die Bibliothek nicht, Sie weisen Proguard lediglich an, sie standardmäßig zu ignorieren. Mit dem Fix ignorieren Sie alles unter android.support außer android.support.v7.internal.view.menu
vereinheitlichen Sie den
2
Ich benutze seit Monaten eine Lösung aus diesem Problembericht und plötzlich, nachdem ich auf die neuesten Support-Bibliotheken und SDK 23 aktualisiert habe, habe ich begonnen, diesen neuen Bericht über Crashlytics zu erhalten:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
Casolorz
3
Das Problem trat in meiner App auf, als II auf AppCompat v23 aktualisiert wurde. Ich habe die JAR-Datei AppCompat v.23.1.1 analysiert und festgestellt, dass das "interne" Verzeichnis in v7 entfernt wurde. Daher sollte die Proguard-Befehlszeile jetzt wie folgt lauten: [-keep class! Android.support.v7.view. menu. **, android.support. ** {*;}] Ich habe immer noch keine Bestätigung von Tests auf einem realen Gerät, auf dem das Problem aufgetreten ist. Könnte jemand mit einem solchen Gerät dies testen? Oder ist das Entfernen des 'internen' Verzeichnisses tatsächlich die Lösung für das Problem und wir müssen uns nicht mehr mit dem Umbenennen der Proguard-Klasse herumschlagen?
Gregko
7
Fügen Sie dies zu Ihren Proguard-Einstellungen hinzu, um das Problem zu lösen: FOR APPCOMPAT 23.1.1: -keep class! Android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -keep interface android.support.v7. * { ; } FÜR ÄLTERE APPCOMPAT-VERSION: -keep class! Android.support.v7.internal.view.menu. * MenuBuilder , android.support.v7. ** { ; } -keep interface android.support.v7. * {*; }
Andrea Bellitto
26

Wie # 150 von Google Groups sagte

Weil vorsichtig mit -keep class! Android.support.v7.internal.view.menu. **. Dort gibt es eine Reihe von Klassen, auf die aus den Ressourcen des Appcompat verwiesen wird.

Die bessere Lösung besteht darin, stattdessen die folgenden Zeilen hinzuzufügen:

-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }
Pongpat
quelle
In meinen Tests, basierend auf einer Überprüfung der generierten Proguard-Zuordnungsdatei, führt diese vorgeschlagene Proguard-Konfiguration nicht dazu, dass der MenuBuilder-Klassenname verschleiert wird, obwohl SubMenuBuilder verschleiert wird.
Andy Dennie
3
@ William Jemand hat es gelöscht, weiß nicht warum. Wie auch immer, hier ist meine Lösung: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
Andy Dennie
3
Dies funktionierte für mich, wo das -keep class !android.support.v7.internal.view.menu.**,** {*;} mit v23 der App-Kompatibilität nicht mehr funktionierte .
Quentin Klein
1
-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; }als Antwort :)
Quentin Klein
2
In der 23.1.1-Unterstützungsbibliothek wurden die internen Paketpfade geändert. Daher lautet die korrekte Proguard-Einstellung jetzt: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -keep interface android.support.v7. * {*; }
Andrea Bellitto
23

Auf welchem ​​Gerät ist dieses Problem aufgetreten? (Samsung / HTC usw.)

Wenn es Samsung ist,

Verschiedene Samsung-Handys enthalten ältere Versionen der Android-Support-Bibliothek im Framework oder Klassenpfad. Wenn Sie die neue Materialunterstützungsbibliothek verwenden, wird dieser Absturz auf diesen Samsung-Geräten angezeigt:

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

Um dies zu beheben, müssen Sie diese Klasse umbenennen. Der einfachste Weg, dies zu tun, ist das Ausführen von Proguard. Wenn Sie nicht verschleiern möchten, finden Sie hier einen 1-Liner, mit dem Sie nur die betreffenden Klassen umbenennen können:

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

Es gibt ein Problem, das dieses Problem verfolgt, aber da es sich wirklich um einen Samsung-Fehler handelt, wird es nie behoben. Die einzige Möglichkeit, dies auf der Google / AOSP-Seite zu beheben, besteht darin, diese internen Klassen umzubenennen.

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

Ganesh AB - Android
quelle
Verwenden Sie Proguard für Support v4?
Jared Burrows
@JaredBurrows Ich habe versucht, Unterstützung v7. Aber für v4 wird es auch funktionieren.
Ganesh AB - Android
2
@ Android007: Danke, dass du auf die Umgehung hingewiesen hast, die tatsächlich funktioniert. Es scheint jedoch niemand erklären zu können, warum die fehlerhaften ROMs, die die alte Android-Support-Bibliothek in ihren Bootklassenpfad einbetten, diese Ausnahme verursachen, da die fehlende Klasse "android.support.v7.internal.view.menu.MenuBuilder" in der Klasse verfügbar ist. apk DEX-Code der Anwendung, die unter diesem Problem leidet. Hätten Sie einen Zeiger zur Hand, der erklärt, wie die Android-Laufzeit die Klassen lädt, die aus den Bootclasspath-JAR / Dex-Dateien und den Anwendungen stammen, bitte? Oder eine genaue Erklärung bitte?
Édouard Mercier
@ ÉdouardMercier Entschuldigung für die späte Antwort. Derzeit habe ich keine Antwort auf Ihre Frage, werde mich aber bald bei Ihnen melden. :)
Ganesh AB - Android
Vielen Dank an Android007, wie jeder Programmierer, ich mag Hexerei nicht sehr;) Ein Hinweis: Würde der eingebettete Bootklassenpfad "versiegelte" .jar / .dex enthalten, was das Verhalten erklären würde?
Édouard Mercier
15

Dieses Problem trat dort auf, AppCompat 23.1.1wo das .internalPaket aus dem Bibliotheksglas entfernt wurde.

Wie in den obigen Kommentaren vorgeschlagen (Credits an die Leute, die es dort vorgeschlagen haben), muss sich jetzt auch die Proguard-Konfiguration ändern.

Fügen Sie diese Zeilen zu Ihren Proguard-Dateien hinzu, damit die oben vorgeschlagene Antwort wieder funktioniert:

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

Anstelle des alten Fixes:

#FOR OLDER APPCOMPAT VERSION:
-keep class !android.support.v7.internal.view.menu.*MenuBuilder, android.support.v7.** { ; }
-keep interface android.support.v7.* { *; }
RWIL
quelle
!android.support.v7.view.menu.**ist sicherer wegen anderer Klassen wie SubMenuBuilder
JaredBanyard
12

Laut den letzten Beiträgen des Fehlerberichts sollte dies in der neuen Version der Support-Bibliothek (24.0.0) behoben werden: https://code.google.com/p/android/issues/detail?id=78377 # c374

Jemand behauptete sogar, es habe das Problem behoben.

Diese Version ist seit letztem Monat verfügbar , daher sollten Sie sie aktualisieren.

Android-Entwickler
quelle
Unsere Tests bestätigen, dass 24.0.0 das Problem behebt. Wir haben die Support-Bibliothek auf 24.0.0 (nicht Alpha) aktualisiert, die von uns als Problemumgehung verwendete Verschleierung entfernt und auf einem Samsung-Testgerät, auf dem wir zuvor den Absturz gesehen haben, keine Abstürze festgestellt.
Mark McClelland
4

Ja. Samsung kennt dieses Problem bereits. Ich kann vorschlagen, dass Sie versuchen, dieselbe Implementierung von Popup von GitHub zu verwenden . Es ist nicht der beste Weg, aber es wird funktionieren.

Eldar Miensutov
quelle
1
Ja, das habe ich im Samsung-Forum gesehen, aber es scheint nicht so, als wären sie interessiert, da keiner ihrer Vertreter oder Unterstützer geantwortet hat.
Matt K
4

Ich hatte das gleiche Problem mit dieser MenuBuilder-Klasse, das im USB-Debugging-Modus nicht gefunden wurde. Ich habe dieses Problem gelöst, indem ich einfach minifyEnabled sowohl im Release- als auch im Debug- BuildTypes- Block von build.gradle auf true gesetzt habe . so was:

buildTypes {

    debug {

        minifyEnabled true
    }

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

Ich habe minifyEnabled im Debug- Typ auf true gesetzt, um zu verhindern, dass die App über das USB-Debugging auf einem Live-Mobilteil abstürzt.

FAQi
quelle
0

Ich habe Proguard mit den Standard-Proguard-Eigenschaften aktiviert, die mit einem Eclipse-Projekt bereitgestellt wurden, und das Problem wurde für mich behoben. Basierend auf einigen Kommentaren hier https://code.google.com/p/android/issues/detail?id=78377 müssen einige Leute möglicherweise neu packen mit: -repackageclasses "android.support.v7"

u2tall
quelle
Sieht so aus, als würde das für die meisten Leute im Forum nicht funktionieren. Die Rückkehr zu Appcompat-20 scheint eine zuverlässigere Option zu sein.
Matt K
Dies wurde angeblich in Support v23.1.1
Tim Malseed
0

Ich habe den gleichen Fehler erhalten, als ich versucht habe, eine "Hello World" -App auf meinem Samsung Galaxy Tab 3-Tablet über Android Studio auszuführen. Die App scheint zu starten und stürzt dann sofort ab, und dieser Fehler wird in der Konsole in Android Studio angezeigt. Ich habe ein System-Update auf dem Tablet durchgeführt und kann jetzt die App 'Hello World' ausführen. Der Fehler wird nicht mehr angezeigt. Ich hoffe, dies hilft jemandem, sein Problem zu lösen.

Hinweis: Das Systemupdate, das ich auf dem Tablet durchgeführt habe, hat die Android-Betriebssystemversion nicht aktualisiert, da immer noch angegeben wird, dass die Version 4.2.2 ist.

Julian David
quelle
-4

Ändern Sie die Compile Sdk-Version Ihres Projekts in "API 18: (JellyBean)".

Der Standardwert ist "Lollipop"

SCHRITTE

  1. Klicken Sie mit der rechten Maustaste auf Ihr Projekt und wählen Sie Moduleinstellungen öffnen (oder drücken Sie F4).
  2. Auf der Registerkarte Eigenschaften Kompilierte Sdk-Version
Jazib Hasan
quelle