Master Python + ADB: Build Multi‑Device Automation Scripts for Android Apps
This tutorial explains how to use Python and ADB to create a group‑control script that connects multiple Android devices, extracts package information, launches apps, performs UI actions via YAML, and cleans up, providing a practical foundation for mobile automation testing.
1. Introduction
Group control—controlling several Android devices from a single computer—is common in automation testing. This article shows how to write a Python‑ADB script to automate tasks across multiple devices.
2. Preparation
Install the Android development environment, ensure adb is added to the system PATH, and connect the devices via USB or a hub. Verify the connections with:
# Below shows three connected devices
xag:Test xingag$ adb devices
List of devices attached
822QEDTL225T7 device
ca2b3455 device
DE45d9323SE96 device3. Practical Example
Using the Xianyu app as a case study, the automation consists of seven steps: obtain the package name and launch activity, list online devices, start the app on each device, perform UI actions defined in a YAML file, and finally stop the app.
Step 1 – Get package name and launch activity
# Get current running app package and initial Activity
adb shell dumpsys activity | grep -i runRun the command on the device; the output displays the package and activity.
Step 2 – Get all online devices
# All device IDs
device_ids = []
def get_online_devices(self):
"""Retrieve all online devices"""
global device_ids
try:
for line in exec_cmd("adb devices"):
# Skip the first line and offline entries
if "device" in line:
device_ids.append(line.split("\t")[0])
device_ids = device_ids[1:]
except Exception as e:
print(e)
# Return connected devices and count
return device_idsStep 3 – Launch the target app on each device
def start_app(self):
"""Open the app on all devices"""
for device in device_ids:
os.popen("adb -s " + device + " shell am start -W {}/{}".format(self.packageName, self.home_activity))
print('Waiting for loading...')
sleep(10)Step 4 – Save UI hierarchy locally
def save_ui_tree_to_local(dName):
"""Dump the current Activity UI tree and pull it locally"""
exec_cmd("adb -s %s shell uiautomator dump /data/local/tmp/%s.xml" % (dName, dName))
sleep(2)
exec_cmd("adb -s %s pull /data/local/tmp/%s.xml ./../" % (dName, dName))Step 5 – Parse UI XML to obtain element coordinates
def get_element_position(element_id, uidump_name):
"""Parse the UI XML, find the element by id, and return its center coordinates"""
tree = ET.parse('./../%s.xml' % uidump_name)
root = tree.getroot()
result_element = None
for node in root.findall('.//node'):
if node.attrib['resource-id'] == element_id:
result_element = node
break
if result_element is None:
print('Element not found!')
return None
coord = re.compile(r"\d+").findall(result_element.attrib['bounds'])
center = (int((int(coord[0]) + int(coord[2])) / 2), int((int(coord[1]) + int(coord[3])) / 2))
return centerStep 6 – Execute steps from a YAML file
# steps_adb.yaml
# Package and Activity
package_name: com.taobao.idlefish
home_activity: com.taobao.fleamarket.home.activity.InitActivity
# Execution steps
steps:
- save_ui_tree_to_local:
method: save_ui_tree_to_local
args:
- find_element_and_click:
id: com.taobao.idlefish:id/tx_id
- save_ui_tree_to_local:
method: save_ui_tree_to_local
- input_content:
content: Python
- find_element_and_click:
id: com.taobao.idlefish:id/search_buttonThe script reads each step, iterates over all devices, and performs the corresponding action (save UI tree, locate element, click, input text, etc.).
# Execute steps
for step in self.steps:
for device in device_ids:
step_name = list(step)[0]
if step_name == 'save_ui_tree_to_local':
save_ui_tree_to_local(device)
elif step_name == 'find_element_and_click':
element_id = step[step_name]['id']
pos = get_element_position(element_id, device)
exec_cmd('adb -s %s shell input tap %s %s' % (device, pos[0], pos[1]))
elif step_name == 'input_content':
content = step[step_name]['content']
exec_cmd('adb -s %s shell input text %s' % (device, content))
else:
print('Other operation')Step 7 – Close the app on all devices
def stop_all(self):
"""Force‑stop the app on every device"""
for device in device_ids:
os.popen("adb -s " + device + " shell am force-stop %s" % self.packageName)4. Conclusion
This article presents the simplest Python‑based group‑control implementation for Android apps; more advanced techniques will be explored in future posts.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Crawling & Data Mining
Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
