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


170

运行Android 4.2的Samsung设备上的Android appcompat v7库存在问题。我在开发人员控制台中通过以下堆栈跟踪不断崩溃:

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)

这是CustomActivity.java的第215行:

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

崩溃来自一系列设备,但始终是三星,并且始终是Android 4.2。

快速的网络搜索使我相信很多人都遇到相同的问题,我尝试解决的一些步骤包括:

  • 检查Android项目属性,确保正确添加了appcompat库。
  • 检查Java Build Path Order和Export项目属性,确保已选中Android Dependencies和Android Private Libraries。
  • 确认该类已包含在库(android.support.v7.internal.view.menu.MenuBuilder)中。
  • 确认R.java位于android.support.v7.appcompat的gen目录中。
  • 确认AppCompat主题包含在Manifest.xml活动中。
  • 清理并重建项目。

尽管采取了这些步骤,并且尽管它可以在所有其他设备和Android版本上运行,但崩溃报告仍然会通过。


4
注意:我也曾在巴基斯坦的低端手机QMobile X25上看到过这种情况。因此,看起来其他方式与失败的Samsung ROM所采用的方法或ROM相同。
威廉

由于Google和Samsung都无法解决这个巨大的问题,因此谁能想到不涉及Proguard的解决方案(这会引发其他问题)?
清单

Google不会对此做任何事情,因为三星似乎已经进行了其他修改,导致库之间的名称冲突。Proguard避免了碰撞。在Android Issue Tracker论坛上也没有看到任何更好的解决方案。
Matt K

我也可以添加巴基斯坦以外的QMobile A290。
sstn

2
同样的问题[QMobile X30-Android 4.4.2]
shanraisshan

Answers:


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
谁能验证这个答案?我无法使用三星,并且正在使用的应用程序不再处于活动状态,因此无法对其进行测试。
Matt K

3
@JaredBurrows您不会删除该库,只是告诉Proguard默认情况下忽略它,并使用该修复程序忽略了android.support下的所有内容,但android.support.v7.internal.view.menu除外
统一

2
我已经使用该问题报告中的解决方案已有几个月了,在更新到最新的支持库和sdk 23之后突然间,我开始获取关于crashlytics的新报告:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
casolorz 2015年

3
当II升级到AppCompat v23时,该问题在我的应用程序中返回。我分析了AppCompat v.23.1.1 jar文件,发现它们已经删除了v7内部的“内部”目录,因此Proguard指令行现在应该是:[-keep class!android.support.v7.view。 menu。**,android.support。** {*;}]我仍然没有从发生问题的真实设备上的测试中得到确认。拥有这种设备的人可以测试吗?或者,也许删除“内部”目录实际上是解决该问题的方法,而我们不再需要混淆Proguard类重命名了吗?
gregko

7
添加到您的ProGuard设置,它会解决这个问题:FOR程序兼容性23.1.1:-keep类android.support.v7.view.menu *使用MenuBuilder *,** android.support.v7 {!。; } -keep接口android.support.v7。* { ; }对于较旧的程序兼容性版本:!-keep类android.support.v7.internal.view.menu *使用MenuBuilder,android.support.v7 ** { ; } -keep接口android.support.v7。* {*; }
Andrea Bellitto 2015年

26

正如来自Google Group的#150所说

因为请小心-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映射文件的检查,该建议的proguard配置不会混淆SubMenuBuilder,但不会导致混淆MenuBuilder类名。
安迪·丹妮

3
@William有人删除了它,不知道为什么。无论如何,这是我的解决方案: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
安迪·丹尼

3
这对我有用因为应用程序兼容性v23-keep class !android.support.v7.internal.view.menu.**,** {*;} 不再可用了。
昆汀·克莱恩

1
-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; }作为答案:)
昆汀·克莱因

2
在23.1.1支持库内包装路径被修改了,所以现在正确的ProGuard设置为:-keep类android.support.v7.view.menu *使用MenuBuilder *,** android.support.v7 {!。; } -keep接口android.support.v7。* {*; }
Andrea Bellitto 2015年

23

您在哪个设备上遇到此问题?(三星/ HTC等)

如果是三星

各种三星手机都包含在框架或类路径中的android支持库的旧版本中。如果您使用新的材料支持库,则会在这些三星设备上看到此崩溃:

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


您是否使用proguard for support v4?
Jared Burrows 2014年

@JaredBurrows我尝试过支持v7。但是对于v4也可以。
Ganesh AB-Android 2014年

2
@ Android007:感谢您指出实际可行的解决方法。但是,似乎没有人能够解释为什么将错误的ROM嵌入其引导类路径中的旧Android支持库会导致此异常,因为缺少可用的“ android.support.v7.internal.view.menu.MenuBuilder”类。遭受此问题的应用程序的apk DEX代码。请问您有什么指针可以解释Android运行时如何加载从bootclasspath jar / dex文件和应用程序中获取的类吗?还是有任何确切的解释?
爱德华·名士

@ÉdouardMercier抱歉,回复延迟。目前您的问题没有任何答案,但我会尽快与您联系。:)
Ganesh AB-Android

谢谢@ Android007,作为任何程序员,我都不喜欢巫术;)一个提示:嵌入式bootclasspath是否包含“密封的” .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.* { *; }

!android.support.v7.view.menu.**由于其他类,例如SubMenuBuilder
JaredBanyard

12

根据错误报告的最后几篇文章,应该在新版本的支持库(24.0.0)上解决此问题: https //code.google.com/p/android/issues/detail? =#c374

有人甚至声称已修复它。

该版本自上个月起可用,因此您应该对其进行更新。


我们的测试确认24.0.0已解决问题。我们将支持库升级到24.0.0(不是Alpha版),消除了我们作为变通办法使用的混淆方法,并且在以前看到过崩溃的Samsung测试设备上没有看到崩溃。
Mark McClelland

4

是。三星已经知道问题。我可以建议您尝试使用来自GitHub的Popup的相同实现。这不是最好的方法,但是会起作用。


1
是的,我在三星论坛上看到了这一点,但是似乎他们并不感兴趣,因为他们的代表或支持者都没有答复。
Matt K

4

我在USB调试模式下没有找到与MenuBuilder类相同的问题。我通过简单的设置解决了这个问题minifyEnabled真正的发布和调试buildTypes的build.gradle。像这样:

buildTypes {

    debug {

        minifyEnabled true
    }

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

我在调试类型中将minifyEnabled设置为true,以防止应用程序通过USB调试进入实时手机而崩溃。


0

我使用了eclipse项目提供的默认proguard属性启用了proguard,该问题已为我解决。根据此处https://code.google.com/p/android/issues/detail?id=78377上的一些评论,某些人可能必须使用以下命令重新打包:-repackageclasses“ android.support.v7”


似乎对论坛中的大多数人来说都不起作用。似乎回到appcompat-20是一个更可靠的选择。
Matt K

据说这已在支持v23.1.1中得到了解决
Tim Malseed

0

尝试通过Android Studio在我的Samsung Galaxy Tab 3平板电脑上运行“ Hello World”应用程序时遇到相同的错误。该应用程序似乎已启动,然后立即崩溃,该错误将显示在Android Studio的控制台中。我在平板电脑上进行了系统更新,现在可以运行“ Hello World”应用程序了,并且不再出现错误。我希望这可以帮助某人解决他们的问题。

注意:我在平板电脑上执行的系统更新未更新Android OS版本,因为它仍显示该版本为4.2.2。


-4

将项目的编译SDK版本更改为“ API 18:(JellyBean)”

默认设置为“棒棒糖

脚步

  1. 右键单击您的项目,然后选择“打开模块设置”(或按F4键)
  2. 在属性选项卡中,“已编译的SDK版本”
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.