解決使用Instrumentation發送事件慢的問題

使用Instrumentation發送事件時發現每次都要幾十毫秒,原因是它使用的模式是InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH(2),而不是INJECT_INPUT_EVENT_MODE_ASYNC(0)。

    public void sendPointerSync(MotionEvent event) {
        validateNotAppThread();
        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
        }
        try {
            WindowManagerGlobal.getWindowManagerService().injectInputAfterTransactionsApplied(event,
                    InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
        } catch (RemoteException e) {
        }
    }

要想異步發送事件,可以通過反射調用InputManager.getInstance().injectInputEvent()。

public class XXXUtil {
    private static InputManager sInputManager;
    private static Method sInjectInputEventMethod;

    public static InputManager getInputManager() {
        if (sInputManager == null) {
            try{
                Class<?> inputManagerClass=InputManager.class;
                Method getInstanceMethod = inputManagerClass.getMethod("getInstance");
                sInputManager = (InputManager)getInstanceMethod.invoke(inputManagerClass);
            }catch (Exception e){
            }
        }
        return sInputManager;
    }


    public static Method getInjectInputEventMethod() {
        if (sInjectInputEventMethod == null) {
            try{
                Class<?> inputManagerClass=InputManager.class;
                sInjectInputEventMethod = inputManagerClass.getMethod("injectInputEvent", InputEvent.class, int.class);
            }catch (Exception e){
            }
        }
        return sInjectInputEventMethod;
    }
    

    private static void sendPointerEvent(MotionEvent event) {
        try {
            if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
                event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
            }
            getInjectInputEventMethod().invoke(getInputManager(), event, 0);
        } catch (Exception e) {
        }
    }
    
    private static void sendKeyEvent(KeyEvent event) {
        long downTime = event.getDownTime();
        long eventTime = event.getEventTime();
        int action = event.getAction();
        int code = event.getKeyCode();
        int repeatCount = event.getRepeatCount();
        int metaState = event.getMetaState();
        int deviceId = event.getDeviceId();
        int scancode = event.getScanCode();
        int source = event.getSource();
        int flags = event.getFlags();
        if (source == InputDevice.SOURCE_UNKNOWN) {
            source = InputDevice.SOURCE_KEYBOARD;
        }
        if (eventTime == 0) {
            eventTime = SystemClock.uptimeMillis();
        }
        if (downTime == 0) {
            downTime = eventTime;
        }
        KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
                deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
        try {
            getInjectInputEventMethod().invoke(getInputManager(), newEvent, 0);
        }catch (Exception e){
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章