Android is nice because you can script the hell out of any part of it, and mess with the apps dynamically in any number of ways. For scripting the inputs, there are at least three ways to do it.
The good ol’ monkey with its monkeyrunner is the first thing that comes to mind: device.touch(x, y, ‘DOWN_AND_UP’) Sadly though, only some elements in a real app will honor monkey requests. After some logcatting we see how a monkey goes about generating a click:
D/MonkeyStub(12294): translateCommand: tap 551 1812 I/InputDispatcher( 714): Delivering touch to: action: 0x0 D/lights ( 714): button : 1 + D/lights ( 714): button : 1 - I/InputDispatcher( 714): Delivering touch to: action: 0x1
compared to a real tap on a screen:
D/InputReader( 714): Input event: value=1 when=2124062362000 I/InputReader( 714): Touch event's action is 0x0 (deviceType=0) [pCnt=1, s=0.122 ] when=2124062423000 I/InputDispatcher( 714): Delivering touch to: action: 0x0 D/lights ( 714): button : 1 + D/lights ( 714): button : 1 - D/InputReader( 714): Input event: value=0 when=2124153701000 I/InputReader( 714): Touch event's action is 0x1 (deviceType=0) [pCnt=1, s=] when=2124153701000 I/InputDispatcher( 714): Delivering touch to: action: 0x1
For those app UI elements that refuse to be monkeyed with, we can work with lower-level input events. One approach is to record a real tap (or any input sequence for that matter) with adb shell getevent and replay the same sequence with setevent like shown here. An easier approach is to simply use adb shell input with x and y:
adb shell input touchscreen tap 500 800
which gives us apparently a more palatable tap, and the following logcat output:
D/AndroidRuntime(16262): Calling main entry com.android.commands.input.Input I/Input (16262): injectMotionEvent: MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=500.0, y[0]=1870.0, toolType[0]=TOOL_TYPE_UNKNOWN, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=3300706, downTime=3300706, deviceId=0, source=0x1002 } I/InputDispatcher( 714): Delivering touch to: action: 0x0 D/lights ( 714): button : 1 + D/lights ( 714): button : 1 - I/Input (16262): injectMotionEvent: MotionEvent { action=ACTION_UP, id[0]=0, x[0]=500.0, y[0]=1870.0, toolType[0]=TOOL_TYPE_UNKNOWN, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=3300706, downTime=3300706, deviceId=0, source=0x1002 } I/InputDispatcher( 714): Delivering touch to: action: 0x1
Happy clicking!