Reputation: 38228
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
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
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
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