Android從觸碰屏幕開始的事件采集,解析及分發(fā)(1)

????關(guān)于Android的事件分發(fā)機(jī)制,網(wǎng)上的文章快爛大街了, 大多數(shù)文章都是在千篇一律的講activity, viewgroup, view之間的分發(fā)機(jī)制, 對(duì)于事件的源頭卻沒有提及. 比如, 當(dāng)手指觸碰屏幕的一瞬間, 手機(jī)是怎么知道手指觸碰的哪里, 是觸碰的back鍵, 還是home鍵, 還是哪個(gè)坐標(biāo)點(diǎn), 是點(diǎn)擊事件, 還是滑動(dòng)事件等等, 也就是說, Android系統(tǒng)的事件采集是怎樣的. 接下來是怎么把這些采集的事件信息進(jìn)行處理的, 由誰來處理, 處理完成后又是由誰最后分發(fā)給到具體的activity的?

????有人可能會(huì)說, 作為一個(gè)普通的Android應(yīng)用層開發(fā)者, 不需要掌握這些也可以啊, 我不想知道事件是怎么來的, 我只知道事件是怎么分發(fā)的, 我能夠在程序中控制事件就可以了. 的確, 事實(shí)是這樣, 不了解這些不影響應(yīng)用層的開發(fā), 但是如果掌握了這些, 那就太有意思了, 可以做很多有意思的事情, 比如說, 按鍵精靈類的app為什么能夠記憶你的操作, 而且還能夠自動(dòng)模擬你的操作而解放你的雙手? 其實(shí), 這類app的原理無非就是通過某個(gè)辦法來采集到你的所有的操作過程, 即事件采集, 這樣他就記憶下來了, 當(dāng)需要自動(dòng)模擬事件的時(shí)候, 它會(huì)把這些采集到的信息經(jīng)過處理, 轉(zhuǎn)變成可執(zhí)行信息,這樣就能夠?qū)崿F(xiàn)模擬人的雙手來進(jìn)行自動(dòng)模擬操作了.

????因?yàn)橐胫v清楚整個(gè)事件的采集,處理及分發(fā)過程, 篇幅過大, 因此準(zhǔn)備用一個(gè)系列文章來講, 本文是系列文章的開篇, 那么先講采集.

(一) 原始事件信息

打開模擬器, 或者用usb把手機(jī)連接上電腦并打開手機(jī)上面的開發(fā)者模式, (這里為了截圖方便用了模擬器)打開cmd, 輸入adb shell getevent回車, 然后點(diǎn)擊模擬器或者手機(jī)后, 就會(huì)看到有N多行的/dev/input/event......輸出. 其實(shí), 這些信息就是最原始的事件信息.

(注:嚴(yán)格來說最原始的信息肯定是由硬件捕獲到的, 這里所說的原始信息是經(jīng)過硬件處理后返回給framework層的信息)
采集信息.gif

再看一下, 我們能否通過cmd命令來控制手機(jī)來模擬操作事件呢? 重新打開cmd, 或者Ctrl + c退出剛才的命令, 重新執(zhí)行adb shell input keyevent 4 , 發(fā)現(xiàn)手機(jī)自動(dòng)執(zhí)行了返回鍵

模擬返回鍵.gif

(二) 信息分析

以上簡(jiǎn)單的演示了下采集信息和發(fā)送信息, 接下來開始解析信息.cmd重新執(zhí)行adb shell getevent -t -l, 再次點(diǎn)擊手機(jī)的某個(gè)app, 顯示出的信息是這樣的:


點(diǎn)擊app.png

前面[ 13236.364793]顯示的是時(shí)間, 是手機(jī)或模擬器開機(jī)后到命令執(zhí)行時(shí)的時(shí)間間隔, 后面顯示的是具體命令, 其中, /dev/input/event1表示的是屏幕的輸入事件, 第一個(gè)ABS_MT_TRACKING_ID 表示采集信息開始, 后一個(gè)ABS_MT_TRACKING_ID表示采集信息結(jié)束, ABS_MT_PRESSURE表示的是屏幕感受到的壓力值, SYN_REPORT 表示的是同步數(shù)據(jù), 最重要的是ABS_MT_POSITION_X和ABS_MT_POSITION_Y, 毫無疑問, 這個(gè)就是表示屏幕感受到的觸碰坐標(biāo)位置. 最右邊的一列是16進(jìn)制的值.

其他的信息我們可以先忽略, 最主要的是要記錄時(shí)間和坐標(biāo)點(diǎn), 接下來就是把采集到的坐標(biāo)點(diǎn)轉(zhuǎn)換成10進(jìn)制的坐標(biāo)點(diǎn), x坐標(biāo)采集到的值是00005487,轉(zhuǎn)換10進(jìn)制是21639, 同理, y坐標(biāo)轉(zhuǎn)換前是00006b5b, 轉(zhuǎn)換后是27483, 接下來需要根據(jù)公式來獲取到真正的應(yīng)用層能識(shí)別的坐標(biāo)系, 具體公式為:

x = (x-xmin) * 手機(jī)像素寬 / (xmax-xmin) ;
y = (y-ymin) * 手機(jī)像素高 / (ymax-ymin);

手機(jī)像素我們可以通過代碼獲取當(dāng)前手機(jī)的像素, 但是xmin和xmax, 以及ymin和ymax是什么呢?我們還是通過cmd用adb shell getevent -p命令來獲取. 執(zhí)行命令后,拉到最下方, 看到如下圖示:


獲取參數(shù).png

我們找到0035和0036的行, 即

 0035  : value 0, min 0, max 32767, fuzz 0, flat 0, resolution 0
 0036  : value 0, min 0, max 32767, fuzz 0, flat 0, resolution 0

0035所在的行就是x信息, 0036所在的行就是y信息, 每行的min值和max值對(duì)應(yīng)上面公式的min和max, 所以我這里最終轉(zhuǎn)換成的x, y坐標(biāo)結(jié)果如下: (我的模擬器經(jīng)過代碼獲取的寬高分辨率分別是480, 728)

x = (21639 - 0) * 480 / (32767 - 0) = 317
y = (27483 - 0) * 728 / (32767 - 0) = 610

即當(dāng)點(diǎn)擊手機(jī)桌面屏幕的(317, 610)坐標(biāo), 就打開了這個(gè)app, 那么我們接下來驗(yàn)證一下, 通過cmd來發(fā)送命令, 來模擬點(diǎn)擊事件, 看看模擬器或者手機(jī)是不是能打開這個(gè)app呢?
重新打開cmd, 執(zhí)行adb shell input tap 317 610命令, 結(jié)果如下:


模擬點(diǎn)擊app.gif

我們成功的通過命令來模擬點(diǎn)擊桌面應(yīng)用了. 其實(shí)整個(gè)過程就是一個(gè)采集信息,處理信息,發(fā)送信息的過程。

到這里, 其實(shí)我們就可以自己開發(fā)出來一個(gè)類似按鍵精靈類的簡(jiǎn)單版app了, 大體思路就是在app中給一個(gè)按鈕,用來觸發(fā)信息采集, 之后用戶的一切觸碰屏幕操作都進(jìn)行錄入, 再給一個(gè)結(jié)束采集的按鈕, 觸發(fā)按鈕就結(jié)束信息錄入, 并開始處理信息, 包括每個(gè)動(dòng)作的屬性(是點(diǎn)擊, 還是滑動(dòng), 還是長(zhǎng)按等等), 相鄰動(dòng)作的時(shí)間間隔, 等等, 然后保存起來, 最后再給一個(gè)自動(dòng)模擬事件的按鈕, 當(dāng)觸發(fā)時(shí), 程序開始自動(dòng)讀取保存的事件信息并執(zhí)行模擬事件了.

以上, 是我們?nèi)藶榈倪M(jìn)行事件采集, 處理, 發(fā)送. 那么Android系統(tǒng)內(nèi)部是怎么做的呢? 是誰負(fù)責(zé)把這個(gè)事件信息處理后轉(zhuǎn)換成為各種KeyEvent或者M(jìn)otionEvent的, 以及最終是怎么傳遞到的activity中的, 請(qǐng)關(guān)注系列文章之后的文章。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 跨進(jìn)程模擬觸屏事件的作用## 有很多在一個(gè)Activity中實(shí)現(xiàn)虛擬觸摸的方法,但是無法做到跨進(jìn)程虛擬觸摸。無論是...
    babybus_hentai閱讀 8,570評(píng)論 1 3
  • Android 調(diào)試橋 Android 調(diào)試橋 (adb) 是一個(gè)通用命令行工具,其允許您與模擬器實(shí)例或連接的 A...
    guanjm閱讀 1,633評(píng)論 0 1
  • 女兒從香港回來,給下一輩的幾個(gè)小朋友帶了珍妮小熊曲奇餅干,順便也有我的一盒。 瞧,上圖那方型的餅干盒上,一身消防員...
    星韻r閱讀 813評(píng)論 1 5
  • GET: request.GET.get("your key",none)#字典形式,也是js對(duì)象; requst...
    zhu733756閱讀 2,866評(píng)論 0 0
  • 今年目標(biāo):健康管理(早睡11點(diǎn)之前、飲食、體重) 黑色280 找到一位合作伙伴 今日青蛙:1.聽音頻。2.投資交易...
    鎮(zhèn)星Aquarius閱讀 94評(píng)論 0 0

友情鏈接更多精彩內(nèi)容