
Android Use
- 87 installs
- 32 repo stars
- Updated January 30, 2026
- shehbajdhillon/android-use
Helps with ai & agent building tasks.
About
android-use is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- android-use
- AI & Agent Building
- AI-coding skill
Android Use by the numbers
- 87 all-time installs (skills.sh)
- Ranked #4,982 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/shehbajdhillon/android-use --skill android-useAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 87 |
|---|---|
| repo stars | ★ 32 |
| Last updated | January 30, 2026 |
| Repository | shehbajdhillon/android-use ↗ |
What it does
Helps with ai & agent building tasks.
Files
Android Device Control Skill
This skill enables you to control Android devices connected via ADB (Android Debug Bridge). You act as both the reasoning and execution engine - reading the device's UI state directly and deciding what actions to take.
Prerequisites
- Android device connected via USB with USB debugging enabled
- ADB installed and accessible in PATH
- Device authorized for debugging (accepted the "Allow USB debugging?" prompt)
Multi-Device Support
All scripts support the -s <serial> flag to target a specific device. This is essential when multiple devices are connected (e.g., a physical phone AND an emulator).
Identifying Devices
Run scripts/check-device.sh to see all connected devices:
Multiple devices connected (2):
[PHYSICAL] 1A051FDF6007PA - Pixel 6
[EMULATOR] emulator-5554 - sdk_gphone64_arm64
Use -s <serial> to specify which device to use.Choosing the Right Device
When the user mentions:
- "phone", "my phone", "physical device" → Use the
[PHYSICAL]device - "emulator", "virtual device", "AVD" → Use the
[EMULATOR]device - If unclear, ask the user which device they want to target
Using the Serial Flag
Once you identify the target device, pass -s <serial> to ALL subsequent scripts:
# Check specific device
scripts/check-device.sh -s 1A051FDF6007PA
# All actions on that device
scripts/get-screen.sh -s 1A051FDF6007PA
scripts/tap.sh -s 1A051FDF6007PA 540 960
scripts/launch-app.sh -s 1A051FDF6007PA chromeImportant: Be consistent - use the same serial for all commands in a session.
Core Workflow
When given a task, follow this perception-action loop:
1. Check device connection - Run scripts/check-device.sh first
- If multiple devices: identify target based on user intent or ask
- Note the serial number for subsequent commands
2. Get current screen state - Run scripts/get-screen.sh [-s serial] to dump UI hierarchy 3. Analyze the XML - Read the accessibility tree to understand what's on screen 4. Decide next action - Based on goal + current state, choose an action 5. Execute action - Run the appropriate script with -s serial if needed 6. Wait briefly - Allow UI to update (typically 500ms-1s) 7. Repeat - Go back to step 2 until goal is achieved
Reading UI XML
The get-screen.sh script outputs Android's accessibility XML. Key attributes to look for:
<node index="0" text="Settings" resource-id="com.android.settings:id/title"
class="android.widget.TextView" content-desc=""
bounds="[42,234][1038,345]" clickable="true" />Important attributes:
text- Visible text on the elementcontent-desc- Accessibility description (useful for icons)resource-id- Unique identifier for the elementbounds- Screen coordinates as[left,top][right,bottom]clickable- Whether element responds to tapsscrollable- Whether element can be scrolledfocused- Whether element has input focus
Calculating tap coordinates: From bounds="[left,top][right,bottom]", calculate center:
- x = (left + right) / 2
- y = (top + bottom) / 2
Example: bounds="[42,234][1038,345]" → tap at x=540, y=289
Available Scripts
All scripts are in the scripts/ directory. Run them via bash.
All scripts support `-s <serial>` to target a specific device.
Device Management
| Script | Args | Description |
|---|---|---|
check-device.sh | [-s serial] | List devices / verify connection |
wake.sh | [-s serial] | Wake device and dismiss lock screen |
screenshot.sh | [-s serial] | Capture screen image |
Screen Reading
| Script | Args | Description |
|---|---|---|
get-screen.sh | [-s serial] | Dump UI accessibility tree |
Input Actions
| Script | Args | Description |
|---|---|---|
tap.sh | [-s serial] x y | Tap at coordinates |
type-text.sh | [-s serial] "text" | Type text string |
swipe.sh | [-s serial] direction | Swipe up/down/left/right |
key.sh | [-s serial] keyname | Press key (home/back/enter/recent) |
App Management
| Script | Args | Description |
|---|---|---|
launch-app.sh | [-s serial] package_or_name | Launch app by package or search by name |
install-apk.sh | [-s serial] path/to/file.apk | Install APK to device |
Action Guidelines
When to tap
- Target clickable elements
- Always calculate center from bounds
- Prefer elements with
clickable="true"
When to type
- After tapping a text input field
- The field should have
focused="true"orclass="android.widget.EditText" - Clear existing text first if needed (select all + delete)
When to swipe
- To scroll lists or pages
- To navigate between screens (e.g., swipe left/right for tabs)
- Directions:
up(scroll down),down(scroll up),left,right
When to use keys
home- Return to home screenback- Go back / close dialogsenter- Submit forms / confirmrecent- Open recent apps
When to take screenshots
- For visual debugging when XML doesn't capture enough info
- To verify visual state (colors, images, etc.)
- When the task requires visual confirmation
When to wake the device
- Before starting any task (device may have gone to sleep)
- If
get-screen.shreturns empty or minimal XML - If actions don't seem to be working (screen may be off)
- Note: Won't bypass PIN/pattern/password - user must unlock manually
Common Patterns
Opening an app
# By package name (fastest)
scripts/launch-app.sh com.android.chrome
# By app name (searches installed apps)
scripts/launch-app.sh "Chrome"Tapping a button
1. Get screen: scripts/get-screen.sh 2. Find element with matching text/content-desc 3. Calculate center from bounds 4. Tap: scripts/tap.sh 540 289
Entering text in a field
1. Tap the text field to focus it 2. Wait for keyboard 3. Type: scripts/type-text.sh "your text here" 4. Press enter if needed: scripts/key.sh enter
Scrolling to find content
1. Get screen to check if target is visible 2. If not found, swipe: scripts/swipe.sh up 3. Get screen again, repeat until found or reached end
Handling dialogs/popups
- Look for elements with text like "OK", "Allow", "Accept", "Cancel"
- Tap the appropriate button
- Or press back to dismiss:
scripts/key.sh back
Error Handling
No device connected
- Check USB connection
- Verify USB debugging is enabled
- Run
adb devicesmanually to troubleshoot
Element not found
- The UI may have changed - get fresh screen dump
- Try scrolling to find the element
- Element might be in a different screen/state
Action didn't work
- Wait longer between actions (UI might be slow)
- Verify coordinates are correct
- Check if a popup/dialog appeared
App not responding
- Press home and reopen the app
- Or force close and restart
Example Sessions
Single Device
User request: "Open Chrome and search for weather"
1. scripts/check-device.sh
→ Device connected: Pixel 6
→ Serial: 1A051FDF6007PA
→ Type: Physical
2. scripts/launch-app.sh com.android.chrome
→ Chrome launched
3. scripts/get-screen.sh
→ [Read XML, find search/URL bar]
→ Found: bounds="[0,141][1080,228]" resource-id="com.android.chrome:id/url_bar"
→ Center: x=540, y=184
4. scripts/tap.sh 540 184
→ Tapped URL bar
5. scripts/get-screen.sh
→ [Verify keyboard appeared and field is focused]
6. scripts/type-text.sh "weather"
→ Typed "weather"
7. scripts/key.sh enter
→ Pressed enter to search
8. scripts/get-screen.sh
→ [Verify search results loaded]
→ Task complete!Multiple Devices
User request: "Open Settings on my phone" (with emulator also running)
1. scripts/check-device.sh
→ Multiple devices connected (2):
→ [PHYSICAL] 1A051FDF6007PA - Pixel 6
→ [EMULATOR] emulator-5554 - sdk_gphone64_arm64
User said "my phone" → target the PHYSICAL device
Serial to use: 1A051FDF6007PA
2. scripts/check-device.sh -s 1A051FDF6007PA
→ Device connected: Pixel 6
→ Serial: 1A051FDF6007PA
→ Type: Physical
→ Status: Ready
3. scripts/launch-app.sh -s 1A051FDF6007PA settings
→ Resolved 'settings' to package: com.android.settings
→ Launched: com.android.settings
4. scripts/get-screen.sh -s 1A051FDF6007PA
→ [Read XML, verify Settings app is open]
→ Task complete!Tips
- Be patient - Android UI can be slow, wait between actions
- Read carefully - The XML tells you exactly what's on screen
- Check your work - Get screen after each action to verify state
- Use screenshots - When XML doesn't give enough context
- Start simple - Break complex tasks into small steps
- Multi-device - Always check for multiple devices first; ask user if target is unclear
- Consistent serial - Once you pick a device, use
-s <serial>on ALL commands
android-use
A Claude Code skill for controlling Android devices via ADB. Uses Claude as the reasoning engine to read UI state and execute actions.
Installation
npx skills add https://github.com/shehbajdhillon/android-useOr just link this repo to your agent and let it figure it out.
Prerequisites
- ADB installed and in your PATH (Android SDK Platform Tools)
- Android device with USB debugging enabled
- Device authorized for debugging (accept the "Allow USB debugging?" prompt)
Usage
Once installed, invoke the skill with /android-use:
/android-use open Chrome and search for weather
/android-use take a screenshot
/android-use open Settings and enable dark modeThe skill uses a perception-action loop: 1. Dumps the UI accessibility tree 2. Claude reads the XML to understand screen state 3. Decides and executes the next action (tap, swipe, type, etc.) 4. Repeats until the task is complete
Multi-Device Support
All scripts support targeting specific devices with -s <serial>. When multiple devices are connected (e.g., physical phone + emulator), the agent will:
- Identify devices as
[PHYSICAL]or[EMULATOR] - Match user intent ("my phone" → physical device)
- Ask for clarification if unclear
Available Scripts
| Script | Description |
|---|---|
check-device.sh | List connected devices / verify connection |
wake.sh | Wake device and dismiss lock screen |
get-screen.sh | Dump UI accessibility tree (XML) |
tap.sh | Tap at x,y coordinates |
type-text.sh | Type text string |
swipe.sh | Swipe in direction (up/down/left/right) |
key.sh | Press key (home/back/enter/recent) |
screenshot.sh | Capture screen image |
launch-app.sh | Launch app by package name or search |
install-apk.sh | Install APK file to device |
How It Works
Unlike traditional Android automation that requires a separate LLM or parser, this skill leverages Claude's ability to directly read and understand Android's accessibility XML. Claude acts as both the reasoning and execution engine.
Example XML that Claude parses:
<node text="Settings" bounds="[42,234][1038,345]" clickable="true" />Claude calculates tap coordinates from bounds and decides actions based on the current UI state and user goal.
License
MIT
ADB Command Reference
Quick reference for Android Debug Bridge (ADB) commands used in this skill.
Device Management
# List connected devices
adb devices
# Get device serial
adb get-serialno
# Get device state
adb get-state
# Restart ADB server
adb kill-server
adb start-serverDevice Properties
# Get device model
adb shell getprop ro.product.model
# Get Android version
adb shell getprop ro.build.version.release
# Get screen size
adb shell wm size
# Get screen density
adb shell wm densityInput Commands
# Tap at coordinates
adb shell input tap <x> <y>
# Swipe from point to point
adb shell input swipe <x1> <y1> <x2> <y2> [duration_ms]
# Type text
adb shell input text "<text>"
# Press key
adb shell input keyevent <keycode>
# Long press
adb shell input swipe <x> <y> <x> <y> 1000Common Keycodes
| Key | Keycode |
|---|---|
| Home | 3 |
| Back | 4 |
| Call | 5 |
| End Call | 6 |
| Volume Up | 24 |
| Volume Down | 25 |
| Power | 26 |
| Camera | 27 |
| Menu | 82 |
| Enter | 66 |
| Delete/Backspace | 67 |
| Tab | 61 |
| Space | 62 |
| Escape | 111 |
| Recent Apps | 187 |
| Search | 84 |
D-Pad Keys
| Key | Keycode |
|---|---|
| Up | 19 |
| Down | 20 |
| Left | 21 |
| Right | 22 |
| Center | 23 |
Letter Keys (A-Z)
Keycodes 29-54 for A-Z
Number Keys (0-9)
Keycodes 7-16 for 0-9
UI Automation
# Dump UI hierarchy
adb shell uiautomator dump /sdcard/window_dump.xml
adb pull /sdcard/window_dump.xml
# Take screenshot
adb shell screencap -p /sdcard/screen.png
adb pull /sdcard/screen.png
# Record screen
adb shell screenrecord /sdcard/recording.mp4
# Stop with Ctrl+C, then pull the fileApp Management
# List installed packages
adb shell pm list packages
# List packages with names
adb shell pm list packages -f
# Search for package
adb shell pm list packages | grep <name>
# Install APK
adb install <path_to_apk>
adb install -r <path> # Replace existing
# Uninstall app
adb uninstall <package_name>
# Clear app data
adb shell pm clear <package_name>
# Force stop app
adb shell am force-stop <package_name>Activity Manager
# Start activity
adb shell am start -n <package>/<activity>
# Start app's main activity
adb shell monkey -p <package> -c android.intent.category.LAUNCHER 1
# Start with action
adb shell am start -a android.intent.action.VIEW -d <uri>
# Broadcast intent
adb shell am broadcast -a <action>File Operations
# Push file to device
adb push <local_path> <device_path>
# Pull file from device
adb pull <device_path> <local_path>
# List files
adb shell ls <path>
# Remove file
adb shell rm <path>Shell Commands
# Open shell
adb shell
# Run command
adb shell <command>
# Run as root (if available)
adb root
adb shellTroubleshooting
Device not found
1. Check USB connection 2. Enable USB debugging in Settings > Developer Options 3. Revoke and re-authorize USB debugging 4. Try different USB port/cable 5. Restart ADB server: adb kill-server && adb start-server
Unauthorized device
1. On device, revoke USB debugging authorizations 2. Reconnect USB 3. Accept the "Allow USB debugging?" prompt
Multiple devices
# Specify device
adb -s <serial> <command>
# Set default device
export ANDROID_SERIAL=<serial>Command not found
Ensure ADB is in your PATH:
# Check if ADB is installed
which adb
# Add to PATH if needed
export PATH=$PATH:/path/to/platform-toolsScreen Coordinates
Android coordinates start at top-left (0, 0):
- X increases to the right
- Y increases downward
Example on 1080x1920 screen:
- Top-left: (0, 0)
- Top-right: (1080, 0)
- Bottom-left: (0, 1920)
- Bottom-right: (1080, 1920)
- Center: (540, 960)
Parsing UI Bounds
The bounds attribute format: [left,top][right,bottom]
To calculate center for tapping:
x = (left + right) / 2
y = (top + bottom) / 2Example: bounds="[42,234][1038,345]"
- left=42, top=234, right=1038, bottom=345
- center_x = (42 + 1038) / 2 = 540
- center_y = (234 + 345) / 2 = 289
- Tap command:
adb shell input tap 540 289
#!/bin/bash
# Check if an Android device is connected via ADB
# Usage: check-device.sh [-s <serial>]
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: check-device.sh [-s <serial>]"; exit 1 ;;
esac
done
# Check if adb is available
if ! command -v adb &> /dev/null; then
echo "Error: adb is not installed or not in PATH"
exit 1
fi
# Get list of connected devices
devices=$(adb devices | grep -v "List of devices" | grep -v "^$" | grep -v "offline")
if [ -z "$devices" ]; then
echo "Error: No Android device connected"
echo ""
echo "Troubleshooting:"
echo "1. Connect your device via USB"
echo "2. Enable USB debugging in Developer Options"
echo "3. Accept the 'Allow USB debugging?' prompt on device"
echo "4. Run 'adb devices' to verify"
exit 1
fi
# Count connected devices
device_count=$(echo "$devices" | wc -l | tr -d ' ')
if [ "$device_count" -gt 1 ]; then
echo "Multiple devices connected ($device_count):"
echo ""
# List all devices with details
while IFS= read -r line; do
dev_serial=$(echo "$line" | awk '{print $1}')
dev_state=$(echo "$line" | awk '{print $2}')
if [ "$dev_state" = "device" ]; then
dev_model=$(adb -s "$dev_serial" shell getprop ro.product.model 2>/dev/null | tr -d '\r')
dev_type=$(adb -s "$dev_serial" shell getprop ro.build.characteristics 2>/dev/null | tr -d '\r')
# Determine if emulator or physical device
if [[ "$dev_serial" == emulator-* ]] || [[ "$dev_type" == *"emulator"* ]]; then
dev_label="[EMULATOR]"
else
dev_label="[PHYSICAL]"
fi
echo " $dev_label $dev_serial - $dev_model"
else
echo " [OFFLINE] $dev_serial - state: $dev_state"
fi
done <<< "$devices"
echo ""
if [ -z "$SERIAL" ]; then
echo "Use -s <serial> to specify which device to use."
echo "Example: check-device.sh -s $(echo "$devices" | head -1 | awk '{print $1}')"
exit 1
fi
fi
# If serial specified, verify it exists
if [ -n "$SERIAL" ]; then
if ! echo "$devices" | grep -q "^$SERIAL"; then
echo "Error: Device '$SERIAL' not found"
echo ""
echo "Available devices:"
echo "$devices" | awk '{print " " $1}'
exit 1
fi
device_serial="$SERIAL"
else
# Use first device
device_serial=$(echo "$devices" | head -1 | awk '{print $1}')
fi
device_state=$(echo "$devices" | grep "^$device_serial" | awk '{print $2}')
if [ "$device_state" != "device" ]; then
echo "Error: Device '$device_serial' is in state '$device_state' (expected 'device')"
exit 1
fi
# Get device model and info
device_model=$(adb -s "$device_serial" shell getprop ro.product.model 2>/dev/null | tr -d '\r')
android_version=$(adb -s "$device_serial" shell getprop ro.build.version.release 2>/dev/null | tr -d '\r')
dev_type=$(adb -s "$device_serial" shell getprop ro.build.characteristics 2>/dev/null | tr -d '\r')
# Determine device type
if [[ "$device_serial" == emulator-* ]] || [[ "$dev_type" == *"emulator"* ]]; then
device_type="Emulator"
else
device_type="Physical"
fi
echo "Device connected: $device_model"
echo "Serial: $device_serial"
echo "Type: $device_type"
echo "Android: $android_version"
echo "Status: Ready"
#!/bin/bash
# Dump the current UI hierarchy (accessibility tree) from the Android device
# Usage: get-screen.sh [-s <serial>]
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: get-screen.sh [-s <serial>]"; exit 1 ;;
esac
done
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
# Paths
DEVICE_PATH="/sdcard/window_dump.xml"
LOCAL_PATH="/tmp/android_ui_dump.xml"
# Dump UI hierarchy on device
$ADB_CMD shell uiautomator dump "$DEVICE_PATH" > /dev/null 2>&1
# Pull the file
$ADB_CMD pull "$DEVICE_PATH" "$LOCAL_PATH" > /dev/null 2>&1
# Clean up device file
$ADB_CMD shell rm -f "$DEVICE_PATH" > /dev/null 2>&1
# Output the XML content
cat "$LOCAL_PATH"
#!/bin/bash
# Install an APK file to the Android device
# Usage: install-apk.sh [-s <serial>] <path_to_apk>
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: install-apk.sh [-s <serial>] <path_to_apk>"; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
if [ $# -ne 1 ]; then
echo "Usage: install-apk.sh [-s <serial>] <path_to_apk>"
echo "Example: install-apk.sh /path/to/app.apk"
echo "Example: install-apk.sh -s emulator-5554 /path/to/app.apk"
exit 1
fi
apk_path="$1"
# Check if file exists
if [ ! -f "$apk_path" ]; then
echo "Error: APK file not found: $apk_path"
exit 1
fi
# Check if it's an APK file
if [[ ! "$apk_path" == *.apk ]]; then
echo "Warning: File does not have .apk extension"
fi
# Get file size
file_size=$(ls -lh "$apk_path" | awk '{print $5}')
echo "Installing APK: $apk_path"
echo "Size: $file_size"
echo ""
# Install the APK
# -r: replace existing application
# -t: allow test packages
# -d: allow version code downgrade
result=$($ADB_CMD install -r "$apk_path" 2>&1)
if echo "$result" | grep -q "Success"; then
echo "Installation successful!"
# Try to get the package name from the APK
if command -v aapt &> /dev/null; then
package=$(aapt dump badging "$apk_path" 2>/dev/null | grep "package:" | sed "s/.*name='//" | sed "s/'.*//")
if [ -n "$package" ]; then
echo "Package: $package"
fi
fi
else
echo "Installation failed!"
echo "$result"
exit 1
fi
#!/bin/bash
# Press a key on the Android device
# Usage: key.sh [-s <serial>] <keyname>
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: key.sh [-s <serial>] <keyname>"; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
if [ $# -ne 1 ]; then
echo "Usage: key.sh [-s <serial>] <keyname>"
echo "Keys: home, back, enter, recent, menu, search, power, volume_up, volume_down, tab, delete"
echo "Example: key.sh home"
echo "Example: key.sh -s 1A051FDF6007PA back"
exit 1
fi
keyname="$1"
# Map key names to Android keycodes
case "$keyname" in
home)
keycode=3
;;
back)
keycode=4
;;
enter|return)
keycode=66
;;
recent|recents|overview)
keycode=187
;;
menu)
keycode=82
;;
search)
keycode=84
;;
power)
keycode=26
;;
volume_up|vol_up)
keycode=24
;;
volume_down|vol_down)
keycode=25
;;
tab)
keycode=61
;;
delete|del|backspace)
keycode=67
;;
space)
keycode=62
;;
escape|esc)
keycode=111
;;
dpad_up)
keycode=19
;;
dpad_down)
keycode=20
;;
dpad_left)
keycode=21
;;
dpad_right)
keycode=22
;;
dpad_center)
keycode=23
;;
*)
# Check if it's a numeric keycode
if [[ "$keyname" =~ ^[0-9]+$ ]]; then
keycode=$keyname
else
echo "Error: Unknown key '$keyname'"
echo "Available keys: home, back, enter, recent, menu, search, power, volume_up, volume_down, tab, delete, space, escape"
echo "Or use numeric keycode directly"
exit 1
fi
;;
esac
$ADB_CMD shell input keyevent "$keycode"
echo "Pressed $keyname (keycode $keycode)"
#!/bin/bash
# Launch an app on the Android device by package name or app name
# Usage: launch-app.sh [-s <serial>] <package_name_or_app_name>
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: launch-app.sh [-s <serial>] <package_name_or_app_name>"; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
if [ $# -lt 1 ]; then
echo "Usage: launch-app.sh [-s <serial>] <package_name_or_app_name>"
echo "Examples:"
echo " launch-app.sh com.android.chrome"
echo " launch-app.sh Chrome"
echo " launch-app.sh -s emulator-5554 settings"
exit 1
fi
app="$1"
# Convert to lowercase for matching
app_lower=$(echo "$app" | tr '[:upper:]' '[:lower:]')
# Map common app names to package names
get_package() {
case "$1" in
chrome) echo "com.android.chrome" ;;
settings) echo "com.android.settings" ;;
phone|dialer) echo "com.android.dialer" ;;
messages|sms) echo "com.google.android.apps.messaging" ;;
camera) echo "com.android.camera" ;;
photos) echo "com.google.android.apps.photos" ;;
gmail) echo "com.google.android.gm" ;;
maps) echo "com.google.android.apps.maps" ;;
youtube) echo "com.google.android.youtube" ;;
playstore|play_store) echo "com.android.vending" ;;
calendar) echo "com.google.android.calendar" ;;
clock) echo "com.google.android.deskclock" ;;
calculator) echo "com.google.android.calculator" ;;
contacts) echo "com.android.contacts" ;;
files) echo "com.google.android.documentsui" ;;
whatsapp) echo "com.whatsapp" ;;
instagram) echo "com.instagram.android" ;;
facebook) echo "com.facebook.katana" ;;
twitter|x) echo "com.twitter.android" ;;
spotify) echo "com.spotify.music" ;;
netflix) echo "com.netflix.mediaclient" ;;
telegram) echo "org.telegram.messenger" ;;
discord) echo "com.discord" ;;
slack) echo "com.Slack" ;;
zoom) echo "us.zoom.videomeetings" ;;
teams) echo "com.microsoft.teams" ;;
outlook) echo "com.microsoft.office.outlook" ;;
drive) echo "com.google.android.apps.docs" ;;
keep|notes) echo "com.google.android.keep" ;;
*) echo "" ;;
esac
}
# Check if it's a known app name
package=$(get_package "$app_lower")
if [ -n "$package" ]; then
echo "Resolved '$app' to package: $package"
elif [[ "$app" == *"."* ]]; then
# Looks like a package name (contains dots)
package="$app"
else
# Try to find the package by searching installed apps
echo "Searching for app: $app"
# Get list of installed packages and their labels
matches=$($ADB_CMD shell pm list packages 2>/dev/null | grep -i "$app" | head -5)
if [ -z "$matches" ]; then
echo "Error: Could not find app '$app'"
echo ""
echo "Try using the full package name, e.g.:"
echo " com.example.myapp"
echo ""
echo "Or use one of these common app names:"
echo " chrome, settings, messages, camera, photos, gmail, maps, youtube"
echo " instagram, whatsapp, facebook, twitter, spotify, telegram, discord"
exit 1
fi
# Extract first matching package
package=$(echo "$matches" | head -1 | sed 's/package://')
if [ -z "$package" ]; then
echo "Error: Could not parse package from matches"
echo "Matches found:"
echo "$matches"
exit 1
fi
echo "Found package: $package"
fi
# Launch the app
echo "Launching $package..."
# Method 1: Use monkey to launch (most reliable)
result=$($ADB_CMD shell monkey -p "$package" -c android.intent.category.LAUNCHER 1 2>&1)
if echo "$result" | grep -q "No activities found"; then
# Method 2: Try am start with action MAIN
echo "Trying alternative launch method..."
$ADB_CMD shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER "$package" 2>/dev/null || {
echo "Error: Failed to launch $package"
echo "The app may not be installed or may not have a launcher activity."
exit 1
}
fi
echo "Launched: $package"
#!/bin/bash
# Take a screenshot of the Android device
# Usage: screenshot.sh [-s <serial>]
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: screenshot.sh [-s <serial>]"; exit 1 ;;
esac
done
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
# Paths
DEVICE_PATH="/sdcard/screen.png"
LOCAL_DIR="/tmp"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOCAL_PATH="$LOCAL_DIR/android_screenshot_$TIMESTAMP.png"
# Take screenshot on device
$ADB_CMD shell screencap -p "$DEVICE_PATH"
# Pull to local
$ADB_CMD pull "$DEVICE_PATH" "$LOCAL_PATH" > /dev/null 2>&1
# Clean up device file
$ADB_CMD shell rm -f "$DEVICE_PATH" > /dev/null 2>&1
echo "Screenshot saved: $LOCAL_PATH"
echo ""
echo "Use the Read tool to view this image."
#!/bin/bash
# Swipe in a direction on the Android device
# Usage: swipe.sh [-s <serial>] <direction>
# -s <serial> Target specific device by serial number
# direction: up, down, left, right
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: swipe.sh [-s <serial>] <direction>"; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
if [ $# -ne 1 ]; then
echo "Usage: swipe.sh [-s <serial>] <direction>"
echo "Directions: up, down, left, right"
echo "Example: swipe.sh up"
echo "Example: swipe.sh -s emulator-5554 down"
exit 1
fi
direction="$1"
# Get screen dimensions
screen_size=$($ADB_CMD shell wm size | grep -oE '[0-9]+x[0-9]+' | head -1)
width=$(echo "$screen_size" | cut -d'x' -f1)
height=$(echo "$screen_size" | cut -d'x' -f2)
# Calculate center and edges
center_x=$((width / 2))
center_y=$((height / 2))
# Swipe margins (20% from edges)
margin_x=$((width / 5))
margin_y=$((height / 5))
# Swipe duration in milliseconds
duration=300
case "$direction" in
up)
# Swipe up (scrolls content down)
x1=$center_x
y1=$((height - margin_y))
x2=$center_x
y2=$margin_y
;;
down)
# Swipe down (scrolls content up)
x1=$center_x
y1=$margin_y
x2=$center_x
y2=$((height - margin_y))
;;
left)
# Swipe left
x1=$((width - margin_x))
y1=$center_y
x2=$margin_x
y2=$center_y
;;
right)
# Swipe right
x1=$margin_x
y1=$center_y
x2=$((width - margin_x))
y2=$center_y
;;
*)
echo "Error: Unknown direction '$direction'"
echo "Use: up, down, left, right"
exit 1
;;
esac
$ADB_CMD shell input swipe "$x1" "$y1" "$x2" "$y2" "$duration"
echo "Swiped $direction (from $x1,$y1 to $x2,$y2)"
#!/bin/bash
# Tap at the specified x,y coordinates on the Android device
# Usage: tap.sh [-s <serial>] <x> <y>
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: tap.sh [-s <serial>] <x> <y>"; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
if [ $# -ne 2 ]; then
echo "Usage: tap.sh [-s <serial>] <x> <y>"
echo "Example: tap.sh 540 960"
echo "Example: tap.sh -s emulator-5554 540 960"
exit 1
fi
x="$1"
y="$2"
# Validate coordinates are numbers
if ! [[ "$x" =~ ^[0-9]+$ ]] || ! [[ "$y" =~ ^[0-9]+$ ]]; then
echo "Error: Coordinates must be positive integers"
exit 1
fi
$ADB_CMD shell input tap "$x" "$y"
echo "Tapped at ($x, $y)"
#!/bin/bash
# Type text on the Android device
# Handles special characters by escaping them properly
# Usage: type-text.sh [-s <serial>] <text>
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: type-text.sh [-s <serial>] <text>"; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
if [ $# -lt 1 ]; then
echo "Usage: type-text.sh [-s <serial>] <text>"
echo "Example: type-text.sh \"Hello World\""
echo "Example: type-text.sh -s 1A051FDF6007PA \"Hello World\""
exit 1
fi
text="$*"
# For simple alphanumeric text, use input text directly
# For complex text with special chars, escape them
# Check if text contains only simple characters
if [[ "$text" =~ ^[a-zA-Z0-9]+$ ]]; then
# Simple text - use input text
$ADB_CMD shell input text "$text"
else
# Complex text - escape special characters for shell
# Replace spaces with %s (ADB convention)
escaped="${text// /%s}"
# Escape shell special characters
escaped="${escaped//\'/\\\'}"
escaped="${escaped//\"/\\\"}"
escaped="${escaped//\\/\\\\}"
escaped="${escaped//\(/\\\(}"
escaped="${escaped//\)/\\\)}"
escaped="${escaped//\&/\\\&}"
escaped="${escaped//\|/\\\|}"
escaped="${escaped//\;/\\\;}"
escaped="${escaped//\</\\\<}"
escaped="${escaped//\>/\\\>}"
escaped="${escaped//\$/\\\$}"
escaped="${escaped//\`/\\\`}"
$ADB_CMD shell input text "$escaped"
fi
echo "Typed: $text"
#!/bin/bash
# Wake up the Android device and dismiss lock screen
# Usage: wake.sh [-s <serial>]
# -s <serial> Target specific device by serial number
set -e
# Parse arguments
SERIAL=""
ADB_CMD="adb"
while getopts "s:" opt; do
case $opt in
s) SERIAL="$OPTARG" ;;
*) echo "Usage: wake.sh [-s <serial>]"; exit 1 ;;
esac
done
# Build ADB command with optional serial
if [ -n "$SERIAL" ]; then
ADB_CMD="adb -s $SERIAL"
fi
# Check if screen is on or off
# mScreenState=ON or mScreenState=OFF (varies by Android version)
screen_state=$($ADB_CMD shell "dumpsys display | grep -E 'mScreenState|Display Power: state'" 2>/dev/null | head -1)
is_screen_on() {
if echo "$screen_state" | grep -qiE "ON|BRIGHT"; then
return 0
else
return 1
fi
}
if is_screen_on; then
echo "Screen already on"
else
echo "Screen is off, waking device..."
# Send WAKEUP keyevent (224)
$ADB_CMD shell input keyevent 224
# Brief wait for screen to turn on
sleep 0.5
# Get screen dimensions for swipe
size=$($ADB_CMD shell wm size | grep -oE '[0-9]+x[0-9]+' | tail -1)
width=$(echo "$size" | cut -d'x' -f1)
height=$(echo "$size" | cut -d'x' -f2)
# Calculate swipe coordinates (bottom center to middle)
center_x=$((width / 2))
start_y=$((height * 4 / 5))
end_y=$((height / 3))
# Swipe up to dismiss lock screen (works for swipe-to-unlock)
# Won't bypass PIN/pattern/password - user must handle that
$ADB_CMD shell input swipe $center_x $start_y $center_x $end_y 300
sleep 0.3
echo "Woke device and dismissed lock screen"
fi
# Verify final state
final_state=$($ADB_CMD shell "dumpsys display | grep -E 'mScreenState|Display Power: state'" 2>/dev/null | head -1)
if echo "$final_state" | grep -qiE "ON|BRIGHT"; then
echo "Status: Screen is now on"
else
echo "Status: Screen may still be off (check for PIN/pattern lock)"
fi