天天看点

安卓使用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权限。

写这篇文章的主要目的,并不是要强调这件事的难度,也不只是为了提出问题的解决方案(那样就没必要写前面那么多过程了)。而是想把我解决问题的过程完整的写出来,对我而言算是一个记录,对读者而言,没准能从中找到一些东西。

解决这个问题之后,后来意外的发现,这个问题其实有人已经解决了,并且发了博客。不幸的是,那篇博客被大量使用前两种思路的博客掩埋了,当时我怎么也没找到。这篇博客地址在此:

<a href="http://blog.csdn.net/aminfo/article/details/7785975" target="_blank">http://blog.csdn.net/aminfo/article/details/7785975</a>

顺便说明一点,这篇博客中作者提到的缺点:反应速度较慢。前面提到我也越到了同样的问题,也已经给出了解决方案。

(标注了原文链接的文章除外)

android模拟按键问题总结[使用IWindowManager.injectKeyEvent方法]

<a href="http://blog.csdn.net/xudongdong99/article/details/8857173" target="_blank">http://blog.csdn.net/xudongdong99/article/details/8857173</a>

Android中使用隐藏API(大量图解)  

<a href="http://163liufuliang.blog.163.com/blog/static/331651862013119114431760/" target="_blank">http://163liufuliang.blog.163.com/blog/static/331651862013119114431760/</a>

通过Runtime实现,代码如下:

try  

{  

    String keyCommand = "input keyevent " + KeyEvent.KEYCODE_MENU;  

    Runtime runtime = Runtime.getRuntime();  

    Process proc = runtime.exec(keyCommand);  

}  

catch (IOException e)  

    // TODO Auto-generated catch block  

    e.printStackTrace();  

这个代码是模拟菜单键,模拟其它按键只需将KeyEvent.KEYCODE_MENU替换成其它键值。

缺点:反应速度较慢

以下附带各KeyCode值:

KEYCODE_UNKNOWN=0;   

KEYCODE_SOFT_LEFT=1;   

KEYCODE_SOFT_RIGHT=2;   

KEYCODE_HOME=3;   

KEYCODE_BACK=4;   

KEYCODE_CALL=5;   

KEYCODE_ENDCALL=6;   

KEYCODE_0=7;   

KEYCODE_1=8;   

KEYCODE_2=9;   

KEYCODE_3=10;   

KEYCODE_4=11;   

KEYCODE_5=12;   

KEYCODE_6=13;   

KEYCODE_7=14;   

KEYCODE_8=15;   

KEYCODE_9=16;   

KEYCODE_STAR=17;   

KEYCODE_POUND=18;   

KEYCODE_DPAD_UP=19;   

KEYCODE_DPAD_DOWN=20;   

KEYCODE_DPAD_LEFT=21;   

KEYCODE_DPAD_RIGHT=22;   

KEYCODE_DPAD_CENTER=23;   

KEYCODE_VOLUME_UP=24;   

KEYCODE_VOLUME_DOWN=25;   

KEYCODE_POWER=26;   

KEYCODE_CAMERA=27;   

KEYCODE_CLEAR=28;   

KEYCODE_A=29;   

KEYCODE_B=30;   

KEYCODE_C=31;   

KEYCODE_D=32;   

KEYCODE_E=33;   

KEYCODE_F=34;   

KEYCODE_G=35;   

KEYCODE_H=36;   

KEYCODE_I=37;   

KEYCODE_J=38;   

KEYCODE_K=39;   

KEYCODE_L=40;   

KEYCODE_M=41;   

KEYCODE_N=42;   

KEYCODE_O=43;   

KEYCODE_P=44;   

KEYCODE_Q=45;   

KEYCODE_R=46;   

KEYCODE_S=47;   

KEYCODE_T=48;   

KEYCODE_U=49;   

KEYCODE_V=50;   

KEYCODE_W=51;   

KEYCODE_X=52;   

KEYCODE_Y=53;   

KEYCODE_Z=54;   

KEYCODE_COMMA=55;   

KEYCODE_PERIOD=56;   

KEYCODE_ALT_LEFT=57;   

KEYCODE_ALT_RIGHT=58;   

KEYCODE_SHIFT_LEFT=59;   

KEYCODE_SHIFT_RIGHT=60;   

KEYCODE_TAB=61;   

KEYCODE_SPACE=62;   

KEYCODE_SYM=63;   

KEYCODE_EXPLORER=64;   

KEYCODE_ENVELOPE=65;   

KEYCODE_ENTER=66;   

KEYCODE_DEL=67;   

KEYCODE_GRAVE=68;   

KEYCODE_MINUS=69;   

KEYCODE_EQUALS=70;   

KEYCODE_LEFT_BRACKET=71;   

KEYCODE_RIGHT_BRACKET=72;   

KEYCODE_BACKSLASH=73;   

KEYCODE_SEMICOLON=74;   

KEYCODE_APOSTROPHE=75;   

KEYCODE_SLASH=76;   

KEYCODE_AT=77;   

KEYCODE_NUM=78;   

KEYCODE_HEADSETHOOK=79;   

KEYCODE_FOCUS=80;//*Camera*focus   

KEYCODE_PLUS=81;   

KEYCODE_MENU=82;   

KEYCODE_NOTIFICATION=83;   

KEYCODE_SEARCH=84;   

KEYCODE_MEDIA_PLAY_PAUSE=85;   

KEYCODE_MEDIA_STOP=86;   

KEYCODE_MEDIA_NEXT=87;   

KEYCODE_MEDIA_PREVIOUS=88;   

KEYCODE_MEDIA_REWIND=89;   

KEYCODE_MEDIA_FAST_FORWARD=90;   

KEYCODE_MUTE=91;