简体   繁体   中英

Why is there no InputManager.getInstance() for me? And injectInputEvent()?

I'm trying to develop a service that injects touch events to the system while the service interacts with some hardware/remote server. I've googled and everyone suggests using the InputManager class, referencing Monkey as an example project to follow.

However, there is no getInstance() method for me in InputManager ! All I have access to is exactly what the documentation shows. No getInstance() method, and most importantly, no injectInputEvent() method.

My build target SDK is Android 4.1.2, and my AndroidManifest.xml file specifies a target SDK version of 16 (I've tried changing the min target to 16 too, which didn't help (plus I'd like to keep it at 8 if possible)).

How on earth can I use InputManager like Monkey does? Where are the methods Monkey is using, and why can't I use them?

You cannot inject input events to one application from other application. Also you cannot inject events to your own application from within application. https://groups.google.com/forum/?fromgroups=#!topic/android-developers/N5R9rMJjgzk%5B1-25%5D

If you want to automate, you can use monkeyrunner scripts to do the same.

Class cl = InputManager.class;
try {
    Method method = cl.getMethod("getInstance");
    Object result = method.invoke(cl);
    InputManager im = (InputManager) result;
    method = cl.getMethod("injectInputEvent", InputEvent.class, int.class);
    method.invoke(im, event, 2);
}
catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}  catch (IllegalArgumentException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
} catch (NoSuchMethodException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}catch (InvocationTargetException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Maybe this is a bit late but could be helpful for future reference.

Method 1: Using an instrumentation object

Instrumentation instrumentation = new Instrumentation();
instrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
instrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));

Method 2: Using internal APIs with reflection

This method uses reflection to access internal APIs.

private void injectInputEvent(KeyEvent event) {
    try {
        getInjectInputEvent().invoke(getInputManager(), event, 2);
    } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
        e.printStackTrace();
    }
}

private static Method getInjectInputEvent() throws NoSuchMethodException {

    Class<InputManager> cl = InputManager.class;
    Method method = cl.getDeclaredMethod("injectInputEvent", InputEvent.class, int.class);
    method.setAccessible(true);
    return method;
}

private static InputManager getInputManager() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    Class<InputManager> cl = InputManager.class;
    Method method = cl.getDeclaredMethod("getInstance");
    method.setAccessible(true);
    return (InputManager) method.invoke(cl);
}

injectInputEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
injectInputEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));

Please note that method 1 is a clean solution based on public API and internally it uses the same calls from method 2 .

Also note that neither of this two methods can be invoked from the MainThread .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM