Cornstalks
Cornstalks

Reputation: 38228

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?

Upvotes: 4

Views: 4154

Answers (3)

tiper
tiper

Reputation: 1

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.

Upvotes: 0

JulianHe
JulianHe

Reputation: 11

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();
}

Upvotes: 1

Durairaj Packirisamy
Durairaj Packirisamy

Reputation: 4725

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.

Upvotes: 2

Related Questions