Java反射机制在Android自动化测试框架的应用

在我们谈到这个问题时,我们不得不用的例子就是Robotium,这是当前最流行的除了Google的就属Robotium,很多其他的工具都基于Robotium修改而成。

针对Robotium怎么获得应用的windowmanager对象,然后再获取屏幕上的WindorDecorViews。

因为测试应用和被测应用是同一个进程中,所以夸应用是不可能的事情,所以不要试图去获取不属于该被测应用的Activity。

下面是怎么获取windowmanager对象的code

	private static Class<?> windowManager;
	static{
		try {
			String windowManagerClassName;
			if (android.os.Build.VERSION.SDK_INT >= 17) {
				windowManagerClassName = "android.view.WindowManagerGlobal";
			} else {
				windowManagerClassName = "android.view.WindowManagerImpl"; 
			}
 			windowManager = Class.forName(windowManagerClassName);

		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		} catch (SecurityException e) {
			e.printStackTrace();
		}
	}

我们可以看到,当sdk>=17时候,WindowManagerGlobal获取窗口ViewGroup的

那么我们再看看它是怎么获取里面的方法和属性呢?

         /**
	 * Returns the WindorDecorViews shown on the screen.
	 * 
	 * @return the WindorDecorViews shown on the screen
	 */

	public View[] getWindowDecorViews()
	{

		Field viewsField;
		Field instanceField;
		try {
			viewsField = windowManager.getDeclaredField("mViews");
			instanceField = windowManager.getDeclaredField(windowManagerString);
			viewsField.setAccessible(true);
			instanceField.setAccessible(true);
			Object instance = instanceField.get(null);
			return (View[]) viewsField.get(instance);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}
         /**
	 * Sets the window manager string.
	 */
	private void setWindowManagerString(){

		if (android.os.Build.VERSION.SDK_INT >= 17) {
			windowManagerString = "sDefaultWindowManager";
			
		} else if(android.os.Build.VERSION.SDK_INT >= 13) {
			windowManagerString = "sWindowManager";

		} else {
			windowManagerString = "mWindowManager";
		}
	}

我们来温故一下java反射吧:

反射常用的类和函数:Class,Constructor,Field, Method, 其中Class是类的对象,Constructor是类的构造函数对象,Field是类的属性对象实例,Method是方法对象实例。

Class:

1)Class clazz = Class.forName("com.android.settings.SettingsActivity")

2)基本类型:Class inter = Interger.TYPE

3) Class clz = MyClass.class

Constructor:

Constructor getConstructor(Class[] params) 用来获取特殊参数的公共构造函数

Constructor[] getConstructors()用来获取所有公共构造函数

getDeclaredConstructors()获取所有构造函数

getDeclaredConstructors(Class[] params) 获取所有带参数构造函数

获取属性的方法:

Field getField(String name)获取公共属性

Field[] getFields()获取所有公共属性

Fiel[] getDeclaredFields()获取所有属性

Field getDeclaredFields(String name)获取name属性

Method:

Method getMethod(String name, Class[] params)获取公共method

Method[] getMethods()获取所有公共methods

Fiel[] getDeclaredMethods()获取所有method

Field getDeclaredMethods(String name, Class[] params)获取name, methods


Robotium 其他的反射还有在获取ActionMenuItem的时候,这里用到的反射比较齐全,有方法,有属性

	/**
	 * Clicks on an ActionBar Home/Up button.
	 */

	public void clickOnActionBarHomeButton() {
		Activity activity = activityUtils.getCurrentActivity();
		MenuItem homeMenuItem = null;

		try {
			Class<?> cls = Class.forName("com.android.internal.view.menu.ActionMenuItem");
			Class<?> partypes[] = new Class[6];
			partypes[0] = Context.class;
			partypes[1] = Integer.TYPE;
			partypes[2] = Integer.TYPE;
			partypes[3] = Integer.TYPE;
			partypes[4] = Integer.TYPE;
			partypes[5] = CharSequence.class;
			Constructor<?> ct = cls.getConstructor(partypes);
			Object argList[] = new Object[6];
			argList[0] = activity;
			argList[1] = 0;
			argList[2] = android.R.id.home;
			argList[3] = 0;
			argList[4] = 0;
			argList[5] = "";
			homeMenuItem = (MenuItem) ct.newInstance(argList);
		} catch (Exception ex) {
			Log.d(LOG_TAG, "Can not find methods to invoke Home button!");
		}

		if (homeMenuItem != null) {
			activity.getWindow().getCallback().onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, homeMenuItem);
		}
	}


另外一个,使用反射方法的一个例子

	/**
	 * Parse a timeout value set using adb shell.
	 *
	 * There are two options to set the timeout. Set it using adb shell:
	 * <br><br>
	 * 'adb shell setprop solo_large_timeout milliseconds' 
	 * <br>  
	 * 'adb shell setprop solo_small_timeout milliseconds'
	 * <br><br>
	 * Set the values directly using setLargeTimeout() and setSmallTimeout
	 *
	 * @param property name of the property to read the timeout from
	 * @param defaultValue default value for the timeout
	 * @return timeout in milliseconds 
	 * 
	 */

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static int initializeTimeout(String property, int defaultValue) {
		try {
			Class clazz = Class.forName("android.os.SystemProperties");
			Method method = clazz.getDeclaredMethod("get", String.class);
			String value = (String) method.invoke(null, property);
			return Integer.parseInt(value);
		} catch (Exception e) {
			return defaultValue;
		}
	}



所以在我们在做我们的自动化框架的时候,在必要的时候可以使用反射机制获取我们想要的东西,不过我们要注意进程安全行不要跨越Android规定的,不然会是徒劳无功的。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值