Android代码模拟物理屏幕点击事件

Posted 星辰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android代码模拟物理屏幕点击事件相关的知识,希望对你有一定的参考价值。

一、应用中模拟物理和屏幕点击事件

例如,模拟对某个view的点击事件

private void simulateClick(View view, float x, float y) {
    long downTime = SystemClock.uptimeMillis();
    final MotionEvent downEvent = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_DOWN, x, y, 0);
    downTime += 1000;
    final MotionEvent upEvent = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_UP, x, y, 0);
    view.onTouchEvent(downEvent);
    view.onTouchEvent(upEvent);
    downEvent.recycle();
    upEvent.recycle();
}

public void setMouseClick(int x, int y){  
    MotionEvent evenDownt = MotionEvent.obtain(System.currentTimeMillis(),  
            System.currentTimeMillis() + 100, MotionEvent.ACTION_DOWN, x, y, 0);  
    dispatchTouchEvent(evenDownt);  
    MotionEvent eventUp = MotionEvent.obtain(System.currentTimeMillis(),  
            System.currentTimeMillis() + 100, MotionEvent.ACTION_UP, x, y, 0);  
    dispatchTouchEvent(eventUp);  
    evenDownt.recycle();  
    eventUp.recycle();  
}  

这实现原理就是模拟两个MotionEvent (按下和提起) 然后用一个View 来处理这个Event 。

二、Instrumentation实现模拟键盘鼠标事件

// 可以不用在 Activity 中增加任何处理,各 Activity 都可以响应  
Instrumentation inst = new Instrumentation();  
inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),   
    MotionEvent.ACTION_DOWN, 200, 500, 0));  
inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),   
    MotionEvent.ACTION_UP, 200, 500, 0));  

三、系统中模拟物理和屏幕点击事件

1、adb shell 进入手机命令行 
2、getevent -h 用法说明

[email protected]:/ $ getevent -h  

Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]
    -t: show time stamps
    -n: dont print newlines
    -s: print switch states for given bits
    -S: print all switch states
    -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)
    -d: show HID descriptor, if available
    -p: show possible events (errs, dev, name, pos. events)
    -i: show all device info and possible events
    -l: label event types and names in plain text
    -q: quiet (clear verbosity mask)
    -c: print given number of events then exit
    -r: print rate events are received

[-t] 参数显示事件的时间戳 
[-n] 取消事件显示时的换行符 
[-s switchmask] 得到指定位的开关状态 
[-S] 得到所有开关的状态 
[-v [mask]] 根据mask的值显示相关信息 
[-p] 显示每个设备支持的事件类型和编码 
[-q] 只显示事件数据 
[-c count] 只显示count次事件的数据 
[-r] 显示事件接收频率

3、getevent -p 显示出来当前系统存在的所有input设备,并且把每个设备支持的事件类型以及编码

[email protected]:/ $ getevent -p

add device 1: /dev/input/event2
  name:     "hi6421_on"
  events:
    KEY (0001): 0074 
  input props:
    <none>
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 2: /dev/input/event4
  name:     "huawei,touchscreen"
  events:
    KEY (0001): 003b  003c  003d  003e  003f  0040  0041  0042 
                0043  0044  0057  00bd  00be  00bf  00c0  00c1 
                0145  014a 
    ABS (0003): 0000  : value 0, min 0, max 1079, fuzz 0, flat 0, resolution 0
                0001  : value 0, min 0, max 1919, fuzz 0, flat 0, resolution 0
                0018  : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
                0030  : value 0, min 0, max 15, fuzz 0, flat 0, resolution 0
                0035  : value 0, min 0, max 1079, fuzz 0, flat 0, resolution 0
                0036  : value 0, min 0, max 1919, fuzz 0, flat 0, resolution 0
                0039  : value 0, min 0, max 15, fuzz 0, flat 0, resolution 0
                003a  : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
  input props:
    INPUT_PROP_DIRECT
add device 3: /dev/input/event0
  name:     "mhl_rcp_dev"
  events:
    KEY (0001): 0002  0003  0004  0005  0006  0007  0008  0009 
                000a  000b  000e  001c  0034  003b  003c  003d 
                003e  003f  0067  0069  006a  006c  0071  0072 
                0073  0077  0080  008b  009e  009f  00a1  00a4 
                00a5  00a7  00a8  00ae  00c8  00c9  00cf  00d0 
                00d5  00e8  0161  0163  0192  0193  019c 
  input props:
    <none>
could not get driver version for /dev/input/mice, Not a typewriter
add device 4: /dev/input/event1
  name:     "hisi_gpio_key.14"
  events:
    KEY (0001): 0072  0073 
  input props:
    <none>
add device 5: /dev/input/event3
  name:     "hi3630_hi6401_CARD Headset Jack"
  events:
    KEY (0001): 0072  0073  00e2 
    SW  (0005): 0002  0004 
  input props:
    <none>

4、getevent 查看输入设备和查看事件 
打印输出log日志,等待输入设备,我们触摸屏幕或是手机物理按键,便会看到这里的变化

[email protected]:/ $ getevent

例如:
/dev/input/event0: 0001 014a 00000001
/dev/input/event0: 0003 0000 000000f6
/dev/input/event0: 0003 0001 000002ed
/dev/input/event0: 0003 0035 000000f6
/dev/input/event0: 0003 0036 000002ed
/dev/input/event0: 0003 0032 00000001
/dev/input/event0: 0003 0039 00000000
/dev/input/event0: 0003 003a 00000043
/dev/input/event0: 0000 0002 00000000

他们四个参数对应的是device type code value 
device:指的是处理触摸和按键的输入设备。 
type:指的是事件类型,EV_SYN [0000] (同步事件),EV_KEY [0001] (按键事件),EV_ABS [0003] (绝对值事件) 
code 指的是前面type代表的事件中支持的编码。 
value 指的是值。

例如:需要模拟一次点击BACK键,模拟点击的功能通常都是使用 /dev/input/event0 这个输入设备,back键的类型为 0001(按键事件),BACK的编码为 0x9e 转换为十进制后即158

注意的是在getevent中code显示的是十六进制,而sendevent时需要用十进制

那我们输入如下命令即可模拟一次BACK键的按下和弹起:

adb shell sendevent /dev/input/event0 1 158 1
adb shell sendevent /dev/input/event0 1 158 0

5、input keyevent 命令

先列举 input keyevent 几个比较常用的code值:

input keyevent 3    // Home

input keyevent 4    // Back

input keyevent 19  //Up

input keyevent 20  //Down

input keyevent 21  //Left

input keyevent 22  //Right

input keyevent 23  //Select/Ok

input keyevent 24  //Volume+

input keyevent 25  // Volume-

input keyevent 82  // Menu 菜单

例如: 
点击back键

[email protected]:/ $ input keyevent 3 

input text 命令 
输入框输入内容的。后面参数为 “字符串”,例如输入”helloworld”字符串

[email protected]:/ $ input text "helloworld!"

input tap 命令 
模拟单击事件 后面参数为: x y ,例如点击(168,252)位置

[email protected]:/ $ input tap 168 252  

input swipe 命令 
此命令为滑动事件。例如:从 30 10 滑动到 30 100

[email protected]:/ $ input swipe 30 10 30 100

Android代码实现,注意需要root

private void execShellCmd(String cmd) {  
    try {  
        // 申请获取root权限,这一步很重要,不然会没有作用  
        Process process = Runtime.getRuntime().exec("su");  
        // 获取输出流  
        OutputStream outputStream = process.getOutputStream();  
        DataOutputStream dataOutputStream = new DataOutputStream(  
                outputStream);  
        dataOutputStream.writeBytes(cmd);  
        dataOutputStream.flush();  
        dataOutputStream.close();  
        outputStream.close();  
    } catch (Throwable t) {  
        t.printStackTrace();  
    }  
}  
execShellCmd("getevent -p");  
execShellCmd("sendevent /dev/input/event0 1 158 1");  
execShellCmd("sendevent /dev/input/event0 1 158 0");  
execShellCmd("input keyevent 3");//home  
execShellCmd("input text  ‘helloworld!‘ ");  
execShellCmd("input tap 168 252");  
execShellCmd("input swipe 100 250 200 280"); 
<uses-permission android:name = "android.permission.INJECT_EVENTS"/>

 

以上是关于Android代码模拟物理屏幕点击事件的主要内容,如果未能解决你的问题,请参考以下文章

[Android]通过adb shell input上报命令模拟屏幕点击事件

Android模拟屏幕点击input tap替代解决方案

Android 模拟手势点击屏幕

iOS Swift 中的 Android 片段模拟

Android导航抽屉点击事件问题

Android模拟点击