Robotium基于Instrumentation的二次封装,然而UiAutomation 也能通过instrumentation.getUiAutomation()拿到。
android的输入事件处理, 大多跟InputReader, InputManager, InputManagerService。
---- Instrumentation sendPointerSync(MotionEvent event),按键事件
Android Instrumentation模拟鼠标点击事件或按键事件
Instrumentation发送键盘鼠标事件:Instrumentation提供了丰富的以send开头的函数接口来实现模拟键盘鼠标,如下所述:
sendCharacterSync(int keyCode) //用于发送指定KeyCode的按键
sendKeyDownUpSync(int key) //用于发送指定KeyCode的按键
sendPointerSync(MotionEvent event) //用于模拟Touch
sendStringSync(String text) //用于发送字符串
注意:以上函数必须通过Message的形式抛到Message队列中。如果直接进行调用加会导致程序崩溃。
Robotium是通过对instrumentation的注入事件(sendKeyDownUpSync、sendPointerSync)的封装、以及通过调用instrumentation的runOnMainSync、runOnUiThread等来完成对控件的操作,让用户可以直接调用一个solo.clickOnText等方法,就能够完成操作,而不用自己去写一堆找到控件,然后再点击触发等方法。
Android Inputmanager的injectEvent()方法也可以模拟产生输入事件(API16以上版本)。不过此方法属于隐藏方法,需要反射调用。
Instrumentation mInst = new Instrumentation(); mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_A); //按键事件
这两句. KeyEvent.KEYCODE_A替换成自己的按键需求。
Instrumentation类——Android自动化测试学习历程- https://www.cnblogs.com/keke-xiaoxiami/p/4307571.html
Instrumentation instrument= new Instrumentation();
instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, dx, dy, 0));
instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, mx, my, 0));
instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, upx, upy, 0));
instrument.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 200, 300, 0);
instrument.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 200, 300, 0);
private static void sendPointerSync(MotionEvent event) {
try {
(IWindowManager.Stub.asInterface(ServiceManager
.getService("window"))).injectPointerEvent(event, true);
} catch (RemoteException e) {
e.printStackTrace();
}
}
---- MotionEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN),设置事件源与事件反控
Handler.postDelayed(new Runnable(){
public void run(){
event.setSource(InputDevice.SOURCE_TOUCHSCREEN);// 留意参数
// 同样, 留意参数, 如果参数错, 会不成功.
imgr.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
} }, delayed); }
Android——使用InputManager实现模拟滚动- https://blog.csdn.net/weixin_42832981/article/details/89883339
android 模拟发送多点触摸事件- http://www.itgo.me/a/3875849884570322271/InputManager-MotionEvent
Android inject input events 注入Touch 点(x, y) 触摸输入事件- https://blog.csdn.net/zjwfan/article/details/50549784?locationNum=12
1. 使用Instrumentation
new Thread(new Runnable() {
@Override
public void run() {
Instrumentation mInst = new Instrumentation();
mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_A); //按键事件
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMilis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, point.x, point.y, 0); //触摸按下
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMilis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, point.x, point.y, 0); //触摸抬起
}
}).start();
查看sendPointerSync()方法的源码会看到,它使用的是 injectInputEvent()方法实现:
public void sendPointerSync(MotionEvent event) {
validateNotAppThread();
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
}
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}
使用Instrumentation需要<uses-permission android:name="android.permission.INJECT_EVENTS"/>权限,并且跨App注入事件需要系统应用(AndroidManifest.xml 中加入android:sharedUserId="android.uid.system")并且平台签名才行。
2. 使用反射直接调用injectInputEvent() 方法:
private void invokeInjectInputEvent(MotionEvent event) {
Class cl = InputManager.class;
try {
Method method = cl.getMethod("getInstance");
Object result = method.invoke(cl);
InputManager im = (InputManager) result;
method = cl.getMethod("injectInputEvent", InputEvent.class, int.class);
method.invoke(im, event, 0);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}catch (InvocationTargetException e) {
e.printStackTrace();
}
}
4. 针对特定的应用可以使用Android Accessibility
5. 可以直接使用Adb shell
adb shell input tap point.x point.y
6.monkeyrunner是一个功能更为丰富的选项,不过需要连接电脑