我的Android应用程序上有一些入侵测试,我想测试我的Activity的onOptionsItemSelected()方法。
为此,我使用了仪器的invokeMenuActionSync方法:
这适用于较新版本的Android,但似乎不会导致onOptionsItemSelected()方法在旧版本上调用(例如API10)。
我尝试过与其他方法结合使用:
if (getInstrumentation().invokeMenuActionSync(activity, R.id.menu_refresh, 0 /* flags */) ||
getInstrumentation().invokeContextMenuAction(activity, R.id.menu_refresh, 0 /* flags */)) {
// verify
}
没有变化。
我正在使用AppCompat ActionBar。
是否有更好的方法可以始终调用它,或者我可以在较旧的API级别上使用并在两者之间切换的方法?
答案 0 :(得分:0)
我发现使用检测类调用支持菜单的唯一方法是使用丑陋的反射代码 (可能不需要“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);
}
}