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, убедитесь, что библиотека appcompat добавлена ​​правильно.
  • Проверьте свойства порядка и порядка экспорта Java Build Path, убедитесь, что установлены зависимости Android и Android Private Libraries.
  • Убедитесь, что класс включен в библиотеку (android.support.v7.internal.view.menu.MenuBuilder).
  • Подтвердите, что R.java находится в директории gen для android.support.v7.appcompat.
  • Убедитесь, что тема AppCompat включена в действие Manifest.xml.
  • Очистить и перестроить проект.

Несмотря на эти шаги, и несмотря на то, что он работает на всех других устройствах и версиях Android, отчеты о сбоях все еще приходят.

Мэтт К
источник
4
Примечание: я также видел, что это происходит на QMobile X25, который является телефоном низкого уровня из Пакистана. Таким образом, похоже, что другие используют тот же подход или тот же ROM, что и вышедший из строя Samsung ROM.
Уильям
Поскольку и Google, и Samsung не помогают в решении этой ОГРОМНОЙ проблемы, может ли кто-нибудь придумать решение, не связанное с Proguard (которое вызывает другие проблемы)?
контрольный список
Google не собирается ничего с этим делать, поскольку Samsung, похоже, внесла дополнительные изменения, вызвав конфликт имен между библиотеками. Proguard избегает столкновения. Лучших решений на форуме Android Issue Tracker тоже не было.
Мэтт К
Я могу добавить QMobile A290, также из Пакистана.
sstn
2
та же проблема [QMobile X30 - Android 4.4.2]
Шанрайссан

Ответы:

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 .

Старый ответ (Временное решение): это происходит в проекте, где я использую счетчик в панели действий. Мое решение состояло в том, чтобы проверить эти условия и изменить поток приложения:

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. menu. **, android.support. ** {*;}] У меня все еще нет подтверждения от испытаний на реальном устройстве, где возникла проблема. Может ли кто-нибудь с таким устройством проверить это? Или, может быть, удаление «внутреннего» каталога на самом деле является решением проблемы, и нам больше не нужно возиться с переименованием класса Proguard?
Грегко
7
Добавьте это в настройки Proguard, это решит проблему: ДЛЯ APPCOMPAT 23.1.1: -keep class! Android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -поддерживать интерфейс android.support.v7. * { ; } ДЛЯ СТАРЫХ ВЕРСИЙ APPCOMPAT: -поддержите класс! 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.** { *; }
Pongpat
источник
В моих тестах, основанных на обзоре сгенерированного файла сопоставления proguard, эта предложенная конфигурация 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 внутренние пути пакетов были изменены, поэтому теперь правильная настройка proguard: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -поддерживать интерфейс android.support.v7. * {*; }
Андреа Беллитто
23

На каком устройстве вы столкнулись с этой проблемой? (Samsung / HTC и т. Д.)

Если это Samsung,

Различные телефоны Samsung включены старые версии библиотеки поддержки Android в рамках или classpath. Если вы используете новую библиотеку поддержки материалов, вы увидите этот сбой на следующих устройствах 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/issues/detail?id=78377

Ганеш А.Б. - Android
источник
Вы используете proguard для поддержки v4?
Джаред Берроуз
@JaredBurrows Я пытался за поддержку v7. Но для v4 это тоже будет работать.
Ганеш А.Б. - Android
2
@ Android007: спасибо за указание на то, что действительно работает. Однако никто не может объяснить, почему неисправные ПЗУ, встраивающие старую библиотеку поддержки Android в их путь загрузки, вызывают это исключение, поскольку отсутствующий класс «android.support.v7.internal.view.menu.MenuBuilder» доступен в. apk DEX-код приложения, которое страдает от этой проблемы. Не могли бы вы иметь под рукой указатель, который объясняет, как среда выполнения Android загружает классы, взятые из файлов jar / dex bootclasspath и приложения, пожалуйста? Или любое точное объяснение, пожалуйста?
Эдуард Мерсье
@ ÉdouardMercier Извините за поздний ответ. В настоящее время у меня нет ответа на ваш вопрос, но я скоро перезвоню. :)
Ганеш А.Б. - Android от
Спасибо @ Android007, как любой программист, мне не очень нравится колдовство;) Один намек: будет ли встроенный путь к загрузочной логике содержать «загерметизированный» .jar / .dex, что будет объяснять поведение?
Эдуард Мерсье
15

Эта проблема вернулась, AppCompat 23.1.1когда .internalпакет был удален из библиотеки JAR.

Как указано в комментариях выше (благодарность тем, кто предложил это там), теперь также должна измениться конфигурация proguard.

Чтобы ответ, предложенный выше, снова работал, попробуйте добавить эти строки в ваши файлы 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.* { *; }
RWIL
источник
!android.support.v7.view.menu.**безопаснее из-за других классов, таких как SubMenuBuilder
JaredBanyard
12

Согласно последним сообщениям об ошибке, это следует исправить в новой версии библиотеки поддержки (24.0.0): https://code.google.com/p/android/issues/detail?id=78377. # c374

Кто-то даже утверждал, что это исправило это.

Эта версия доступна с прошлого месяца , поэтому вы должны обновить ее.

разработчик Android
источник
Наше тестирование подтверждает, что 24.0.0 решает проблему. Мы обновили библиотеку поддержки до 24.0.0 (не альфа), удалили обфускацию, которую мы использовали в качестве обходного пути, и не увидели сбоев на тестовом устройстве Samsung, где мы ранее видели сбой.
Марк Макклелланд,
4

Да. Samsung уже знает об этой проблеме. Я могу предложить вам попробовать использовать ту же реализацию Popup от GitHub . Это не лучший способ, но будет работать.

Эльдар Миенсутов
источник
1
Да, я видел это на форуме Samsung, но не похоже, что они заинтересованы, так как никто из их представителей или поддержки не ответил.
Мэтт К
4

У меня была та же проблема этого класса MenuBuilder, не найденного в режиме отладки USB. Я решил эту проблему, просто установив для minifyEnabled значение true в блоке release и debug buildTypes файла build.gradle . как это:

buildTypes {

    debug {

        minifyEnabled true
    }

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

Я установил для minifyEnabled значение true в типе отладки, чтобы предотвратить сбой приложения через отладку по USB на живой телефон.

FAQi
источник
0

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

u2tall
источник
Похоже, это не работает для большинства людей на форуме. Похоже, что возврат к appcompat-20 - более надежный вариант.
Мэтт К
Это якобы было решено в поддержке v23.1.1
Тим Malseed
0

Я получил ту же ошибку при попытке запустить приложение «Hello World» на своем планшете Samsung Galaxy Tab 3 через Android Studio. Приложение может запуститься, а затем мгновенно завершить работу, и эта ошибка отобразится в консоли в Android Studio. Я выполнил обновление системы на планшете, и теперь я могу запустить приложение «Hello World», и я больше не получаю сообщение об ошибке. Я надеюсь, что это поможет кому-то решить их проблему.

Примечание. Обновление системы, которое я выполнил на планшете, не обновило версию ОС Android, поскольку в ней по-прежнему указывается версия 4.2.2.

JulianDavid
источник
-4

Измените версию вашего проекта Compile Sdk на «API 18: (JellyBean)»

По умолчанию установлено значение «Lollipop»

ШАГОВ

  1. Щелкните правой кнопкой мыши по вашему проекту и выберите «Открыть настройки модуля» (или нажмите F4).
  2. На вкладке свойств Скомпилированная версия SDK
Джазиб Хасан
источник