安卓使用Root權限實現后台模擬全局按鍵、觸屏事件方法(類似按鍵精靈)


繼續在網上搜索安卓按鍵模擬(其實那時都不知道用什么關鍵字好了,能想到的關鍵字都用遍了,但是搜索出來的結果,都是之前提到的那幾個依賴源碼環境和系統權限的方案)。發現有很多介紹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表示音量加。
 
編譯完程序安裝執行,終於實現了預期的效果,當時非常高興。至於觸屏或鼠標事件,只要調用相應的ADB指令即可。但是有一點問題,就是反應速度非常慢,尤其是連續模擬多個按鍵的時候,甚至會死機。而按鍵精靈運行的就相當流暢,我又開始好奇按鍵精靈是怎么實現的。
 
后來終於還是找到了原因,模擬按鍵時,不應每次都調用Runtime.getRuntime().exec(“su”),因為每次調用這個代碼的時候,都會獲取Runtime實例,並且執行”su”請求Root權限,反應就會很慢(我的理解是相當於每次都新開一個命令行窗口);而應該只是在一開始執行一次,並獲取一個OutputStream實例,后來每次執行一條Shell指令,只需向其中寫入相應字符串,這樣就快了很多。
 
下面貼出可用的代碼。要求設備已經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");
	}
}

 

 
寫這篇文章的主要目的,並不是要強調這件事的難度,也不只是為了提出問題的解決方案(那樣就沒必要寫前面那么多過程了)。而是想把我解決問題的過程完整的寫出來,對我而言算是一個記錄,對讀者而言,沒准能從中找到一些東西。
 
解決這個問題之后,后來意外的發現,這個問題其實有人已經解決了,並且發了博客。不幸的是,那篇博客被大量使用前兩種思路的博客掩埋了,當時我怎么也沒找到。這篇博客地址在此:
 
 
順便說明一點,這篇博客中作者提到的缺點:反應速度較慢。前面提到我也越到了同樣的問題,也已經給出了解決方案。
 
 
android模擬按鍵問題總結[使用IWindowManager.injectKeyEvent方法]
 
Android中使用隱藏API(大量圖解)  
 

通過Runtime實現,代碼如下:

[html]  view plain copy
 
  1. try  
  2. {  
  3.     String keyCommand = "input keyevent " + KeyEvent.KEYCODE_MENU;  
  4.     Runtime runtime = Runtime.getRuntime();  
  5.     Process proc = runtime.exec(keyCommand);  
  6. }  
  7. catch (IOException e)  
  8. {  
  9.     // TODO Auto-generated catch block  
  10.     e.printStackTrace();  
  11. }  

這個代碼是模擬菜單鍵,模擬其它按鍵只需將KeyEvent.KEYCODE_MENU替換成其它鍵值。

缺點:反應速度較慢

 

以下附帶各KeyCode值:

 

[html]  view plain copy
 
  1. KEYCODE_UNKNOWN=0;   
  2.   
  3. KEYCODE_SOFT_LEFT=1;   
  4.   
  5. KEYCODE_SOFT_RIGHT=2;   
  6.   
  7. KEYCODE_HOME=3;   
  8.   
  9. KEYCODE_BACK=4;   
  10.   
  11. KEYCODE_CALL=5;   
  12.   
  13. KEYCODE_ENDCALL=6;   
  14.   
  15. KEYCODE_0=7;   
  16.   
  17. KEYCODE_1=8;   
  18.   
  19. KEYCODE_2=9;   
  20.   
  21. KEYCODE_3=10;   
  22.   
  23. KEYCODE_4=11;   
  24.   
  25. KEYCODE_5=12;   
  26.   
  27. KEYCODE_6=13;   
  28.   
  29. KEYCODE_7=14;   
  30.   
  31. KEYCODE_8=15;   
  32.   
  33. KEYCODE_9=16;   
  34.   
  35. KEYCODE_STAR=17;   
  36.   
  37. KEYCODE_POUND=18;   
  38.   
  39. KEYCODE_DPAD_UP=19;   
  40.   
  41. KEYCODE_DPAD_DOWN=20;   
  42.   
  43. KEYCODE_DPAD_LEFT=21;   
  44.   
  45. KEYCODE_DPAD_RIGHT=22;   
  46.   
  47. KEYCODE_DPAD_CENTER=23;   
  48.   
  49. KEYCODE_VOLUME_UP=24;   
  50.   
  51. KEYCODE_VOLUME_DOWN=25;   
  52.   
  53. KEYCODE_POWER=26;   
  54.   
  55. KEYCODE_CAMERA=27;   
  56.   
  57. KEYCODE_CLEAR=28;   
  58.   
  59. KEYCODE_A=29;   
  60.   
  61. KEYCODE_B=30;   
  62.   
  63. KEYCODE_C=31;   
  64.   
  65. KEYCODE_D=32;   
  66.   
  67. KEYCODE_E=33;   
  68.   
  69. KEYCODE_F=34;   
  70.   
  71. KEYCODE_G=35;   
  72.   
  73. KEYCODE_H=36;   
  74.   
  75. KEYCODE_I=37;   
  76.   
  77. KEYCODE_J=38;   
  78.   
  79. KEYCODE_K=39;   
  80.   
  81. KEYCODE_L=40;   
  82.   
  83. KEYCODE_M=41;   
  84.   
  85. KEYCODE_N=42;   
  86.   
  87. KEYCODE_O=43;   
  88.   
  89. KEYCODE_P=44;   
  90.   
  91. KEYCODE_Q=45;   
  92.   
  93. KEYCODE_R=46;   
  94.   
  95. KEYCODE_S=47;   
  96.   
  97. KEYCODE_T=48;   
  98.   
  99. KEYCODE_U=49;   
  100.   
  101. KEYCODE_V=50;   
  102.   
  103. KEYCODE_W=51;   
  104.   
  105. KEYCODE_X=52;   
  106.   
  107. KEYCODE_Y=53;   
  108.   
  109. KEYCODE_Z=54;   
  110.   
  111. KEYCODE_COMMA=55;   
  112.   
  113. KEYCODE_PERIOD=56;   
  114.   
  115. KEYCODE_ALT_LEFT=57;   
  116.   
  117. KEYCODE_ALT_RIGHT=58;   
  118.   
  119. KEYCODE_SHIFT_LEFT=59;   
  120.   
  121. KEYCODE_SHIFT_RIGHT=60;   
  122.   
  123. KEYCODE_TAB=61;   
  124.   
  125. KEYCODE_SPACE=62;   
  126.   
  127. KEYCODE_SYM=63;   
  128.   
  129. KEYCODE_EXPLORER=64;   
  130.   
  131. KEYCODE_ENVELOPE=65;   
  132.   
  133. KEYCODE_ENTER=66;   
  134.   
  135. KEYCODE_DEL=67;   
  136.   
  137. KEYCODE_GRAVE=68;   
  138.   
  139. KEYCODE_MINUS=69;   
  140.   
  141. KEYCODE_EQUALS=70;   
  142.   
  143. KEYCODE_LEFT_BRACKET=71;   
  144.   
  145. KEYCODE_RIGHT_BRACKET=72;   
  146.   
  147. KEYCODE_BACKSLASH=73;   
  148.   
  149. KEYCODE_SEMICOLON=74;   
  150.   
  151. KEYCODE_APOSTROPHE=75;   
  152.   
  153. KEYCODE_SLASH=76;   
  154.   
  155. KEYCODE_AT=77;   
  156.   
  157. KEYCODE_NUM=78;   
  158.   
  159. KEYCODE_HEADSETHOOK=79;   
  160.   
  161. KEYCODE_FOCUS=80;//*Camera*focus   
  162.   
  163. KEYCODE_PLUS=81;   
  164.   
  165. KEYCODE_MENU=82;   
  166.   
  167. KEYCODE_NOTIFICATION=83;   
  168.   
  169. KEYCODE_SEARCH=84;   
  170.   
  171. KEYCODE_MEDIA_PLAY_PAUSE=85;   
  172.   
  173. KEYCODE_MEDIA_STOP=86;   
  174.   
  175. KEYCODE_MEDIA_NEXT=87;   
  176.   
  177. KEYCODE_MEDIA_PREVIOUS=88;   
  178.   
  179. KEYCODE_MEDIA_REWIND=89;   
  180.   
  181. KEYCODE_MEDIA_FAST_FORWARD=90;   
  182.   
  183. KEYCODE_MUTE=91;   


免責聲明!

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



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