appcompat-v7 v21.0.0 在搭载 Android v4.2.2 的三星设备上导致崩溃

79

我们刚刚更新了应用程序,使用appcompat-v7 support库以利用支持的操作栏和支持Material主题。现在使用v21.0.0的appcompat-v7(以及v21.0.0的support-v4),我们发现只有Samsung设备运行Android v4.2.2的情况下,在Google Play和Crashlytics中看到崩溃。这是来自Google Play的堆栈跟踪,应用程序似乎在显示和/或使无效操作栏时立即崩溃。

java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder
at android.support.v7.app.ActionBarActivityDelegateBase.initializePanelMenu(ActionBarActivityDelegateBase.java:991)
at android.support.v7.app.ActionBarActivityDelegateBase.preparePanel(ActionBarActivityDelegateBase.java:1041)
at android.support.v7.app.ActionBarActivityDelegateBase.doInvalidatePanelMenu(ActionBarActivityDelegateBase.java:1259)
at android.support.v7.app.ActionBarActivityDelegateBase.access$100(ActionBarActivityDelegateBase.java:80)
at android.support.v7.app.ActionBarActivityDelegateBase$1.run(ActionBarActivityDelegateBase.java:116)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5299)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)

其他运行v4.2.2的设备和模拟器没有出现这种情况。据我所知,许多Google应用程序已经使用这个新版本的appcompat来显示操作栏。如果这些应用程序在这些设备上没有报告崩溃,那么了解如何避免/修复这个问题会有所帮助。

我向Google报告了这个问题,但是它被关闭了,原因是这是一个开发问题。虽然我同意这可能是问题,但我想知道/如何在Samsung 4.2.2设备上使用appcompat-v7 v21.0.0而不会崩溃。

更新:看起来Google至少正在考虑可能的解决方法。详见此处


我也遇到了这个问题。应用程序正在生产中,收到来自安装有4.2.2的三星设备的崩溃报告。 - Martin Vandzura
1
我在我的操作栏中也没有旋转器,并且从运行Android 4.2.2的非三星设备(Qmobile I9和Wiko(未知型号))中获取此信息。 - Jürgen 'Kashban' Wahlmann
你尝试过清理项目吗?或者检查一下库是否真的插入到了项目的属性>Android中。 - ralphgabb
1
@Devashish:第二个答案中的proguard解决方案对我有用。我针对受appthwack.com影响的三星设备进行了测试,在应用proguard配置之后,我不再收到任何错误信息。 - Jürgen 'Kashban' Wahlmann
显示剩余3条评论
9个回答

15

我在这里找到了正确的解决方案:https://dev59.com/42Af5IYBdhLWcg3wSRHi#26641388

通过使用

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

而不是

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

1
我认为你可以使用“-keepnames”而不是“-keep”来节省更多的空间。 - Justin
正如在 https://code.google.com/p/android/issues/detail?id=78377 的讨论中所提到的,使用这种特定的解决方案可能会由于 appcompat 库中的资源引用而导致问题。然而,对于我们的特定应用程序来说,这一直在起作用,因此我将此答案标记为已接受。 - Erik Pedersen
我应该在哪里写这行代码? - Bugs Happen
@BugsHappen,这将放在你的Gradle构建文件中。你可以在这里阅读更多关于ProGuard的信息:http://developer.android.com/tools/help/proguard.html - Dick Lucas

7
根据来自https://code.google.com/p/android/issues/detail?id=78377的 #150 评论,需要小心使用-keep class !android.support.v7.internal.view.menu.**。在那里有许多从appcompat的资源中引用的类。更好的解决方案是添加以下行:
-keep class !android.support.v7.internal.view.menu.MenuBuilder, !android.support.v7.internal.view.menu.SubMenuBuilder, android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }

在我的测试中,基于对生成的Proguard映射文件的审查,这个建议的Proguard配置并没有导致MenuBuilder类名被混淆,尽管它确实混淆了SubMenuBuilder。 - Andy Dennie
搞定了,看我的答案。 - Andy Dennie
嘿,安迪,我遇到了同样的问题,MenuBuilder没有混淆,但其他的都有,你能告诉我你是怎么解决的吗?谢谢。 - Qing

6
自从Appcompat 23.1.1版本开始,AppCompat jar包中的.internal包已被移除。
使用Proguard更新修复方案:
#FOR APPCOMPAT 23.1.1:
-keep class !android.support.v7.view.menu.*MenuBuilder*, android.support.v7.** { *; }
-keep interface android.support.v7.* { *; }

2

1
如果有人对不使用progaurd的解决方案感兴趣。
请阅读链接,我已经在我的一个应用程序中尝试过这个方法,它在onCreate()中的setSupportActionBar(toolbar)时出现了异常。
很简单,只需在调用周围添加try catch块即可。
try {

 setSupportActionBar(toolbar);

} catch (Throwable t) {

 // WTF SAMSUNG!

}

0

我在Tecno P9上遇到了同样的问题,但是在使用了构建工具24和支持库24.2.0之后,问题得到了解决。


-2

将您的项目的编译SDK版本更改为“API 18:(果冻豆)”

默认设置为“棒棒糖”

到目前为止,这解决了我的Qmobile i9问题

步骤

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

-3

替换

public class class_name extends AppCompatActivity
{

.........

}

使用

public class class_name extends Activity
{

.........

}

这对我很有帮助。


请不要在同一个问题上重复回答。 - Sufian

-3

将AppCompatActivity替换为Activity

这对我很有帮助。


廉价的解决方案。他可能正在使用AppCompat,因为他想支持API < 11或其他什么。这将破坏这个想法。 - Sufian
我认为,如果有人同意Sufian所说的原因,这篇文章可能会被踩得够惨的。但是并不至于被删除。 - Gangnus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接