android应用发送按键事件

模拟按键事件分发

主要用到了以下三种方法:

Instrumentation

标准写法如下,缺点是不能跨进程

	private void sentKey(final int keyCode) {
        Log.d(TAG,"---sentKey---, keyCode : " + keyCode);
        new Thread() {
            public void run() {
                try {
                    Instrumentation inst = new Instrumentation();
                    inst.sendKeyDownUpSync(keyCode);
                } catch (Exception e) {
                    Log.e(TAG, e.toString());
                }
            }
        }.start();
    }

模拟发送串口命令

参照串口调试执行input keyevent keycode
可跨进程,缺点按键响应时间过长,主观感觉有1-2s

	private void sentKey(int keyCode) {
        try {
            String command = "input keyevent " + keyCode;
            Log.i(TAG, "command = " + command);
            Runtime runtime = Runtime.getRuntime();
            Process proc = runtime.exec(command);
        } catch (IOException e) {
            Log.e(TAG, "Process exec failed!!!");
            Log.e(TAG, e.toString());
            e.printStackTrace();
        }
    }

InputManager类的injectInputEvent(非系统应用)

不能跨进程

 //public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0;
    private void sentKey(int keyCode) {
        Log.d(TAG,"---sentKey---, keyCode : " + keyCode);
        Log.d(TAG,"\n");
        new Thread() {
            public void run() {
                try {

                    long now = SystemClock.uptimeMillis();

                    KeyEvent down =  new KeyEvent(now, now,KeyEvent.ACTION_DOWN, keyCode, 0);
                    KeyEvent up = new KeyEvent(now, now,KeyEvent.ACTION_UP, keyCode, 0);

                    InputManager inputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
                    invokeInjectInputEventMethod(inputManager,down,0);
                    invokeInjectInputEventMethod(inputManager,up,0);

//                    InputManager.getInstance().injectInputEvent(down, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
//                    InputManager.getInstance().injectInputEvent(up, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
                } catch (Exception e) {
                    Log.e(TAG, "Simulate KeyEvent failed !!");
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private void invokeInjectInputEventMethod(InputManager inputManager, InputEvent event, int mode) {
        Class<?> clazz = null;
        Method injectInputEventMethod = null;
        Method recycleMethod = null;

        try {
            clazz = Class.forName("android.hardware.input.InputManager");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try {
            injectInputEventMethod = clazz.getMethod("injectInputEvent", InputEvent.class, int.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        try {
            injectInputEventMethod.invoke(inputManager, event, mode);
            // 准备回收event的方法
            recycleMethod = event.getClass().getMethod("recycle");
            //执行event的recycle方法
            recycleMethod.invoke(event);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }

InputManager类的injectInputEvent(系统应用)

最终使用的方案,在系统中编译了的,可跨进程,响应时间适中。

 	private void sentKey(int keyCode)  {
//        int actkey = getRcCode(keyCode);
        Log.i(TAG, "sentKey "+keyCode);
        Thread sendKeyEvent = new Thread() {
            @Override
            public void run() {
                try {

                    long now = SystemClock.uptimeMillis();

                    KeyEvent down =  new KeyEvent(now, now,KeyEvent.ACTION_DOWN, keyCode, 0);
                    KeyEvent up = new KeyEvent(now, now,KeyEvent.ACTION_UP, keyCode, 0);

                    InputManager.getInstance().injectInputEvent(down, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
                    InputManager.getInstance().injectInputEvent(up, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);


                } catch (Exception e) {
                    Log.e(TAG, "Simulate KeyEvent failed !!");
                    e.printStackTrace();
                }
            }
        };

        sendKeyEvent.start();
    }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐