我发现使用检测类调用支持菜单的唯一方法是使用丑陋的反射代码(可能不需要“init”部分中的某些字段和类,抱歉,我也将它们用于其他代码)
// support part
private static Class<?> actionBarActivitySupportClass;
private static Field mImplField;
private static Class<?> actionBarActivityDelegateBaseClass;
private static Field mActionModeSupportField;
private static Class<?> actionModeSupportImplClass;
private static Field mMenuActionModeSupportField;
private static Class<?> menuBuilderSupportClass;
private static Field mVisibleItemsSupportField;
private static Field mCallbackActionModeSupportField;
private static Class<?> callbackWrapperSupportClass;
private static Field mWrappedSupportField;
private static Method onMenuItemSelectedSupportmethod;
private static Field mActionBarSupportView;
private static Class<?> actionBarViewSupportClass;
private static Field mOptionMenuSupportField;
private static Method dispatchMenuItemSelected;
static {
init();
}
private static void init() {
try {
actionBarActivitySupportClass = Class.forName("android.support.v7.app.ActionBarActivity"); //$NON-NLS-1$
mImplField = actionBarActivitySupportClass.getDeclaredField("mImpl"); //$NON-NLS-1$
mImplField.setAccessible(true);
actionBarActivityDelegateBaseClass = Class.forName("android.support.v7.app.ActionBarActivityDelegateBase"); //$NON-NLS-1$
mActionModeSupportField = actionBarActivityDelegateBaseClass.getDeclaredField("mActionMode"); //$NON-NLS-1$
mActionModeSupportField.setAccessible(true);
actionModeSupportImplClass = Class.forName("android.support.v7.app.ActionBarImplBase$ActionModeImpl"); //$NON-NLS-1$
mMenuActionModeSupportField = actionModeSupportImplClass.getDeclaredField("mMenu"); //$NON-NLS-1$
mMenuActionModeSupportField.setAccessible(true);
menuBuilderSupportClass = Class.forName("android.support.v7.internal.view.menu.MenuBuilder"); //$NON-NLS-1$
mVisibleItemsSupportField = menuBuilderSupportClass.getDeclaredField("mVisibleItems"); //$NON-NLS-1$
mVisibleItemsSupportField.setAccessible(true);
mCallbackActionModeSupportField = actionModeSupportImplClass.getDeclaredField("mCallback"); //$NON-NLS-1$
mCallbackActionModeSupportField.setAccessible(true);
callbackWrapperSupportClass = Class.forName("android.support.v7.app.ActionBarActivityDelegateBase$ActionModeCallbackWrapper"); //$NON-NLS-1$
mWrappedSupportField = callbackWrapperSupportClass.getDeclaredField("mWrapped"); //$NON-NLS-1$
mWrappedSupportField.setAccessible(true);
onMenuItemSelectedSupportmethod = actionModeSupportImplClass.getDeclaredMethod("onMenuItemSelected", new Class[]{menuBuilderSupportClass,MenuItem.class}); //$NON-NLS-1$
onMenuItemSelectedSupportmethod.setAccessible(true);
mActionBarSupportView = actionBarActivityDelegateBaseClass.getDeclaredField("mActionBarView"); //$NON-NLS-1$
mActionBarSupportView.setAccessible(true);
actionBarViewSupportClass = Class.forName("android.support.v7.internal.widget.ActionBarView"); //$NON-NLS-1$
mOptionMenuSupportField = actionBarViewSupportClass.getDeclaredField("mOptionsMenu"); //$NON-NLS-1$
mOptionMenuSupportField.setAccessible(true);
dispatchMenuItemSelected = menuBuilderSupportClass.getDeclaredMethod("dispatchMenuItemSelected", new Class[]{menuBuilderSupportClass,MenuItem.class}); //$NON-NLS-1$
dispatchMenuItemSelected.setAccessible(true);
} catch (ClassNotFoundException e) {
System.out.println("support class not loaded "+e.getMessage()); //$NON-NLS-1$
} catch (SecurityException e) {
System.out.println("support class not loaded "+e.getMessage()); //$NON-NLS-1$
} catch (NoSuchFieldException e) {
System.out.println("support class not loaded "+e.getMessage()); //$NON-NLS-1$
} catch (NoSuchMethodException e) {
System.out.println("support class not loaded "+e.getMessage()); //$NON-NLS-1$
}
}
public static void invokeMenu(Instrumentation instrumentation,final Activity activity,final Object item) {
if ((mImplField != null) && (actionBarActivitySupportClass != null) && (actionBarActivitySupportClass.isInstance(activity))
&& (mActionBarSupportView != null) && (mOptionMenuSupportField != null) && (dispatchMenuItemSelected != null)) {
activity.runInUiThread(new Runnable() {
@Override
public void run() {
try {
Object actionBarActivityDelegateBase = mImplField.get(activity);
if (actionBarActivityDelegateBase != null) {
Object actionBarView = mActionBarSupportView.get(actionBarActivityDelegateBase);
if (actionBarView != null) {
Object mOptionMenu = mOptionMenuSupportField.get(actionBarView);
dispatchMenuItemSelected.invoke(mOptionMenu, new Object[]{mOptionMenu,item});
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
} else {
// good old classic way
instrumentation.invokeMenuActionSync(activity, ((MenuItem)item).getItemId(), 0);
}
}