Of course! Let's dive deep into monkeyrunner and its Python scripting capabilities.

What is MonkeyRunner?
monkeyrunner is a test automation tool that comes with the Android SDK. It allows you to write Python scripts that control an Android device or emulator programmatically. Think of it as a remote control for your Android device, where the remote is a Python script.
Key Characteristics:
- API-based Control: It uses a specific API to connect to a device and send commands.
- Multi-Device Support: A single script can control multiple connected devices or emulators simultaneously.
- Functional Testing: It's primarily used for functional testing, UI testing, and automating repetitive tasks.
- Deprecated (Important!): Google officially deprecated
monkeyrunnerin 2025. The modern, recommended replacement is Espresso for UI testing and UI Automator for cross-app testing. However,monkeyrunneris still useful for specific, non-standard tasks.
How MonkeyRunner Works: The Core Components
The monkeyrunner API is built around three main classes:
-
MonkeyRunner: The main class that provides connection and utility functions.
(图片来源网络,侵删)MonkeyRunner.waitForConnection(): Connects your script to a device or emulator.MonkeyRunner.sleep(): Pauses script execution for a specified number of seconds.
-
MonkeyDevice: Represents the device or emulator you are controlling. This is where you'll spend most of your time.- Device Actions:
touch(x, y, 'DOWN_AND_UP'): Simulates a tap, touch, or drag.type(string): Simulates typing text into a text field.press('KEYCODE_HOME'): Simulates pressing a hardware button.reboot(): Reboots the device.install(path): Installs an APK file.uninstall(package_name): Uninstalls an app.wake(): Wakes up the device.
- Information Gathering:
getProperty(property): Gets a system property (e.g.,ro.build.version.sdk).getDisplayInfo(): Gets the screen resolution (width, height, density).getSystemShell(command): Executes a shell command and returns the output.
- Device Actions:
-
MonkeyImage: Represents a screenshot of the device's display.takeSnapshot(): Captures the current screen and returns aMonkeyImageobject.writeToFile(filepath, 'png'): Saves theMonkeyImageto a PNG file.sameAs(other_image, percent): Compares twoMonkeyImageobjects to see if they are visually similar.
Step-by-Step Guide: Creating and Running a Script
Step 1: Prerequisites
- Install Android SDK: Make sure you have the Android SDK installed.
- Add
toolsto PATH: Themonkeyrunnerexecutable is located in theandroid-sdk/tools/directory. Add this directory to your system's PATH for easy access. - Python: Ensure you have Python installed on your machine.
- Device/Emulator: Have an Android device connected via USB (with USB debugging enabled) or an Android emulator running.
Step 2: The "Hello World" of MonkeyRunner: A Simple Tap
This script will connect to a device, wait for 2 seconds, and then tap the screen at coordinates (500, 500).
File: simple_tap.py
# Import the necessary classes from the monkeyrunner module
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
# Connect to the current device. The connection will time out after 40 seconds.
# If no device is connected, it will wait until one is.
device = MonkeyRunner.waitForConnection(40)
# Check if the connection was successful
if device is None:
print("Error: Could not connect to device.")
exit(1)
# Get the display information to understand the screen size
display_info = device.getDisplayInfo()
screen_width = display_info['width']
screen_height = display_info['height']
print(f"Device connected. Screen size: {screen_width}x{screen_height}")
# Wait for the device to be ready
MonkeyRunner.sleep(2)
# Tap the screen at the center (x=500, y=500)
# The third argument 'DOWN_AND_UP' simulates a quick tap.
# You could also use 'DOWN' and 'UP' separately for a drag action.
print("Tapping the screen at (500, 500)...")
device.touch(500, 500, MonkeyDevice.DOWN_AND_UP)
print("Script finished.")
Step 3: Running the Script
-
Open your terminal or command prompt.
-
Navigate to the directory where you saved
simple_tap.py. -
Run the script using the
monkeyrunnercommand:monkeyrunner simple_tap.py
You should see the output in your terminal and your device/emulator should register a tap at the specified coordinates.
Practical Example: Automating a Login Flow
This is a more realistic example. It will open a login screen, enter a username and password, and tap the login button.
Assumptions:
- The app under test is already installed.
- The login screen is the main activity of the app.
- We know the coordinates of the username field, password field, and login button.
File: login_test.py
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage
# --- Configuration ---
PACKAGE_NAME = 'com.example.myapp' # Replace with your app's package name
ACTIVITY_NAME = '.MainActivity' # Replace with your app's main activity
USERNAME = 'testuser'
PASSWORD = 'password123'
# --- Coordinates (You need to find these for your device/resolution) ---
# Use the 'screencap' command or other tools to find these.
USERNAME_X, USERNAME_Y = 200, 400
PASSWORD_X, PASSWORD_Y = 200, 500
LOGIN_X, LOGIN_Y = 200, 600
# --- Script ---
# 1. Connect to the device
print("Connecting to device...")
device = MonkeyRunner.waitForConnection()
if not device:
print("Failed to connect to device.")
exit(1)
# 2. Launch the app
print(f"Launching {PACKAGE_NAME}/{ACTIVITY_NAME}...")
device.startActivity(component=f'{PACKAGE_NAME}/{ACTIVITY_NAME}')
MonkeyRunner.sleep(3) # Wait for the app to load
# 3. Take a screenshot of the initial state
print("Taking initial screenshot...")
initial_screenshot = device.takeSnapshot()
initial_screenshot.writeToFile('login_screen_initial.png', 'png')
# 4. Enter username
print(f"Entering username: {USERNAME}")
device.touch(USERNAME_X, USERNAME_Y, MonkeyDevice.DOWN_AND_UP)
MonkeyRunner.sleep(1)
device.type(USERNAME)
# 5. Enter password
print(f"Entering password: {PASSWORD}")
device.touch(PASSWORD_X, PASSWORD_Y, MonkeyDevice.DOWN_AND_UP)
MonkeyRunner.sleep(1)
device.type(PASSWORD)
# 6. Tap the login button
print("Tapping login button...")
device.touch(LOGIN_X, LOGIN_Y, MonkeyDevice.DOWN_AND_UP)
# 7. Wait for the action to complete and take a final screenshot
MonkeyRunner.sleep(5)
print("Taking final screenshot...")
final_screenshot = device.takeSnapshot()
final_screenshot.writeToFile('login_screen_final.png', 'png')
print("Login test script complete.")
How to Find Coordinates for Touch Actions
This is a common challenge. Here are a few methods:
-
The Brute-Force Method: Manually tap points on the screen while printing the coordinates. Create a small helper script for this:
# This script just prints touch coordinates from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice device = MonkeyRunner.waitForConnection() print("Touch a point on the screen. Press Ctrl+C to exit.") while True: # This is a blocking call, it waits for a touch event # Note: This is not a standard monkeyrunner function and may require # a different approach, like using 'getevent' from ADB shell. # A simpler way is to use logcat. passA more practical way is to use
adb shell geteventand filter for touch events, but it's complex. -
Screenshot and GIMP/Photoshop:
- Take a screenshot using
adb shell screencap -p /sdcard/screen.png. - Pull the image to your PC:
adb pull /sdcard/screen.png. - Open the image in an editor like GIMP or Photoshop. Move your mouse over the buttons/fields, and the status bar will show you the X and Y pixel coordinates.
- Take a screenshot using
-
UI Automator Viewer (Recommended):
- This is the modern, official way to get UI element information, including coordinates.
- Run
uiautomatorviewerfrom your Android SDKtools/directory. - It will open a window. Click the "Device Screenshot" button to capture the current screen of your connected device/emulator.
- The viewer will show you the UI hierarchy on the right, and you can hover over any element on the screenshot to see its properties, including
boundswhich gives you the coordinates (e.g.,[100,200][300,400]).
MonkeyRunner vs. Modern Alternatives (Espresso)
| Feature | MonkeyRunner | Espresso |
|---|---|---|
| Language | Python | Java/Kotlin |
| Control | Low-level (coordinates, raw events) | High-level (UI element IDs, text) |
| Robustness | Brittle. Breaks if UI layout changes (e.g., button moves). | Robust. Tests are tied to view resources (R.id.my_button), not coordinates. |
| Use Case | Simple automation, legacy systems, non-standard tasks. | Standard UI testing for Android apps. |
| Execution | Script runs on host machine, commands sent to device. | Test code runs directly on the device/emulator (as an Instrumentation). |
| Setup | Simple (monkeyrunner my_script.py). |
More complex (Gradle build system, Android Studio project setup). |
Conclusion: While monkeyrunner is powerful for quick-and-dirty automation or tasks that don't fit into a standard UI testing framework, Espresso is the industry standard for reliable, maintainable Android UI tests. You should prefer Espresso for all new testing projects.
