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


170

Існує проблема з бібліотекою Android appcompat v7 на пристроях Samsung, на яких працює Android 4.2. У моїй консолі розробника я постійно отримую збої із таким слідом стека:

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)

Це рядок 215 CustomActivity.java:

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

Збої відбуваються з масиву пристроїв, але завжди Samsung, і завжди Android 4.2.

Швидкий пошук в Інтернеті змушує мене повірити, що багато людей мають одне і те ж питання, і деякі кроки, які я намагався вирішити, це:

  • Перевірте властивості проекту Android, переконайтеся, що бібліотека додатків додана належним чином.
  • Перевірте властивості замовлення та експорту проектів Java Build Path, переконайтеся, що встановлені залежності Android та приватні бібліотеки Android.
  • Переконайтесь, що клас включений у бібліотеку (android.support.v7.internal.view.menu.MenuBuilder).
  • Підтвердити R.java розміщено в каталозі gen для android.support.v7.appcompat.
  • Переконайтесь, що тема AppCompat включена в діяльність Manifest.xml.
  • Очистити та відновити проект.

Незважаючи на ці кроки, і незважаючи на те, що він працює на всіх інших пристроях та версіях Android, звіти про аварійні ситуації все ще надходять.


4
Примітка. Я також бачив, що це відбувається на QMobile X25, який виходить із Пакистану. Таким чином, схоже, що устриці застосовують той самий підхід або той же ПЗУ, що і невдалий ПЗУ Samsung.
Вільям

Оскільки і Google, і Samsung не допомагають вирішити цю ВЕЛИЧНУ проблему, чи може хтось подумати про рішення, яке не стосується Proguard (яке викликає інші проблеми)?
контрольний лист

Google не збирається нічого з цим робити, оскільки, здається, саме Samsung вніс додаткові зміни, спричинивши зіткнення імен між бібліотеками. Proguard уникає зіткнення. Кращі рішення на форумі Android Issue Tracker також не бачили .
Метт К

Я можу додати QMobile A290 і з Пакистану.
sstn

2
той же випуск [QMobile X30 - Android 4.4.2]
shanraisshan

Відповіді:


100

Редагувати:

Для мене рішення було (Використання Proguard) замінити це:

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

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

з цим:

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

Кредит належить групі Google, № 138 .

Стара відповідь (Тимчасове вирішення): Це трапляється в проекті, коли я використовую спінер у ActionBar. Моїм рішенням було перевірити ці умови та змінити потік додатків:

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

Потім у методі onCreate діяльності:

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

Як зазначалося, це не остаточне рішення, це лише спосіб дозволити користувачам мати доступ до обмежених функціональних можливостей, тоді як знайдеться більш постійне рішення.


2
Чи може хтось ще підтвердити цю відповідь? У мене немає доступу до Samsung, і додаток, над яким я працював, більше не активний, тому не можу його перевірити.
Метт К

3
@JaredBurrows Ви не видаляєте бібліотеку, ви просто скажете proguard ігнорувати її за замовчуванням, з виправленням ви ігноруєте все під android.support, за винятком android.support.v7.internal.view.menu
об'єднайте

2
Я вже кілька місяців використовую рішення з цього звіту про проблему, і раптом після оновлення до останніх бібліотек підтримки та sdk 23 Я почав отримувати цей новий звіт про катастрофіку:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
casolorz

3
Проблема повернулась у моєму додатку, коли я оновив програму AppCompat v23. Я проаналізував jar-файл AppCompat v.23.1.1, і побачив, що вони видалили "внутрішній" каталог всередині v7, тому, здається, рядок інструкцій Proguard має бути зараз: [-keep class! Android.support.v7.view. меню. **, android.support. ** {*;}] У мене ще немає підтвердження тестів на реальному пристрої, де сталася проблема. Чи може хтось із таким пристроєм перевірити це? Чи, можливо, видалення "внутрішнього" режиму - насправді виправлення проблеми, і нам більше не потрібно возитися з перейменуванням класу Proguard?
gregko

7
Додайте це до налаштувань Proguard, воно вирішить проблему: ДЛЯ APPCOMPAT 23.1.1: -keep class! Android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -інтерфейс android.support.v7. * { ; } ДЛЯ СТАРОЇ ВЕРСІЇ ЗАПИТУВАННЯ: -keep class! Android.support.v7.internal.view.menu. * MenuBuilder , android.support.v7. ** { ; } -інтерфейс android.support.v7. * {*; }
Андреа Беллітто

26

Як # 150 з Google груп сказав

Тому що обережно з класом -keep! Android.support.v7.internal.view.menu. **. У ньому є ряд класів, на які посилаються ресурси ресурсів appcompat.

Краще рішення - замість цього додати наступні рядки:

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

У моїх тестах, заснованих на огляді сгенерованого файлу картографічного захисту, цей запропонований конфігурація proguard не призводить до оскорблення імені класу MenuBuilder, хоча він придушує SubMenuBuilder.
Енді Денні

3
@William Хтось його видалив, не знаю чому. У всякому разі, ось моє рішення: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
Енді Денні

3
Це працює для мене , де -keep class !android.support.v7.internal.view.menu.**,** {*;} не працював більше з v23 з додатка Compat .
Квентін Кляйн

1
-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; }як відповідь :)
Квентін Кляйн

2
у бібліотеці підтримки 23.1.1 внутрішні шляхи до пакетів були змінені, тому тепер правильним параметром захисту є: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -інтерфейс android.support.v7. * {*; }
Андреа Беллітто

23

На якому пристрої ви стикаєтеся з цією проблемою? (Samsung / HTC тощо)

Якщо це Samsung,

Різні телефони Samsung включають в себе старіші версії бібліотеки підтримки для Android в рамках або в класі. Якщо ви використовуєте нову бібліотеку підтримки матеріалів, ви побачите цей збій на цих пристроях Samsung:

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

Щоб виправити це, потрібно перейменувати цей клас. Найпростіше це зробити, запустивши proguard. Якщо ви не хочете ошукати, ось 1 лайнер, щоб перейменувати лише класи, які порушують право:

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

Існує проблема, яка відстежує цю проблему, але оскільки це справді помилка Samsung, вона ніколи не виправляється на їх шляху. Єдиний спосіб виправити це на стороні Google / AOSP - це перейменування цих внутрішніх класів.

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


Ви використовуєте proguard для підтримки v4?
Джаред Берроуз

@JaredBurrows Я намагався підтримати v7. Але для v4 також він буде працювати.
Ganesh AB - Android

2
@ Android007: дякую за вказівку на ту роботу, яка насправді працює. Однак, схоже, ніхто не може пояснити, чому несправні ПЗУ, що вбудовують стару Бібліотеку підтримки Android у свій завантажувальний приклад, викликають цей виняток, оскільки відсутній клас "android.support.v7.internal.view.menu.MenuBuilder" доступний у. apk код DEX програми, яка страждає від цього питання. Чи є у вас під рукою якийсь вказівник, який пояснює, як програма Android завантажує класи, взяті з файлів jar / dex завантажувального завантажувача та програми, будь ласка? Або будь-яке точне пояснення, будь ласка?
Едуар Мерсьє

@ ÉdouardMercier Вибачте за пізню відповідь. На даний момент у мене немає відповіді на ваше запитання, але я незабаром з вами повернусь. :)
Ganesh AB - Android

Дякую @ Android007, як будь-який програміст, мені не дуже подобається чаклунство;) Один натяк: чи вбудований завантажувальний пристрій міститиме "запечатаний" .jar / .dex, який би пояснював поведінку?
Едуард Мерсьє

15

Ця проблема повернулася AppCompat 23.1.1там, де .internalпакет було вилучено з банку бібліотеки.

Як було запропоновано в коментарях вище (кредити для людей, які його там запропонували), тепер також конфігурація proguard має змінитися.

Щоб відповідь, запропоновану вище, знову працювала, спробуйте додати ці рядки до файлів-захисників:

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

Замість старого виправлення:

#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.**безпечніше через інші класи, такі як SubMenuBuilder
JaredBanyard

12

Відповідно до останніх публікацій звіту про помилки, це має бути зафіксовано у новій версії бібліотеки підтримки (24.0.0): https://code.google.com/p/android/isissue/detail?id=78377 # c374

Хтось навіть стверджував, що це виправили.

Ця версія доступна з минулого місяця , тому слід оновити її.


Наше тестування підтверджує, що проблема усуває 24.0.0. Ми оновили підтримку бібліотеки до 24.0.0 (не альфа), видалили неясність, яку ми використовували як спосіб вирішення, і не побачили збоїв на тестовому пристрої Samsung, де раніше ми бачили збій.
Марк МакКлелленд

4

Так. Samsung вже знає про цю проблему. Я можу запропонувати вам спробувати використовувати таку ж реалізацію Popup від GitHub . Це не найкращий спосіб, але це будуть роботи.


1
Так, я бачив це на форумі Samsung, але, схоже, вони не зацікавлені, оскільки ніхто з їх представників чи підтримка не відповів.
Метт К

4

У мене була така ж проблема цього класу MenuBuilder, який не знайдено в режимі налагодження USB. Я вирішив цю проблему, просто встановивши minifyEnabled на істину як у блоці випуску, так і у відладці buildTypes build.gradle . подобається це:

buildTypes {

    debug {

        minifyEnabled true
    }

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

Я встановив minifyEnabled на true у типі налагодження, щоб уникнути збоїв програми через USB-налагодження на живій трубці.


0

Я увімкнув proguard із властивостями proguard за замовчуванням, наданими проектом eclipse, і для мене була вирішена проблема. На основі деяких коментарів тут https://code.google.com/p/android/isissue/detail?id=78377 деяким людям, можливо, доведеться перепакувати, використовуючи: -repackageclasses "android.support.v7"


Схоже, це не працює для більшості людей на форумі. Схоже, повернення до appcompat-20 є більш надійним варіантом.
Метт К

Це нібито було вирішено у підтримці v23.1.1
Тім Малсід

0

Я отримав таку ж помилку, коли намагався запустити додаток 'Hello World' на своєму планшеті Samsung Galaxy Tab 3 через Android Studio. Здається, додаток запуститься, і тоді воно миттєво вийде з ладу, і ця помилка з’явиться на консолі в Android Studio. Я зробив оновлення системи на планшеті, і тепер я можу запустити додаток "Hello World", і я більше не отримую помилки. Сподіваюся, це допоможе комусь вирішити їхню проблему.

Примітка. Оновлення системи, яке я виконував на планшеті, не оновлювало версію ОС Android, оскільки вона все ще говорить про те, що версія 4.2.2.


-4

Змініть версію проекту Compile Sdk свого проекту на "API 18: (JellyBean)"

За замовчуванням встановлено "Lollipop

КРОКИ

  1. Клацніть правою кнопкою миші на вашому проекті та виберіть Відкрити налаштування модуля (або натисніть F4)
  2. На вкладці властивостей Складена версія SDK
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.