DittoMation Python API Reference
Complete reference for the Android class and all available methods.
Installation
Android Class
The main interface for controlling Android devices. Uses confidence scoring for robust element matching.
Constructor
Parameters:
- device (str, optional): Device serial number. If not provided, auto-detects the first connected device.
- min_confidence (float, optional): Minimum confidence threshold for element matching (0.0-1.0). Default is 0.3 (30%).
Raises:
- DeviceNotFoundError: If no device is connected.
Example:
# Auto-detect device with default 30% confidence threshold
android = Android()
# Connect to specific device with stricter matching
android = Android(device="emulator-5554", min_confidence=0.7)
# Adjust confidence threshold later
android.min_confidence = 0.5
See also: Confidence Scoring Guide for details on how matching works.
Gesture Methods
tap()
Tap at coordinates or on an element.
tap(
x_or_text: int | str = None,
y: int = None,
*,
id: str = None,
desc: str = None,
timeout: float = 5.0
) -> bool
Parameters:
- x_or_text: X coordinate (int) or element text to find (str)
- y: Y coordinate (required when x_or_text is int)
- id: Find element by resource-id
- desc: Find element by content-description
- timeout: Timeout for element search in seconds
Returns: True if successful, False otherwise.
Examples:
# Tap at coordinates
android.tap(500, 500)
# Tap element by text
android.tap("Login")
# Tap element by resource-id
android.tap(id="com.app:id/btn_submit")
# Tap element by content-description
android.tap(desc="Submit button")
# With custom timeout
android.tap("Submit", timeout=10)
long_press()
Long press at coordinates or on an element.
long_press(
x_or_text: int | str = None,
y: int = None,
*,
id: str = None,
desc: str = None,
duration_ms: int = 1000,
timeout: float = 5.0
) -> bool
Parameters:
- x_or_text: X coordinate (int) or element text (str)
- y: Y coordinate
- id: Find element by resource-id
- desc: Find element by content-description
- duration_ms: Press duration in milliseconds (default: 1000)
- timeout: Timeout for element search
Returns: True if successful.
Examples:
# Long press at coordinates
android.long_press(500, 500)
# Long press for 2 seconds
android.long_press(500, 500, duration_ms=2000)
# Long press element
android.long_press("Item to select")
swipe()
Swipe by direction or coordinates.
swipe(
x1_or_direction: int | str,
y1: int = None,
x2: int = None,
y2: int = None,
duration_ms: int = 300
) -> bool
Parameters:
- x1_or_direction: Start X coordinate (int) or direction string ("up", "down", "left", "right")
- y1: Start Y coordinate
- x2: End X coordinate
- y2: End Y coordinate
- duration_ms: Swipe duration in milliseconds
Returns: True if successful.
Examples:
# Swipe by direction (from screen center)
android.swipe("up")
android.swipe("down")
android.swipe("left")
android.swipe("right")
# Swipe by coordinates
android.swipe(500, 1500, 500, 500) # Swipe up
# Slow swipe
android.swipe("up", duration_ms=1000)
scroll()
Scroll in a direction.
Parameters:
- direction: "up", "down", "left", or "right"
- distance: Scroll distance as fraction of screen (0.0-1.0)
- duration_ms: Scroll duration in milliseconds
Returns: True if successful.
Examples:
# Scroll down (default)
android.scroll("down")
# Scroll up with longer distance
android.scroll("up", distance=0.8)
# Slow scroll
android.scroll("down", duration_ms=1000)
pinch()
Pinch gesture for zooming in/out.
pinch(
scale: float = 0.5,
center_x: int = None,
center_y: int = None,
duration_ms: int = 500
) -> bool
Parameters:
- scale: Scale factor (>1 zoom in, <1 zoom out)
- center_x: Center X of pinch (default: screen center)
- center_y: Center Y of pinch (default: screen center)
- duration_ms: Gesture duration
Returns: True if successful.
Note: This is an approximation using sequential swipes.
Examples:
# Zoom in
android.pinch(scale=2.0)
# Zoom out
android.pinch(scale=0.5)
# Pinch at specific location
android.pinch(scale=1.5, center_x=300, center_y=400)
Input Methods
type()
Type text into the focused field.
Parameters:
- text: Text to type
- clear_first: Clear existing text before typing
Returns: True if successful.
Examples:
# Type text
android.type("Hello World")
# Clear field and type
android.type("new text", clear_first=True)
press_home()
Press the home button.
Returns: True if successful.
press_back()
Press the back button.
Returns: True if successful.
press_enter()
Press the enter key.
Returns: True if successful.
press_key()
Press any key by keycode.
Parameters:
- keycode: Android keycode string
Returns: True if successful.
Common Keycodes:
| Keycode | Description |
|---------|-------------|
| KEYCODE_HOME | Home button |
| KEYCODE_BACK | Back button |
| KEYCODE_MENU | Menu button |
| KEYCODE_ENTER | Enter key |
| KEYCODE_DEL | Backspace |
| KEYCODE_VOLUME_UP | Volume up |
| KEYCODE_VOLUME_DOWN | Volume down |
| KEYCODE_POWER | Power button |
| KEYCODE_CAMERA | Camera button |
| KEYCODE_SEARCH | Search |
Examples:
App Methods
open_app()
Open an app by name or package.
Parameters:
- app: App name (e.g., "Chrome") or package name (e.g., "com.android.chrome")
Returns: True if app launch was initiated.
Examples:
# Open by name
android.open_app("Chrome")
android.open_app("Settings")
android.open_app("Camera")
# Open by package
android.open_app("com.android.chrome")
android.open_app("com.google.android.youtube")
Supported App Names: The following common app names are recognized: - Chrome, Settings, Camera, Phone, Messages - Gmail, YouTube, Maps, Play Store - Calculator, Clock, Calendar, Contacts, Files
current_app()
Get information about the current foreground app.
Returns: Dictionary with keys:
- package: Package name (e.g., "com.android.chrome")
- activity: Current activity name
Example:
info = android.current_app()
print(f"Package: {info['package']}")
print(f"Activity: {info['activity']}")
Screen Methods
screenshot()
Take a screenshot.
Parameters:
- filename: Output filename (default: auto-generated with timestamp)
Returns: Absolute path to saved screenshot.
Examples:
# Auto-named screenshot
path = android.screenshot()
# Named screenshot
path = android.screenshot("login_screen.png")
screen_size()
Get the screen dimensions.
Returns: Tuple of (width, height) in pixels.
Example:
Element Methods
find()
Find an element on screen using confidence scoring.
find(
text: str = None,
*,
id: str = None,
desc: str = None,
timeout: float = 0,
min_confidence: float = None
) -> dict | None
Parameters:
- text: Find by visible text (fuzzy matching supported)
- id: Find by resource-id (partial match supported)
- desc: Find by content-description (fuzzy matching supported)
- timeout: Timeout in seconds (0 = single attempt)
- min_confidence: Minimum confidence threshold (0.0-1.0), overrides instance default
Returns: Element dictionary or None if no match above confidence threshold.
Element Dictionary:
{
"class": "android.widget.Button",
"resource_id": "com.app:id/btn_login",
"text": "Login",
"content_desc": "",
"bounds": (100, 200, 300, 250),
"clickable": True,
"enabled": True,
# ... more properties
}
Examples:
# Find by text (uses default 30% threshold)
element = android.find("Login")
# Find by ID
element = android.find(id="btn_submit")
# Fuzzy matching with typo (will match "Settings")
element = android.find("Setings", min_confidence=0.6)
# Strict matching (require 90% confidence)
element = android.find("Submit", min_confidence=0.9)
find_with_confidence()
Find an element with detailed confidence information.
find_with_confidence(
text: str = None,
*,
id: str = None,
desc: str = None,
timeout: float = 0,
min_confidence: float = None
) -> MatchResult | None
Parameters: Same as find()
Returns: MatchResult object with:
- element: The matched element dictionary
- confidence: Confidence score (0.0-1.0)
- match_details: Dictionary showing score breakdown
Examples:
result = android.find_with_confidence("Login")
if result:
print(f"Found: {result.element['text']}")
print(f"Confidence: {result.confidence:.0%}")
print(f"Details: {result.match_details}")
# Output:
# Found: Login
# Confidence: 100%
# Details: {'text_exact': 1.0, 'clickable_bonus': 0.05}
get_confidence()
Get the confidence score for an element match without a minimum threshold.
Returns: Confidence score (0.0-1.0), or 0.0 if no match found.
Examples:
# Check how well a search matches
score = android.get_confidence("Setings") # typo
print(f"Confidence: {score:.0%}") # Output: Confidence: 78%
# Use for conditional logic
if android.get_confidence("Purchase") > 0.9:
android.tap("Purchase")
else:
print("Purchase button not clearly visible - skipping")
find_all()
Find all matching elements on screen.
find_all(
text: str = None,
*,
id: str = None,
desc: str = None,
class_name: str = None
) -> list[dict]
Parameters:
- text: Find by visible text (substring match)
- id: Find by resource-id (substring match)
- desc: Find by content-description (substring match)
- class_name: Find by class name (substring match)
Returns: List of matching element dictionaries.
Examples:
# Find all buttons
buttons = android.find_all(class_name="Button")
# Find all items containing "Item"
items = android.find_all(text="Item")
for item in items:
print(item['text'])
wait_for()
Wait for an element to appear.
wait_for(
text: str = None,
*,
id: str = None,
desc: str = None,
timeout: float = 10.0,
poll_interval: float = 0.5
) -> dict | None
Parameters:
- text: Find by visible text
- id: Find by resource-id
- desc: Find by content-description
- timeout: Maximum wait time in seconds
- poll_interval: Time between checks in seconds
Returns: Element dictionary if found, None if timeout.
Examples:
# Wait for element
element = android.wait_for("Welcome", timeout=15)
# Wait for loading to complete
android.wait_for(id="main_content", timeout=30)
exists()
Check if an element exists on screen.
Parameters:
- text: Find by visible text
- id: Find by resource-id
- desc: Find by content-description
Returns: True if element exists.
Example:
Device Methods
devices()
List all connected devices.
Returns: List of dictionaries with keys:
- serial: Device serial number
- status: Device status ("device", "offline", "unauthorized")
Example:
info()
Get device information.
Returns: Dictionary with device properties:
- serial: Device serial number
- model: Device model name
- manufacturer: Device manufacturer
- android_version: Android version
- sdk_version: SDK API level
- screen_size: Tuple of (width, height)
Example:
info = android.info()
print(f"Model: {info['model']}")
print(f"Android: {info['android_version']}")
print(f"Screen: {info['screen_size'][0]}x{info['screen_size'][1]}")
Automation Class
The Automation class provides a high-level interface for running multi-step automation scripts with variables, conditions, and loops.
Constructor
Automation(
device: str = None,
min_confidence: float = 0.3,
default_timeout: float = 5.0,
default_retries: int = 2,
step_delay: float = 0.3,
stop_on_failure: bool = True,
screenshot_on_failure: bool = False,
initial_vars: Dict[str, Any] = None
)
Parameters:
- device: Device serial (auto-detect if None)
- min_confidence: Default confidence for element matching
- default_timeout: Default timeout for element search
- default_retries: Default retry count per step
- step_delay: Delay between steps in seconds
- stop_on_failure: Stop on first failure
- screenshot_on_failure: Capture screenshot on failure
- initial_vars: Initial variables for the context
run()
Execute a list of automation steps.
Example:
from core.automation import Automation, Step
auto = Automation(initial_vars={"username": "test"})
steps = [
Step(action="open", app="MyApp"),
Step(action="tap", text="Login"),
Step(action="type", value="{{username}}"),
]
result = auto.run(steps)
print(result.summary())
run_from_file()
Load and run automation from a JSON file.
Example:
Variable Methods
# Set a variable
auto.set_variable("count", 5)
# Get a variable
value = auto.get_variable("count", default=0)
# Access context directly
ctx = auto.context
Supported Step Types
| Action | Description |
|---|---|
tap |
Tap element or coordinates |
long_press |
Long press element |
swipe |
Swipe gesture |
scroll |
Scroll gesture |
type |
Type text |
press |
Press device button |
open |
Open app |
wait |
Wait for duration |
wait_for |
Wait for element |
assert_exists |
Assert element exists |
assert_not_exists |
Assert element doesn't exist |
screenshot |
Take screenshot |
set_variable |
Set variable value |
extract |
Extract data from element |
if |
Conditional branching |
for |
For loop |
while |
While loop |
until |
Until loop |
break |
Break from loop |
continue |
Continue to next iteration |
log |
Log message |
assert |
Assert condition |
See also: Variables and Control Flow Guide for detailed documentation.
Exception Classes
Import exceptions for error handling:
from core.exceptions import (
DittoMationError, # Base exception
DeviceNotFoundError, # No device connected
DeviceOfflineError, # Device is offline
ElementNotFoundError, # Element not found
ADBCommandError, # ADB command failed
ADBTimeoutError, # ADB command timed out
# Variables & Expressions
ExpressionError, # Expression evaluation failed
UnsafeExpressionError, # Unsafe expression blocked
VariableNotFoundError, # Variable not defined
# Control Flow
LoopLimitError, # Loop exceeded max iterations
ControlFlowError, # Control flow error
InvalidControlFlowError, # break/continue outside loop
AssertionFailedError, # Assert condition failed
)
Example:
from core import Android
from core.exceptions import DeviceNotFoundError, VariableNotFoundError
try:
android = Android()
except DeviceNotFoundError as e:
print(f"Error: {e.message}")
print(f"Hint: {e.hint}")
Complete Example
from core import Android
from core.exceptions import DeviceNotFoundError
import time
def automate_settings():
"""Example: Navigate Settings and take screenshots."""
try:
android = Android()
except DeviceNotFoundError:
print("Please connect a device")
return
# Print device info
info = android.info()
print(f"Connected to: {info['model']} (Android {info['android_version']})")
# Open Settings
android.open_app("Settings")
time.sleep(2)
# Take initial screenshot
android.screenshot("settings_home.png")
# Look for Network settings
if android.wait_for("Network", timeout=5):
android.tap("Network")
time.sleep(1)
android.screenshot("settings_network.png")
# Go back
android.press_back()
# Scroll and find Display
for _ in range(3):
if android.exists("Display"):
android.tap("Display")
break
android.scroll("down")
# Return home
android.press_home()
print("Automation complete!")
if __name__ == "__main__":
automate_settings()