170

There is an issue with the Android appcompat v7 library on Samsung devices running Android 4.2. I keep getting crashes with the following stack trace in my Developer Console:

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)

This is line 215 of CustomActivity.java:

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

The crashes come from an array of devices, but always Samsung, and always Android 4.2.

A quick web search leads me to believe that many people have the same issue, some of the steps I have tried to solve the issue are:

  • Check the Android project properties, make sure the appcompat library is added properly.
  • Check the Java Build Path Order and Export project properties, make sure Android Dependencies and Android Private Libraries is checked.
  • Confirm the class is included in the library (android.support.v7.internal.view.menu.MenuBuilder).
  • Confirm R.java is located in gen directory for android.support.v7.appcompat.
  • Confirm the AppCompat theme is included in the Manifest.xml activity.
  • Clean and rebuild project.

Despite these steps, and despite it working on all other devices and Android versions the crash reports still come through.

Matt K
  • 6,620
  • 3
  • 38
  • 60
  • 4
    Note: I have also seen this occur on the QMobile X25 which a low end phone out of Pakistan. So it looks like oythers have take the same approach or same ROM as the failed Samsung ROM. – William May 01 '15 at 22:31
  • Since both Google and Samsung are not helpful in resolving this HUGE issue, can anyone think of a solution that does not involve Proguard (which raises other issues)? – checklist Jul 28 '15 at 10:02
  • Google isn't going to do anything about it since it's Samsung that seems to have made additional modifications causing a name collision between libraries. Proguard avoids the collision. Haven't seen any better solutions on the [Android Issue Tracker forum](https://code.google.com/p/android/issues/detail?id=78377) either. – Matt K Jul 28 '15 at 20:46
  • I can add a QMobile A290, out of Pakistan as well. – sstn May 17 '16 at 09:41
  • 2
    same issue [QMobile X30 - Android 4.4.2] – shanraisshan Sep 01 '16 at 16:43

10 Answers10

100

EDIT:

The solution that worked for me was (Using Proguard) to replace this:

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

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

with this:

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

Credit goes to the google group, #138.

Old answer (Temporary Workaround): It happens in a project where I use an spinner in the ActionBar. My solution was to check for those conditions and change the app flow:

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

Then in the activity's onCreate method:

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

As pointed out this is not a definitive solution, it is just a way to allow users to have access to limited functionality while a more permanent solution is found.

schnatterer
  • 7,525
  • 7
  • 61
  • 80
unify
  • 6,161
  • 4
  • 33
  • 34
  • +1 to you. Obviously not ideal, but it works. I'm implementing a similar solution until a permanent fix is in place (not holding my breath). – Bryan Dunlap Oct 30 '14 at 18:38
  • What do you mean by "changing the app flow"? Remove the ActionBar? – Florian Barth Nov 03 '14 at 13:32
  • Updated my answer, yes, basically I made a (limited-functionality) version with no ActionBar in the meantime – unify Nov 03 '14 at 16:33
  • 2
    Can anyone else verify this answer? I don't have access to a Samsung and the app I was working on is no longer active so I can't test it out. – Matt K Dec 01 '14 at 15:49
  • 3
    @JaredBurrows You don't remove the library, you just tell proguard to ignore it by default, with the fix you ignore everything under android.support except for android.support.v7.internal.view.menu – unify Dec 15 '14 at 18:50
  • @unify Alright, I am just trying to get some clarity. Thank you! – Jared Burrows Dec 15 '14 at 19:58
  • @unify I'm trying to apply the proguard solution. Is it correct that the goal is to obfuscate the *class name* of the MenuBuilder class. I've tried to apply it, but only the members end up obfuscated, not the class name. – Dave Cameron Dec 16 '14 at 19:23
  • @DaveCameron Yes, the goal is to rename the classes under android.support.v7.internal.view.menu. Make sure you don't have conflicting rules in your script – unify Dec 22 '14 at 18:15
  • If no one objects I'm going to mark this as the solution, since I can't test it myself at the moment. – Matt K Jan 09 '15 at 15:06
  • Does this work if you use the v7 support library from maven? I don't see any reference to android.support.v7 in my mapping.txt. Thus this solution has no effect... – guillaume-tgl Mar 24 '15 at 10:16
  • While this obfuscates the MenuBuilder and SubMenuBuidler classes, it also obfuscates ActionMenuItemView which is used by the Toolbar resources in appcompat-v7:21 so you get XML inflation and ClassNotFoundErrors – William May 09 '15 at 08:17
  • @unify I hate creating new questions, especially when this is exactly the problem I'm having. But none of these suggestions has worked for me, I've tried both the workaround as well as the proguard solution. Is there a way to ensure that the proguard script is running as intended? Why would it not be working? – akousmata Jul 30 '15 at 22:15
  • Ok, for those who are trying to use this solution, while in debug mode, you must add `minify true`, `proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'` , and `zipAlignEnabled true` to the `debug` build type in your gradle file. This will allow you to at least test locally prior to deploying although it is admittedly harder to debug. – akousmata Aug 03 '15 at 14:45
  • i have that kind of android phone which have the same samsung ROM which have this issue, it crashes when i start my app upon calling the setSupportedToolbar() method. I am trying to create Slide able Tabs. So how come apps like Whatsapp have tabs and don't crash on my phone? – Sireiz Aug 06 '15 at 19:39
  • I actually got this error on a non-Samsung device: "QMobile i9" – android developer Oct 10 '15 at 12:40
  • 2
    I've been using a solution from that issue report for months now and all of the sudden after updating to the latest support libraries and sdk 23 I've started getting this new report on crashlytics: `java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i` – casolorz Oct 15 '15 at 17:49
  • according to the end of https://code.google.com/p/android/issues/detail?id=78377, this issue seems to be resurfacing in SDK23 – Adam J Oct 15 '15 at 21:44
  • @AdamJ this has supposedly been resolved in support v23.1.1 – Tim Malseed Nov 12 '15 at 22:17
  • 3
    The issue returned in my app when II upgraded to AppCompat v23. I analyzed the AppCompat v.23.1.1 jar file, and see that they have removed the "internal" directory inside v7, so it seems the Proguard instruction line should be now: [ -keep class !android.support.v7.view.menu.**,android.support.** {*;} ] I still don't have a confirmation from tests on a real device where the problem happened. Could anyone with such a device test this? Or maybe the removal of 'internal' dir is actually the fix for the issue and we don't need to mess with Proguard class renaming anymore? – gregko Nov 28 '15 at 20:56
  • 7
    Add this to your proguard settings, it will solve the problem: 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.** { *; } – Andrea Bellitto Dec 16 '15 at 10:18
  • @AndreaBellitto Why do we still need to add such things? – android developer Feb 07 '16 at 10:07
  • 2
    @AndreaBellitto I think you missed a "\*" in your code. It's supposed to be : -keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { \*; } -keep interface android.support.v7.** { \*; } – android developer Feb 07 '16 at 11:33
  • Chris Banes recently commented that the next support library release will include a change that should fix the underlying problem, obviating the need for ProGuard: https://code.google.com/p/android/issues/detail?id=78377#c336 ... Fingers crossed! – Mark McClelland Feb 24 '16 at 05:54
  • 1
    @markproxy later in those comments people are saying it's fixed in v24-alpha but he won't commit to saying that the change will actually make it into that version or that it will indeed fix the issue if it does. – akousmata Jun 01 '16 at 15:45
  • In my app I am accessing `MenuBuilder` with reflection so I need to tell Proguard to keep it. Is there a known solution for this case? I can try `isSamsung_4_2_2()` but I don't think that'll work because I still have to keep the class in proguard – yuval Jul 01 '16 at 21:18
  • @unify It has not helped me. I am getting the same crashes. Can you help me. I have written these lines in proguard -keep class !android.support.v7.internal.view.menu.**,android.support.** {*;} -keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; } – Gaurav Arora Jul 06 '16 at 10:54
  • 2
    @akousmata Our testing confirms that the root issue was fixed in support lib 24.0.0. (The official release, not just alpha.) We upgraded to 24.0.0, removed the ProGuard obfuscation workaround, tested on a Samsung device where we previously saw the crash, and we no longer see it. – Mark McClelland Aug 01 '16 at 21:12
  • If others can confirm that support lib 24.0.0 fixes the crash (as it did for me), please upvote http://stackoverflow.com/a/38301963/315702 – Mark McClelland Aug 01 '16 at 21:15
  • That issue also happened to me with a Samsung tablet with Android 5.1.1 and supportLibraryVersion = '27.0.2', and your solution was the only working one. Thank you very much @unify – YawaraNes Jan 16 '18 at 13:34
  • damn guys! the exclamation mark before the package name tell Proguard to KEEP everything except `android.support.v7.internal.view.menu.**,android.support.** {*;}` That mean *no more code obuscation"...that's crazy XD – GDM Oct 04 '18 at 20:00
26

As #150 from google groups said

Because careful with -keep class !android.support.v7.internal.view.menu.**. There are a number of classes in there which are referenced from the appcompat's resources.

The better solution is add the following lines instead:

-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }
schnatterer
  • 7,525
  • 7
  • 61
  • 80
Pongpat
  • 13,248
  • 9
  • 38
  • 51
23

On which device you are facing this problem ? (Samsung/HTC etc.)

If it is Samsung,

Various Samsung phones are included older versions of the android support library in the framework or classpath. If you use the new material support library, you'll see this crash on those Samsung devices:

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

To fix this, you must rename that class. Easiest way to do that is by running proguard. If you don't want to obfuscate, here's a 1 liner to rename just the offending classes:

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

There's an issue tracking this problem, but since it's really a Samsung bug, it's never going to get fixed on their end. Only way to fix it on the Google/AOSP side is to rename these internal classes.

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

Ganesh AB
  • 4,652
  • 2
  • 18
  • 29
  • Do you use proguard for support v4? – Jared Burrows Dec 12 '14 at 13:21
  • @JaredBurrows I have tried for support v7. But for v4 also it will work. – Ganesh AB Dec 12 '14 at 13:46
  • 2
    @Android007: thank you for pointing that work-around which actually works. However, no one seems to be able to explain why the faulty ROMs embedding the old Android Support Library in their bootclasspath causes this exception since the missing "android.support.v7.internal.view.menu.MenuBuilder" class is available in the .apk DEX code of the application which suffers from this issue. Would you have any pointer at hand which explains how the Android runtime loads the classes taken from the bootclasspath jar/dex files and the application's, please? Or any precise explanation, please? – Édouard Mercier Dec 18 '14 at 21:10
  • @ÉdouardMercier Sorry for late reply. Currently I don't have any answer for your question but I will get back to you soon. :) – Ganesh AB Feb 19 '15 at 11:49
  • 1
    Thank you @Android007, as any programmer, I do not like very much witchcraft ;) One hint: would the embedded bootclasspath contain "sealed" .jar/.dex, which would account for the behavior? – Édouard Mercier Feb 19 '15 at 20:13
  • @ÉdouardMercier if it's the same as the default Java classloader then it will always delegate loading to the root most classloader. So if these devices are adding old versions of those libraries to the bootclassloader they will be seen first. Ie they are shading the classes in the APK. – William May 09 '15 at 06:07
  • @William: thank you for this explanation. "Shading" is the magic word! I.e. the bootclasspath ships on those faulty ROMs the faulty Android Support Library v7, which shades the one embedded in the .apk. – Édouard Mercier May 11 '15 at 19:12
  • 1
    The solution in @Android007's answer is the best one I have found. Other solutions have caused weird problems preventing the app from building. – Dick Lucas Jul 08 '15 at 16:10
  • Does anyone know if this bug is fixed by installing newer support libraries? – TheLettuceMaster Sep 30 '15 at 15:22
15

This issue returned in AppCompat 23.1.1 where the .internal package was removed from the library jar.

As suggested in the comments above (credits to the people who suggested it there), now also the proguard configuration has to change.

To get the answer suggested above working again, try adding these lines to your proguard files:

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

In stead of the old fix:

#FOR OLDER APPCOMPAT VERSION:
-keep class !android.support.v7.internal.view.menu.*MenuBuilder, android.support.v7.** { ; }
-keep interface android.support.v7.* { *; }
William
  • 20,150
  • 8
  • 49
  • 91
RWIL
  • 8,729
  • 1
  • 28
  • 37
12

According to the last posts of the bug-report, this should be fixed on the new version of the support library (24.0.0) : https://code.google.com/p/android/issues/detail?id=78377#c374

Someone even claimed it fixed it.

This version is available since last month, so you should update to it.

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • Our testing confirms that 24.0.0 fixes the issue. We upgraded the support library to 24.0.0 (not alpha), removed the obfuscation we were using as a workaround, and saw no crashes on a Samsung test device where we've previously seen the crash. – Mark McClelland Aug 01 '16 at 21:10
4

Yes. Samsung already knows about this problem. I can suggest you try to using same implementation of Popup from GitHub. It is not best way, but will be works.

dreambit.io dreambitio
  • 1,892
  • 1
  • 15
  • 24
  • 1
    Yes I saw that on the Samsung forum but it doesn't seem like they're interested since none of their representatives or support have replied. – Matt K Jul 17 '14 at 18:29
4

I was having the same problem of this MenuBuilder class not found in USB debugging mode. I solved this problem by simply setting the minifyEnabled to true in both release and debug buildTypes block of build.gradle . like this:

buildTypes {

    debug {

        minifyEnabled true
    }

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

I set the minifyEnabled to true in debug type to prevent app from crashing via USB debugging to a live handset.

FAQi
  • 865
  • 1
  • 13
  • 21
0

I enabled proguard with the default proguard properties provided with an eclipse project and the problem was fixed for me. Based on some comments here https://code.google.com/p/android/issues/detail?id=78377 , some people might have to repackage using: -repackageclasses "android.support.v7"

u2tall
  • 450
  • 1
  • 7
  • 12
0

I got the same error when trying to run a 'Hello World' app on my Samsung Galaxy Tab 3 tablet via Android Studio. The app would appear to launch and then it would crash instantly and that error would show in the console in Android Studio. I did a system update on the tablet and now I am able to run the 'Hello World' app and I'm not getting the error anymore. I hope this helps someone to resolve their issue.

Note: The system update I performed on the tablet did not update the Android OS version, because it still says that the version is 4.2.2.

JulianDavid
  • 123
  • 3
  • 14
-4

Change the Compile Sdk Version of your project to "API 18:(JellyBean)"

The default is set to "Lollipop

STEPS

  1. Right Click on your project and select Open Module Settings (or press F4)
  2. In the properties tab Compiled Sdk Version