Android注入事件的三種方法比較

來源:互聯網
上載者:User

標籤:

方法1:使用內部APIs

  該方法和其他所有內部沒有向外正式公布的APIs一樣存在它自己的風險。原理是通過獲得WindowManager的一個執行個體來訪問injectKeyEvent/injectPointerEvent這兩個事件注入方法。

IBinder wmbinder = ServiceManager.getService( "window" ); IWindowManager m_WndManager = IWindowManager.Stub.asInterface( wmbinder );

  ServiceManager和Windowsmanager被定義為存根Stubs類。我們根據我們的需要綁定上這些服務並訪問裡面的方法。 To send a key do the following: 通過以下方式發送一個事件:

// key downm_WndManager.injectKeyEvent( new KeyEvent( KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A ),true );// key upm_WndManager.injectKeyEvent( new KeyEvent( KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A ),true );

  發送touch/mouse事件:

//pozx goes from 0 to SCREEN WIDTH , pozy goes from 0 to SCREEN HEIGHTm_WndManager.injectPointerEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,pozx, pozy, 0), true);m_WndManager.injectPointerEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,pozx, pozy, 0), true);

  這種方法能在你的應用中很好的工作,但,也僅僅只能在你的應用中而已

一旦你想要往其他視窗注入keys/touch事件,你將會得到一個強制關閉的訊息:

E/AndroidRuntime(4908): java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission

  苦逼了吧,畢竟INJECT_EVENTS是需要系統許可權的,一些可能解決的方案在這裡和這裡有討論到。 (天地會珠海分舵注註:請查看本人上一篇翻譯的《Monkey源碼分析番外篇之WindowManager注入事件如何跳出進程間安全限制》裡面有更詳細針對這個問題的描述)

 

方法2: 使用instrumentation對象

  相對以上的隱藏介面和方法,這個是比較乾淨(上面的是隱藏的,故需要用到android不乾淨不推薦的方法去擷取)的方式,但不幸的事它依然有上面的JINECT_EVENTS這個只有系統應用(基本上就是android自己提供的,如monkey)才被允許的許可權問題。

Instrumentation m_Instrumentation = new Instrumentation();m_Instrumentation.sendKeyDownUpSync( KeyEvent.KEYCODE_B );

  以下是觸摸事件執行個體:

//pozx goes from 0 to SCREEN WIDTH , pozy goes from 0 to SCREEN HEIGHTm_Instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,pozx, pozy, 0);m_Instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,pozx, pozy, 0);

 

  在應用內操作的話完全沒有問題,但一旦跳出這個應用去觸發按鍵事件的話就會崩潰。不是因為這個方法不工作,而是因為android開發人員做了限制。謝謝你們,android的開發人員們,你牛逼!個屁。

  通過分析sendPointerSync的對應代碼,可以看到其實instrumentation使用到的注入事件方式其實和方法一提到的通過WindowManager.injectPointerEvents是一樣的,所以穿的都是同一條內褲,只是Robotium出來走動的時候套上條時尚喇叭褲,而以上直接調用WindowManager的方式就猶如只穿一條內褲出街的區別而已。

public void sendPointerSync(MotionEvent event) {validateNotAppThread();try {(IWindowManager.Stub.asInterface(ServiceManager.getService("window"))).injectPointerEvent(event, true);} catch (RemoteException e) {}}

 

方法3:直接注入事件到裝置/dev/input/eventX

  linux以系統裝置的方式向使用者暴露了一套統一的事件注入介面/dev/input/eventX(其中X代表一個整數)。我們可以直接跳用而跳過以上的平台(android這個機遇linux的平台)限制問題。但是這需要工作的話,你需要rooted過的裝置。

  裝置檔案eventX預設是被設定為660這個許可權的(Owner和同群組成員有讀寫,而owner是root)。為了向這個裝置注入事件,你必須讓它能可寫。所以請先做以下動作:

adb shellsuchmod 666 /dev/input/event3

  你將需要root許可權來運行chmod命令。

作/譯者

知識共用公眾號

CSDN

天地會珠海分舵

TechGoGoGo

http://blog.csdn.net/zhubaitian

Android注入事件的三種方法比較

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.