繼續在網上搜索安卓按鍵模擬(其實那時都不知道用什麼關鍵字好了,能想到的關鍵字都用遍了,可是搜索出來的結果,都是以前提到的那幾個依賴源碼環境和系統權限的方案)。發現有不少介紹ADB調試,向手機發送按鍵事件的文章。恰好以前作過在Root權限下,用Java調用安卓底層的Linux Shell,而後執行pm指令進行APK的安裝卸載。這時我突發奇想,可否用Shell調用ADB指令呢?shell
因而就進行了嘗試,使用Java執行Runtime.getRuntime().exec("su").getOutputStream(),獲取了一個具備Root權限的Process的輸出流對象,向其中寫入字符串便可以Root權限被Shell執行,ADB模擬按鍵的指令爲 "input keyevent keyCode",keyCode爲按鍵的鍵值,例如KeyEvent.KEYCODE_VOLUME_UP表示音量加。命令行
編譯完程序安裝執行,終於實現了預期的效果,當時很是高興。至於觸屏或鼠標事件,只要調用相應的ADB指令便可。可是有一點問題,就是反應速度很是慢,尤爲是連續模擬多個按鍵的時候,甚至會死機。而按鍵精靈運行的就至關流暢,我又開始好奇按鍵精靈是怎麼實現的。調試
後來終於仍是找到了緣由,模擬按鍵時,不該每次都調用Runtime.getRuntime().exec("su"),由於每次調用這個代碼的時候,都會獲取Runtime實例,而且執行"su"請求Root權限,反應就會很慢(個人理解是至關於每次都新開一個命令行窗口);而應該只是在一開始執行一次,並獲取一個OutputStream實例,後來每次執行一條Shell指令,只需向其中寫入相應字符串,這樣就快了不少。code
下面貼出可用的代碼。要求設備已經Root,不須要其餘任何特殊權限或簽名。因爲用的是ADB指令,兼容性也不會有太大問題。首次運行程序時(其實也就是執行Runtime.exec("su")的時候),會請求Root權限。對象
/** * 用root權限執行Linux下的Shell指令 * * @author jzj * @since 2014-09-09 */ public class RootShellCmd { private OutputStream os; /** * 執行shell指令 * * @param cmd * 指令 */ public final void exec(String cmd) { try { if (os == null) { os = Runtime.getRuntime().exec("su").getOutputStream(); } os.write(cmd.getBytes()); os.flush(); } catch (Exception e) { e.printStackTrace(); } } /** * 後臺模擬全局按鍵 * * @param keyCode * 鍵值 */ public final void simulateKey(int keyCode) { exec("input keyevent " + keyCode + "\n"); } }