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 用法說明

shell@hwH60:/ $ 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: don't 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設備,並且把每個設備支持的事件類型以及編碼

shell@hwH60:/ $ 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日志,等待輸入設備,我們觸摸屏幕或是手機物理按鍵,便會看到這里的變化

shell@hwH60:/ $ 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鍵

shell@hwH60:/ $ input keyevent 3 

input text 命令 
輸入框輸入內容的。后面參數為 “字符串”,例如輸入”helloworld”字符串

shell@hwH60:/ $ input text "helloworld!"

input tap 命令 
模擬單擊事件 后面參數為: x y ,例如點擊(168,252)位置

shell@hwH60:/ $ input tap 168 252  

input swipe 命令 
此命令為滑動事件。例如:從 30 10 滑動到 30 100

shell@hwH60:/ $ 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"/>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM