Appcompat v21 lanza java.lang.UnsupportedOperationException

Después de actualizar mi proyecto para usar la librería appcompat a la versión 21.0.0 Tengo un problema con un menú contextual creado con un evento gridview multichoice modal. El mismo código funciona bien con appcompat v20.

Esta es la parte relevante de la actividad principal:

public class MainActivity extends android.support.v7.app.ActionBarActivity implements AbsListView.MultiChoiceModeListener { ... mGridView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL); mGridView.setMultiChoiceModeListener(this); @Override public boolean onCreateActionMode(final ActionMode mode, final Menu menu) { mode.setTitle("Started"); mode.getMenuInflater().inflate(R.menu.context_menu, menu); return true; } } 

Y este es el context_menu.xml:

 <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_item_share" android:title="Share..." app:showAsAction="ifRoom" android:icon="@android:drawable/ic_menu_share" app:actionProviderClass="android.support.v7.widget.ShareActionProvider" /> </menu> 

Y este es el stacktrace que estoy recuperando:

 java.lang.UnsupportedOperationException: This is not supported, use MenuItemCompat.setActionProvider() at android.support.v7.internal.view.menu.MenuItemImpl.setActionProvider(MenuItemImpl.java:628) at android.support.v7.internal.view.menu.MenuItemWrapperICS.setSupportActionProvider(MenuItemWrapperICS.java:315) at android.support.v4.view.MenuItemCompat.setActionProvider(MenuItemCompat.java:345) at android.support.v7.internal.view.SupportMenuInflater$MenuState.setItem(SupportMenuInflater.java:473) at android.support.v7.internal.view.SupportMenuInflater$MenuState.addSubMenuItem(SupportMenuInflater.java:485) at android.support.v7.internal.view.SupportMenuInflater.parseMenu(SupportMenuInflater.java:194) at android.support.v7.internal.view.SupportMenuInflater.inflate(SupportMenuInflater.java:118) at creativesdk.adobe.com.myapplication.MainActivity.onCreateActionMode(MainActivity.java:71) at android.widget.AbsListView$MultiChoiceModeWrapper.onCreateActionMode(AbsListView.java:6165) at android.support.v7.internal.view.SupportActionModeWrapper$CallbackWrapper.onCreateActionMode(SupportActionModeWrapper.java:151) at android.support.v7.app.ActionBarActivityDelegateBase$ActionModeCallbackWrapper.onCreateActionMode(ActionBarActivityDelegateBase.java:1367) at android.support.v7.internal.app.WindowDecorActionBar$ActionModeImpl.dispatchOnCreate(WindowDecorActionBar.java:1012) at android.support.v7.internal.app.WindowDecorActionBar.startActionMode(WindowDecorActionBar.java:510) at android.support.v7.app.ActionBarActivityDelegateBase.startSupportActionMode(ActionBarActivityDelegateBase.java:576) at android.support.v7.app.ActionBarActivityDelegateHC.startActionModeForChild(ActionBarActivityDelegateHC.java:62) at android.support.v7.internal.widget.NativeActionModeAwareLayout.startActionModeForChild(NativeActionModeAwareLayout.java:44) at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:694) at android.view.View.startActionMode(View.java:4857) at android.widget.AbsListView.performLongPress(AbsListView.java:3102) at android.widget.AbsListView$CheckForLongPress.run(AbsListView.java:3061) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

Tengo curiosidad por saber si alguien encontró el mismo problema y si hay una manera de evitarlo.

De hecho, existe un problema en los dispositivos ICS al intentar inflar el elemento de menú del ActionMode con AppCompat v21. Parece que los elementos de menú se envuelven 2 veces y un método de elemento envuelto se llama en lugar de la nativa, causando esta excepción.

Google necesita arreglar esto en una versión futura de AppCompat.

De todos modos, he aquí un hack que he implementado para que funcione con la versión actual:

1) Crear una clase de utilidad en el paquete android.support.v7.internal.view.menu (usar este paquete es obligatorio para permitir el acceso a métodos protegidos por paquetes sin usar la reflexión):

 package android.support.v7.internal.view.menu; import android.view.Menu; /** * Hack to allow inflating ActionMode menus on Android 4.0.x with AppCompat v21 */ public class MenuUnwrapper { public static Menu unwrap(Menu menu) { if (menu instanceof MenuWrapperICS) { return ((MenuWrapperICS) menu).getWrappedObject(); } return menu; } } 

2) Inflate su menú como este:

 @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.getMenuInflater().inflate(R.menu.context_menu, MenuUnwrapper.unwrap(menu)); return true; } 

EDIT :

El error se ha corregido en AppCompat v21.0.2 y este hack ya no es necesario.

Actualice sus herramientas.

Prueba esto. Funcionó para mí.

 MenuItem menuItem = menu.findItem(R.id.search); if (menuItem != null) { MenuItemCompat.setOnActionExpandListener(menuItem,this); MenuItemCompat.setActionView(menuItem, mSearchView); } 

Prueba esto

 inflater.inflate(R.menu.menu, menu); // search MenuItem item = menu.findItem(R.id.settings_search); MenuItemCompat.setOnActionExpandListener( item, new MenuItemCompat.OnActionExpandListener() { @Override public boolean onMenuItemActionExpand(MenuItem item) { return true; } @Override public boolean onMenuItemActionCollapse(MenuItem item) { return true; } }); 
 @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { Log.d(TAG, "onCreateActionMode"); MenuItem item = menu.findItem(R.id.menu_item_share); mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(item); MenuItemCompat.setActionProvider(item, mShareActionProvider); return true; } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.