继续在网上搜索安卓按键模拟(其实那时都不知道用什么关键字好了,能想到的关键字都用遍了,可是搜索出来的结果,都是以前提到的那几个依赖源码环境和系统权限的方案)。发现有不少介绍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"); } }