安卓模擬按鍵操做的一些思路

安卓使用Root權限實現後臺模擬全局按鍵、觸屏事件方法(相似按鍵精靈)android

有 時咱們須要使用安卓實如今後臺模擬系統按鍵,好比對音量進行調節(模擬音量鍵),關閉前臺正在運行的App(模擬返回鍵),或者模擬觸屏事件。可是對於原 生安卓系統而言,後臺進程關閉前臺進程,甚至模擬用戶事件,進而操控整個系統,是不符合系統安全原則的,若是有這樣的漏洞被病毒或惡意軟件所利用,會很是 危險。
因爲一些特殊緣由,我恰巧須要實現這樣的功能,而又沒有條件自行編譯安卓系統(可是能夠利用Root權限,由於Root權限的獲取相對簡單不少,而且不少用戶的安卓設備都有Root過)。網上也看到不少人在提相似的問題,不少人討論了半天,結果都是無解。因而我花了很大精力,最後終於找到了解決方案。
在網上查找了不少資料,主要找到兩種方法:Instrumentation和IWindowManager。編程

使用Instrumentation接口:對於非自行編譯的安卓系統,沒法獲取系統簽名,只能在前臺模擬按鍵,不能後臺模擬。安全

一種是使用Instrumentation接口,這個接口本來是用來對軟件進行測試而留出來的。通過嘗試,發現這個接口能夠模擬按鍵,可是前提是在應用處於前臺時。而應用處於前臺時,模擬按鍵基本上也沒有太大的做用(模擬按鍵操做應用自身彷佛沒有很大意義)。
當應用處於後臺時,這個Instrumentation接口就失效了。網上找到的解釋是,在後臺使用這個接口,須要有系統權限,也就是在Manifest中添加android:sharedUserId=」android.uid.system」。而這會致使什麼問題呢?聲明瞭系統權限的APK,只有具備系統簽名的狀況下,才能被安裝到安卓設備上,好比系統自帶的電話、短信,本質上也就是APK程序,可是這些應用具備系統權限。
安 卓系統有一套簽名機制,APK只有有了數字簽名,才能被安裝。一般調試時默認Eclipse自動對其進行簽名,使用的是Debug簽名。當發佈應用時,開 發者則使用本身獨有的數字簽名文件對APK進行簽名(這個文件能夠用Eclipse生成,簽名也可讓Eclipse完成)。APK有新版本的安裝時,如 果檢測到簽名不一致,系統會提示簽名不一致,只有卸載舊版本才能安裝。這一機制從必定程度上避免了第三方對官方發佈的APK進行修改甚至非法植入病毒等行 爲(固然若是用戶主動卸載舊版本的官方應用、安裝新版本的非官方APK也是能夠的)。而具備同一簽名的不一樣App,它們之間能夠共享一些數據。
而 系統簽名怎麼獲取呢?在編譯安卓系統的時候,會將一個系統簽名的數字簽名文件放到一塊兒編譯。對於一個已經編譯完成的系統,或者爲了適配不一樣系統,必然沒法 獲取到這個數字簽名文件,因而也沒法對APK進行系統簽名。最後就致使具備uid.system屬性的APK沒法被安裝,因而 Instrumentation接口後臺模擬按鍵的方法,只能在自行編譯系統的狀況下才可使用。學習

使用反射方法調用系統IWindowManager隱藏API:兼容性較差,穩定性很差,容易出錯。另外實際編譯時發生錯誤,緣由暫時不明。
網 上還有一種方法。安卓系統中有一些隱藏API,一般是利用Java的權限限制,使得這些API沒法被調用。但經過反射的方式,能夠突破Java的權限限 制。在IWindowManager中就隱藏了能夠模擬按鍵和觸屏事件的API。嘗試網上的方法,下載到一個由安卓源碼編譯好的jar文件,添加到工程 中,而後使用發射編寫了一些代碼,嘗試調用隱藏API。結果編譯的時候Eclipse直接不響應了,多是由於電腦配置不夠,jar文件太大。嘗試了幾回 沒有成功,又考慮到這種方法有不少弊端,而且極可能最後仍是須要系統權限(網上很多文章說得不是很清楚),因而就放棄了這個方法。
android模擬按鍵問題總結[使用IWindowManager.injectKeyEvent方法]測試

Android中使用隱藏API(大量圖解)ui

JNI調用C程序模擬按鍵:仍然是權限問題。
參 考了網上一些資料所提出的可能的思路,發現剩下能想到的方法就是用JNI實現,經過調用C/C++程序來模擬按鍵。對Linux底層編程不熟悉,網上參考 了一些代碼,在Ubuntu下編寫了一個按鍵模擬程序,很順利的編譯運行經過。而後又開始學習JNI的編譯方法,先在C程序層寫了個簡單的加法運算,編譯 運行測試經過,而後就把模擬按鍵的代碼貼了進去。滿懷期待的寫好安卓Java層代碼,編譯、下載、執行程序,卻發現徹底沒有效果。
想看一下究竟是哪一步出錯了,就在C程序裏面改了改,用LogCat打印出C程序的返回值,發如今打開按鍵設備的時候出錯,看來確定又是權限的問題了。
儘管系統已經Root,APK也容許使用Root權限,可是Root權限無法傳遞給C程序,權限不夠,程序沒法執行。在網上找了一通有關Linux、安卓權限的資料,也沒找出來什麼思路。其實當時很疑惑,在Linux系統中,Root權限是最高的權限,安卓也不例外,有文章指出,Root權限>系統權限>用戶權限。儘管能獲取到Root權限,卻不能完成系統權限所能完成的任務,總感受不該該。調試

安卓按鍵精靈:使用Root權限而不需系統簽名,實現後臺模擬按鍵和觸屏等事件是可行的。
當時很絕望,感受估計只有自行編譯系統才能解決問題了。就在那時候,忽然想起了按鍵精靈軟件。之前用過電腦版,在安卓市場一找,果真也有安卓版。下載使用發現,按鍵精靈就能夠實如今後臺模擬按鍵操做,須要Root權限,可是是什麼原理卻不得而知。本想嘗試反編譯源碼查看,可是當時出了一些問題,反編譯沒有成功。在網上搜索安卓按鍵精靈的原理,除了以前的那兩種依賴源碼環境才能使用的API,也沒有找到結果。不過至少說明了,使用Root權限而不須要系統簽名,實現模擬按鍵、而且兼容大量安卓設備是可行的。對象

最終解決問題:使用Shell調用ADB指令實現。
繼 續在網上搜索安卓按鍵模擬(其實那時都不知道用什麼關鍵字好了,能想到的關鍵字都用遍了,可是搜索出來的結果,都是以前提到的那幾個依賴源碼環境和系統權 限的方案)。發現有不少介紹ADB調試,向手機發送按鍵事件的文章。恰好以前作過在Root權限下,用Java調用安卓底層的Linux Shell,而後執行pm指令進行APK的安裝卸載。這時我突發奇想,可否用Shell調用ADB指令呢?
因而就進行了嘗試,使用Java執行 Runtime.getRuntime().exec(「su」).getOutputStream(),獲取了一個具備Root權限的Process的 輸出流對象,向其中寫入字符串便可以Root權限被Shell執行,ADB模擬按鍵的指令爲 「input keyevent keyCode」,keyCode爲按鍵的鍵值,例如KeyEvent.KEYCODE_VOLUME_UP表示音量加。
編譯完程序安裝執行,終於實現了預期的效果接口

相關文章
相關標籤/搜索