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

Posted

技术标签:

【中文标题】NoClassDefFoundError:android.support.v7.internal.view.menu.MenuBuilder【英文标题】:NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder 【发布时间】:2014-09-08 16:21:06 【问题描述】:

运行 android 4.2 的三星设备上的 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 版本,但仍会收到崩溃报告。

【问题讨论】:

注意:我在 QMobile X25 上也看到过这种情况,这是一款来自巴基斯坦的低端手机。所以看起来其他人采取了与失败的三星 ROM 相同的方法或相同的 ROM。 既然谷歌和三星都没有帮助解决这个巨大的问题,谁能想到不涉及 Proguard 的解决方案(这会引发其他问题)? Google 不会对此采取任何行动,因为三星似乎做了额外的修改,导致库之间的名称冲突。 Proguard 避免了碰撞。在Android Issue Tracker forum 上也没有看到任何更好的解决方案。 我也可以在巴基斯坦以外添加 QMobile A290。 同样的问题 [QMobile X30 - Android 4.4.2] 【参考方案1】:

编辑:

对我有用的解决方案是(使用 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 group, #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");

然后在activity的onCreate方法中:

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

正如所指出的,这不是一个确定的解决方案,它只是一种允许用户在找到更永久的解决方案时访问有限功能的方法。

【讨论】:

其他人可以验证这个答案吗?我无法访问三星,并且我正在开发的应用程序不再处于活动状态,因此我无法对其进行测试。 @JaredBurrows 你没有删除这个库,你只是告诉proguard默认忽略它,修复后你会忽略android.support下的所有内容,除了android.support.v7.internal.view。菜单 几个月来我一直在使用该问题报告中的解决方案,在更新到最新的支持库和 sdk 23 后突然间我开始收到有关 crashlytics 的新报告:@987654326 @ 当 II 升级到 AppCompat v23 时,我的应用程序中返回了该问题。我分析了 AppCompat v.23.1.1 jar 文件,发现他们已经删除了 v7 中的“内部”目录,所以看起来 Proguard 指令行现在应该是:[ -keep class !android.support.v7.view。 menu.**,android.support.** *; ] 我仍然没有从发生问题的真实设备上的测试中得到确认。有这种设备的人可以测试一下吗?或者也许删除“内部”目录实际上是解决问题的方法,我们不需要再搞乱 Proguard 类的重命名了? 将此添加到您的 proguard 设置中,它将解决问题: FOR APPCOMPAT 23.1.1: -keep class !android.support.v7.view.menu.*MenuBuilder*, android.support.v7 .** ; -keep interface android.support.v7.* ;对于旧的 APPCOMPAT 版本:-keep class !android.support.v7.internal.view.menu.*MenuBuilder, android.support.v7.** ; -keep interface android.support.v7.* *; 【参考方案2】:

正如#150 from google groups所说的

因为小心使用 -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 配置不会导致混淆 MenuBuilder 类名,尽管它确实混淆了 SubMenuBuilder。 @William 有人删除了它,不知道为什么。无论如何,这是我的解决方案:-keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** *; 这对我有用,因为 -keep class !android.support.v7.internal.view.menu.**,** *; 不再适用于 app compatv23 -keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** *; -keep interface android.support.v7.** *; 作为答案:) 在 23.1.1 支持库上修改了内部包路径,所以现在正确的 proguard 设置是:-keep class !android.support.v7.view.menu.*MenuBuilder*, android.support .v7.** ; -keep interface android.support.v7.* *; 【参考方案3】:

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

如果是三星,

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

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

要解决此问题,您必须重命名该类。最简单的方法是运行 proguard。如果您不想混淆,这里有一个 1 行来重命名有问题的类:

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

有一个问题跟踪此问题,但由于它确实是三星的错误,因此永远不会得到解决。在 Google/AOSP 方面修复它的唯一方法是重命名这些内部类。

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

【讨论】:

你使用 proguard 来支持 v4 吗? @JaredBurrows 我已尝试支持 v7。但对于 v4 也可以。 @Android007:感谢您指出实际可行的解决方法。但是,似乎没有人能够解释为什么在其引导类路径中嵌入旧的 Android 支持库的错误 ROM 会导致此异常,因为 .受此问题影响的应用程序的 apk DEX 代码。请问您手头有什么指针可以解释 Android 运行时如何加载从 bootclasspath jar/dex 文件和应用程序中获取的类吗?或者任何准确的解释,好吗? 谢谢@Android007,作为任何程序员,我不太喜欢巫术;)一个提示:嵌入式引导类路径是否包含“密封的”.jar/.dex,这会导致这种行为? @Android007 答案中的解决方案是我找到的最好的解决方案。其他解决方案导致了阻止应用构建的奇怪问题。【参考方案4】:

此问题在 AppCompat 23.1.1 中返回,其中 .internal 包已从库 jar 中删除。

正如上面 cmets 中所建议的(感谢那里提出建议的人),现在 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 等其他类【参考方案5】:

根据错误报告的最后一篇文章,这应该在新版本的支持库 (24.0.0) 上得到修复: https://code.google.com/p/android/issues/detail?id=78377#c374

有人 even claimed 修复了它。

此版本可用since last month,因此您应该更新到它。

【讨论】:

我们的测试确认 24.0.0 解决了这个问题。我们将支持库升级到 24.0.0(不是 alpha),删除了我们作为解决方法使用的混淆,并且在我们之前看到崩溃的三星测试设备上没有看到崩溃。【参考方案6】:

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

【讨论】:

是的,我在三星论坛上看到了,但他们似乎不感兴趣,因为他们的代表或支持人员都没有回复。【参考方案7】:

我遇到了在 USB 调试模式下找不到这个 MenuBuilder 类的相同问题。我通过在 build.gradle 的发布和调试 buildTypes 块中简单地将 minifyEnabled 设置为 true 解决了这个问题.像这样:

buildTypes 

    debug 

        minifyEnabled true
    

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

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

【讨论】:

【参考方案8】:

我使用 Eclipse 项目提供的默认 proguard 属性启用了 proguard,问题已为我解决。根据https://code.google.com/p/android/issues/detail?id=78377 这里的一些 cmets,有些人可能不得不使用以下方法重新打包: -repackageclasses“android.support.v7”

【讨论】:

看起来这对论坛中的大多数人都不起作用。似乎回到 appcompat-20 是一个更可靠的选择。 这应该在支持 v23.1.1 中得到解决【参考方案9】:

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

注意:我在平板上执行的系统更新并没有更新Android OS版本,因为它仍然说版本是4.2.2。

【讨论】:

【参考方案10】:

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

默认设置为"Lollipop

步骤

    右键单击您的项目并选择打开模块设置(或按 F4) 在属性选项卡中编译的 SDK 版本

【讨论】:

以上是关于NoClassDefFoundError:android.support.v7.internal.view.menu.MenuBuilder的主要内容,如果未能解决你的问题,请参考以下文章

NoClassDefFoundError

ANDR-PERF tryGetService 失败; SELinux

Androidx 迁移:NoClassDefFoundError

关于NoClassDefFoundError错误

毕业:java.lang.NoClassDefFoundError

Hive 安装问题:NoClassDefFoundError