29

Some users tell me about the exception the got:

java.lang.IllegalArgumentException: Invalid payload item type
at android.util.EventLog.writeEvent(Native Method)
at android.app.Activity.onMenuItemSelected(Activity.java:2452)
at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:846)
at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:153)
at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:956)
at com.android.internal.view.menu.IconMenuView.invokeItem(IconMenuView.java:534)
at com.android.internal.view.menu.IconMenuItemView.performClick(IconMenuItemView.java:122)
at android.view.View$PerformClick.run(View.java:11934)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4123)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)

But I can't understand what can be wrong. Does anyone have some ideas about the problem? I've tried to repeat that exception, but I failed to do this. Here is the code

@Override
public boolean onCreateOptionsMenu(Menu menu) {  
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.app_menu, menu);
   return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {  
   switch (item.getItemId()) {
   case R.id.about:
      startActivity(new Intent(this, AboutActivity.class));
      return true;
   case R.id.settings:
      startActivity(new Intent(this, SettingsActivity.class));
      return true;
   case R.id.help:
      startActivity(new Intent(this, AboutActivity.class));
      return true;
   }

   return true;
} 

with app_menu xlm file:

<?xml version="1.0" encoding="utf-8"?>
<menu
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/about"
          android:icon="@android:drawable/ic_menu_info_details"
          android:title="@string/about_menu_item"/>
    <item android:id="@+id/settings"
          android:icon="@android:drawable/ic_menu_preferences"
          android:title="@string/settings_menu_item"/>
</menu>
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
polyakovsky
  • 317
  • 4
  • 10

11 Answers11

19

Like people have said, the bug occurs when there's formatting in the MenuItem title, because of an Android bug in Activity when it writes to the system EventLog.

https://android-review.googlesource.com/#/c/47831/

Although I've only seen it manifest on LG so far, it seems like it will happen in any version of Android before the fix. As far as I can tell from that commit, the earliest release it was tagged in was 4.3, but maybe I'm reading it wrong.

In Activity's onMenuItemSelected, they use MenuItem.getTitleCondensed() which causes the error. I don't use the condensed title anywhere, and as far as I can tell the views that use it by default weren't introduced until v7 support library and we're using v4.

So, my change was to override onMenuItemSelected in a base Activity class and set the condensed title to be a string version of the title. This lets the formatted title be displayed (like with a custom font), and then use the plain string one for event log:

@Override
public final boolean onMenuItemSelected(int featureId, android.view.MenuItem item) {
    // fix android formatted title bug
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 
            && item.getTitleCondensed() != null) {
        item.setTitleCondensed(item.getTitleCondensed().toString());
    }

    return super.onMenuItemSelected(featureId, item);
}

Probably you could just do it in 4.1.2, or just for LG, but it's not clear to me why it hasn't manifest on other versions. It looks like the bug could happen elsewhere. Maybe someone can figure out when it was introduced, but there didn't seem like much downside to needlessly setting an extra string.

Mike Venzke
  • 754
  • 6
  • 10
  • 1
    Thanks for this workaround. Beware, however, that the ActionMenuItem passed into this method may violate the MenuItem contract for getTitleCondensed(), i.e. it may return null. See the Android source here: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.2_r1/com/android/internal/view/menu/ActionMenuItem.java#ActionMenuItem.getTitleCondensed%28%29 – gnuf Oct 01 '14 at 19:44
  • yep, what @gnuf said. Already put that fix in my code after hitting it - I'll update the response. – Mike Venzke Oct 03 '14 at 19:30
12

For those using AppCompat:

you can't override Activity.onMenuItemSelected(). If all you need is to apply formatting to MenuItem's title and you don't care about titleCondensed:

    CharSequence rawTitle = "Click here";
    menuItem.setTitleCondensed(rawTitle);

    SpannableString spannableTitle = new SpannableString(rawTitle);
    //...whatever formatting on spannableTitle, you want
    menuItem.setTitle(spannableTitle);
riwnodennyk
  • 8,140
  • 4
  • 35
  • 37
9

For me this error occurred only for a custom font SpannableString in ActionBar title / subtitle. Removing custom formatting solved the problem.

Hack (sorry LG ;-) :

public static void setActionBarTitle(ActionBarActivity a, String s) {
    SpannableString ss = new SpannableString(s);
    ss.setSpan(new TypefaceSpan(a, "Roboto-Light.ttf"), 0, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    ActionBar actionBar = a.getSupportActionBar();
    actionBar.setDisplayShowTitleEnabled(true);
    actionBar.setLogo(R.drawable.icon);
    actionBar.setTitle(isManufacturer("LG") ? s : ss);
}

public static boolean isManufacturer(String company) {
    String manufacturer = Build.MANUFACTURER;
    String model = Build.MODEL;

    return (manufacturer.contains(company) || model.contains(company));
}
Mateusz Jablonski
  • 1,039
  • 9
  • 11
  • Hi Mateusz, I'm getting the same error (always on LG devices) and we have a styled action bar title. A question: did you get the same error? Because the stack trace seems to point at the menu, not the action bar title. If you also got an error saying `onMenuItemSelected` then probably we are experiencing the same as you did. Thanks! – Ferran Maylinch Aug 27 '14 at 09:34
  • Yes the same error. As far I can remember it occurred only on LG devices with 4.1 and I've also got reports with menu not ActionBar. Look at my edited answer to see hack preventing this error. – Mateusz Jablonski Aug 27 '14 at 10:25
  • 1
    Thanks for that idea. Note that your hack will be activated on all LG devices, including Nexus 5 and others... Maybe we could also add the condition `Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN` to activate the hack only on Android 4.1. – Ferran Maylinch Aug 28 '14 at 21:33
  • I checked in Crashlytics that I get the error only on LGE devices (I guess "LGE" is the manufacturer) with Android 4.1.2. – Ferran Maylinch Aug 28 '14 at 21:48
  • Yes I know, I did it for porpouse ;-) It's a punishement for LG... ("they did it once they can do it again") – Mateusz Jablonski Sep 02 '14 at 08:19
  • 1
    Not occurs only on LG devices, I've a Samsung GT-I9000 with Android 2.3.6 that have the same problem :-/ – forlayo Nov 25 '14 at 20:31
7

I had the same problem too. It turned out that I was trying to format my strings.

    <string name="send">
        <b>Send</b>
    </string>

I changed it to:

    <string name="send">
        Send
    </string>

I hope this helps.

You can use CDATA tags also here is a related question link.

        <string name="send">
             <![CDATA[<b>Send</b>]]>
        </string>

Thanks to Travis for pointing this out.

Community
  • 1
  • 1
theJosh
  • 2,894
  • 1
  • 28
  • 50
3

I had the same issue, but looking the Android Source Code, I found that the problem occurs when writting an internal Log, which can't print a formatted text.

The solution: simply skip this Log by reimplementing this function and DON'T CALL ITS SUPER!!

@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
    ... // Do your staff
    return true;
}
Corbella
  • 1,791
  • 14
  • 24
  • 5
    My activities extend `android.support.v7.app.ActionBarActivity` and that method can't be overriden because it's `final`... :( – Ferran Maylinch Jan 26 '14 at 17:16
2

I had the same problem

The problem in Android 4.1 with Menu Item is the Strings

Originally, my Menu Item was like this:

<item android:id="@+id/item1" android:title="@string/ic_login" 
   android:icon="@drawable/ic_login" android:orderInCategory="100" >
</item>

and that didn't work.

I change it into this:

<item android:id="@+id/item1"
    android:title="Login"
    android:orderInCategory="100"
    android:icon="@drawable/ic_login"
/>

and that worked well.

Raghav Sood
  • 81,899
  • 22
  • 187
  • 195
user1245809
  • 153
  • 1
  • 6
2

there is a "not very good' idea with onMenuItemSelected(...)

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
    if (item.getTitle() instanceof SpannableString) {
        SpannableString sp = (SpannableString)item.getTitle();
        Object[] spans = sp.getSpans(0, sp.length(), Object.class);
        if (spans != null && spans.length > 0) {
            // set text without span markups, need for super.onMenuItemSelected(featureId, item);
            item.setTitleCondensed(sp.toString());
            boolean result = super.onMenuItemSelected(featureId, item);
            item.setTitleCondensed(sp);
            return result;
        }
    }


    return super.onMenuItemSelected(featureId, item);
}

It's workaround actions like

to set a raw string, overcame a buggy place, set original formatted string back. I concider that formatted string is a SpannableString object in this example, may be you'll use something else

Mike
  • 479
  • 5
  • 15
1

I found how to cause this error. In inflate menu, I set title like that

menu.setTitle(Html.fromHtml("Menu line #1<br>And what is displayed on line #2"));

When I use this setting, it will cause invalid payload exception. Then I use

menu.setTitle("Menu line #1. Opps, can not set what is displayed on line #2");

it work fine as when I known Android. I want my menu have 2 lines, so use html tag to break line, but success on only Activity, but falied on another. I don't know what happend. Anyone have another idea or solution?

Khai Nguyen
  • 3,065
  • 1
  • 31
  • 24
1

For anyone using the Toolbar with DrawerLayout under Support Library, this issue might occur for them too. This problem can be solved by overriding the default navigation click implementation.

@Override
public void setSupportActionBar(Toolbar toolbar) {
    super.setSupportActionBar(toolbar);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            openDrawer();
        }
    });
}

This should work.

razzledazzle
  • 6,900
  • 4
  • 26
  • 37
0

I had the same problem

The problem is in Android 4.1 the Menu Item can't be formated strings

The original string in the strings.xml was using Bold tag in the string and that didn't work. Then I removed the Bold tag and that worked well.

Comet
  • 21
  • 3
0

Calling setSupportActionBar() after calling setDisplayHomeAsUp() also seems to cause this issue. It is recommended to check for multiple setSupportActionBar() calls, especially in the base classes if they exist.

On deleting the unintended call to setSupportActionBar(), the problem went away.

razzledazzle
  • 6,900
  • 4
  • 26
  • 37