Precisely Sending Events to Android Devices Using Monkey

Mar 20, 2019 · 587 words

Monkey is a program that runs on an Android device (emulator or physical device) and generates a large number of random user input events, such as clicks, touches, and gestures. Therefore, Monkey can be used for UI stress testing. For example, the following command starts a specific app and sends 500 random events:

bash
adb shell monkey -p your.package.name -v 500

However, the Monkey program also has a special --port option. When this option is enabled, Monkey runs in Automated Network Control mode, allowing it to precisely send specific KeyEvent and MotionEvent instances to an app. This provides a programmatic way to send user events as an alternative to the adb shell input command. For information regarding the adb shell input command, you can refer to this link. Testing shows that the user events supported by Monkey are more granular than those of the input command. For instance, the input command can only specify the duration for a swipe action, whereas Monkey can detailedly specify multiple finger movements during a swipe.

If you have the AOSP source code, you can find the README.NETWORK.txt file in the development/cmds/monkey/ directory, which contains simple documentation explaining the Automated Network Control protocol. Alternatively, you can access it here.

The following is a brief summary of the documentation:

Establishing a Connection

The monkey --port command starts the monkey server and listens on a specific port:

bash
adb shell monkey --port 1080

Then, I can send commands to the monkey server from the host machine via a TCP connection. Note that the monkey server only binds to localhost. Since the TCP protocol is supported by ADB, port forwarding needs to be configured:

bash
adb forward tcp:1080 tcp:1080

Now you can send commands to the monkey server.

Protocol Format

Different commands are separated by newlines. For commands completed successfully, monkey responds with OK; otherwise, it responds with ERROR. If a command has a return value, the value is placed on the same line as OK or ERROR, separated by a colon. The return value for an ERROR response is usually an error message. Below is an example of a request-response sequence:

text
key down menu
OK
touch monkey
ERROR: monkey not a number
getvar sdk
OK: donut
getvar foo
ERROR: no such var

Command List

wake

Wakes up the device to receive user input.

touch [down|up|move] x y

Sends a MotionEvent to simulate a user touching the screen. x and y are coordinates relative to the top-left corner. To simulate a swipe event, you can perform a touch down, followed by touch move, and finally a touch up.

tap x y

A simplified version of the touch command, equivalent to one touch down and one touch up.

key [down|up] keycode

Sends a KeyEvent. The keycode can be either text or an integer value. For example, since KeyEvent.KEYCODE_MENU = 82, sending either 82 or “KEYCODE_MENU” will work.

press keycode

A simplified version of the key command, equivalent to one key down and one key up.

type string

Simulates user keyboard input by generating KeyEvents.

flip [open|close]

Simulates the opening or closing of the keyboard.