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

170

Ada masalah dengan pustaka appcompat v7 Android pada perangkat Samsung yang menjalankan Android 4.2. Saya terus mogok dengan jejak tumpukan berikut di Konsol Pengembang saya:

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)

Ini adalah baris 215 dari CustomActivity.java:

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

Tabrakan datang dari berbagai perangkat, tetapi selalu Samsung, dan selalu Android 4.2.

Pencarian web cepat membuat saya percaya bahwa banyak orang memiliki masalah yang sama, beberapa langkah yang saya coba selesaikan adalah:

  • Periksa properti proyek Android, pastikan pustaka appcompat ditambahkan dengan benar.
  • Periksa properti proyek Java Build Path Order dan Ekspor, pastikan Android Dependencies dan Android Private Libraries dicentang.
  • Konfirmasikan kelas termasuk dalam perpustakaan (android.support.v7.internal.view.menu.MenuBuilder).
  • Confirm R.java terletak di direktori gen untuk android.support.v7.appcompat.
  • Konfirmasi tema AppCompat termasuk dalam aktivitas Manifest.xml.
  • Bersihkan dan bangun kembali proyek.

Terlepas dari langkah-langkah ini, dan meskipun bekerja pada semua perangkat lain dan versi Android, laporan kerusakan masih muncul.

Matt K
sumber
4
Catatan: Saya juga melihat ini terjadi pada QMobile X25 yang merupakan ponsel low end dari Pakistan. Jadi sepertinya oythers telah mengambil pendekatan yang sama atau ROM yang sama dengan ROM Samsung yang gagal.
William
Karena Google dan Samsung tidak membantu menyelesaikan masalah BESAR ini, adakah yang bisa memikirkan solusi yang tidak melibatkan Proguard (yang menimbulkan masalah lain)?
daftar periksa
Google tidak akan melakukan apa-apa karena itu Samsung yang tampaknya telah membuat modifikasi tambahan yang menyebabkan benturan nama di antara perpustakaan. Proguard menghindari tabrakan. Belum melihat solusi yang lebih baik di forum Pelacak Isu Android .
Matt K
Saya dapat menambahkan QMobile A290, dari Pakistan juga.
sstn
2
masalah yang sama [QMobile X30 - Android 4.4.2]
shanraisshan

Jawaban:

100

EDIT:

Solusi yang berhasil bagi saya adalah (Menggunakan Proguard) untuk menggantikan ini:

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

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

dengan ini:

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

Kredit diberikan ke grup google, # 138 .

Jawaban lama (Solusi Sementara): Ini terjadi dalam proyek di mana saya menggunakan pemintal di ActionBar. Solusi saya adalah memeriksa kondisi tersebut dan mengubah aliran aplikasi:

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

Kemudian dalam metode onCreate aktivitas:

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

Seperti yang ditunjukkan ini bukan solusi yang pasti, itu hanya cara untuk memungkinkan pengguna memiliki akses ke fungsi terbatas sementara solusi yang lebih permanen ditemukan.

menyatukan
sumber
2
Adakah yang bisa memverifikasi jawaban ini? Saya tidak memiliki akses ke Samsung dan aplikasi yang sedang saya kerjakan tidak lagi aktif sehingga saya tidak bisa mengujinya.
Matt K
3
@JaredBurrows Anda tidak menghapus perpustakaan, Anda hanya meminta proguard untuk mengabaikannya secara default, dengan perbaikan Anda mengabaikan segala sesuatu di bawah android.support kecuali untuk android.support.v7.internal.view.menu
satukan
2
Saya telah menggunakan solusi dari laporan masalah itu selama berbulan-bulan sekarang dan tiba-tiba setelah memperbarui ke perpustakaan dukungan terbaru dan SD 23 saya mulai mendapatkan laporan baru ini pada crashlytics:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
casolorz
3
Masalahnya kembali di aplikasi saya ketika saya ditingkatkan ke AppCompat v23. Saya menganalisis file jar AppCompat v.23.1.1, dan melihat bahwa mereka telah menghapus direktori "internal" di dalam v7, jadi sepertinya baris instruksi Proguard seharusnya sekarang: [-tahankan kelas! Android.support.v7.view]. menu. **, android.support. ** {*;}] Saya masih belum memiliki konfirmasi dari tes pada perangkat nyata di mana masalah terjadi. Adakah yang bisa dengan alat semacam ini menguji ini? Atau mungkin penghapusan dir 'internal' sebenarnya adalah perbaikan untuk masalah ini dan kita tidak perlu lagi mengotak-atik penggantian nama kelas Proguard?
gregko
7
Tambahkan ini ke pengaturan proguard Anda, itu akan memecahkan masalah: UNTUK APPCOMPAT 23.1.1: -jaga kelas! Android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -jaga antarmuka android.support.v7. * { ; } UNTUK VERSI APPCOMPAT TUA: -jaga kelas! Android.support.v7.internal.view.menu. * MenuBuilder , android.support.v7. ** { ; } -jaga antarmuka android.support.v7. * {*; }
Andrea Bellitto
26

Seperti # 150 dari grup google mengatakan

Karena hati-hati dengan kelas -jaga! Android.support.v7.internal.view.menu. **. Ada sejumlah kelas di sana yang dirujuk dari sumber daya appcompat.

Solusi yang lebih baik adalah tambahkan baris berikut sebagai gantinya:

-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }
Pongpat
sumber
Dalam pengujian saya, berdasarkan ulasan dari file pemetaan proguard yang dihasilkan, konfigurasi proguard yang disarankan ini tidak mengakibatkan mengaburkan nama kelas MenuBuilder, meskipun itu mengaburkan SubMenuBuilder.
Andy Dennie
3
@ William Seseorang menghapusnya, tidak tahu mengapa. Bagaimanapun, inilah solusi saya: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
Andy Dennie
3
Ini bekerja untuk saya di mana -keep class !android.support.v7.internal.view.menu.**,** {*;} tidak bekerja lagi dengan v23 dari aplikasi compat .
Quentin Klein
1
-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; }sebagai jawabannya :)
Quentin Klein
2
pada 23.1.1 dukungan perpustakaan jalur paket internal telah diubah, jadi sekarang pengaturan proguard yang benar adalah: -jaga kelas! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -jaga antarmuka android.support.v7. * {*; }
Andrea Bellitto
23

Di perangkat mana Anda menghadapi masalah ini? (Samsung / HTC dll.)

Jika itu Samsung,

Berbagai ponsel Samsung termasuk versi lama dari pustaka dukungan android dalam framework atau classpath. Jika Anda menggunakan pustaka dukungan materi baru, Anda akan melihat kerusakan ini di perangkat Samsung tersebut:

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

Untuk memperbaikinya, Anda harus mengganti nama kelas itu. Cara termudah untuk melakukannya adalah dengan menjalankan proguard. Jika Anda tidak ingin mengaburkan, berikut adalah 1 liner untuk mengganti nama hanya kelas yang menyinggung:

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

Ada masalah melacak masalah ini, tetapi karena ini benar-benar bug Samsung, itu tidak akan pernah diperbaiki pada akhirnya. Satu-satunya cara untuk memperbaikinya di sisi Google / AOSP adalah mengubah nama kelas-kelas internal ini.

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

Ganesh AB - Android
sumber
Apakah Anda menggunakan proguard untuk dukungan v4?
Jared Burrows
@JaredBurrows Saya sudah mencoba dukungan v7. Tetapi untuk v4 juga akan berhasil.
Ganesh AB - Android
2
@ Android007: terima kasih telah menunjukkan bahwa solusi yang sebenarnya berfungsi. Namun, tampaknya tidak ada yang bisa menjelaskan mengapa ROM yang salah yang menyematkan Perpustakaan Dukungan Android lama di bootclasspath mereka menyebabkan pengecualian ini karena kelas "android.support.v7.internal.view.menu.MenuBuilder" yang hilang tersedia di. Apk kode DEX aplikasi yang menderita masalah ini. Apakah Anda memiliki pointer yang menjelaskan bagaimana runtime Android memuat kelas yang diambil dari file jar / dex bootclasspath dan aplikasi, tolong? Atau penjelasan yang tepat, tolong?
Édouard Mercier
@ ÉdouardMercier Maaf atas keterlambatan balasan. Saat ini saya tidak memiliki jawaban untuk pertanyaan Anda tetapi saya akan segera menghubungi Anda. :)
Ganesh AB - Android
Terima kasih @ Android007, seperti programmer mana pun, saya tidak suka banyak sihir;) Satu petunjuk: apakah bootclasspath tertanam berisi "disegel" .jar / .dex, yang mana yang bertanggung jawab atas perilaku tersebut?
Édouard Mercier
15

Masalah ini kembali AppCompat 23.1.1ketika .internalpaket dihapus dari tabung perpustakaan.

Seperti yang disarankan dalam komentar di atas (memuji orang-orang yang menyarankannya di sana), sekarang juga konfigurasi proguard harus diubah.

Agar jawaban yang disarankan di atas berfungsi kembali, coba tambahkan baris ini ke file proguard Anda:

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

Sebagai ganti dari perbaikan lama:

#FOR OLDER APPCOMPAT VERSION:
-keep class !android.support.v7.internal.view.menu.*MenuBuilder, android.support.v7.** { ; }
-keep interface android.support.v7.* { *; }
RWIL
sumber
!android.support.v7.view.menu.**lebih aman karena kelas lain seperti SubMenuBuilder
JaredBanyard
12

Menurut posting terakhir dari laporan bug, ini harus diperbaiki pada versi baru dari perpustakaan dukungan (24.0.0): https://code.google.com/p/android/issues/detail?id=78377 # c374

Seseorang bahkan mengaku sudah memperbaikinya.

Versi ini tersedia sejak bulan lalu , jadi Anda harus memperbaruinya.

pengembang android
sumber
Pengujian kami mengonfirmasi bahwa 24.0.0 memperbaiki masalah. Kami memutakhirkan perpustakaan dukungan menjadi 24.0.0 (bukan alfa), menghapus kebingungan yang kami gunakan sebagai solusi, dan melihat tidak ada kerusakan pada perangkat uji Samsung tempat kami sebelumnya melihat kerusakan.
Mark McClelland
4

Iya. Samsung sudah tahu tentang masalah ini . Saya dapat menyarankan Anda mencoba menggunakan implementasi Popup yang sama dari GitHub . Ini bukan cara terbaik, tetapi akan berhasil.

Eldar Miensutov
sumber
1
Ya saya melihat itu di forum Samsung tetapi sepertinya mereka tidak tertarik karena tidak ada perwakilan atau dukungan mereka yang menjawab.
Matt K
4

Saya mengalami masalah yang sama dengan kelas MenuBuilder ini yang tidak ditemukan dalam mode debugging USB. Aku memecahkan masalah ini dengan hanya menetapkan minifyEnabled untuk benar baik dalam rilis dan debug buildTypes blok build.gradle . seperti ini:

buildTypes {

    debug {

        minifyEnabled true
    }

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

Saya mengatur minifyEnabled menjadi true dalam tipe debug untuk mencegah aplikasi mogok melalui USB debugging ke handset langsung.

FAQi
sumber
0

Saya mengaktifkan proguard dengan properti proguard default yang disediakan dengan proyek gerhana dan masalahnya diperbaiki untuk saya. Berdasarkan beberapa komentar di sini https://code.google.com/p/android/issues/detail?id=78377 , beberapa orang mungkin harus dipaket ulang menggunakan: -repackageclasses "android.support.v7"

U2tall
sumber
Sepertinya itu tidak berfungsi untuk kebanyakan orang di forum. Sepertinya kembali ke appcompat-20 adalah opsi yang lebih andal.
Matt K
Ini diduga telah diselesaikan dalam dukungan v23.1.1
Tim Malseed
0

Saya mendapat kesalahan yang sama ketika mencoba menjalankan aplikasi 'Hello World' pada tablet Samsung Galaxy Tab 3 saya melalui Android Studio. Aplikasi akan muncul untuk diluncurkan dan kemudian akan crash secara instan dan kesalahan itu akan muncul di konsol di Android Studio. Saya melakukan pembaruan sistem pada tablet dan sekarang saya dapat menjalankan aplikasi 'Hello World' dan saya tidak mendapatkan kesalahan lagi. Saya harap ini membantu seseorang untuk menyelesaikan masalah mereka.

Catatan: Pembaruan sistem yang saya lakukan pada tablet tidak memperbarui versi OS Android, karena masih mengatakan bahwa versi tersebut 4.2.2.

JulianDavid
sumber
-4

Ubah Compile Sdk Version proyek Anda menjadi "API 18: (JellyBean)"

Defaultnya diatur ke "Lollipop

LANGKAH

  1. Klik kanan pada proyek Anda dan pilih Buka Pengaturan Modul (atau tekan F4)
  2. Pada tab properti Compiled Sdk Version
Jazib Hasan
sumber