Adbutils
Adbutils is a pure Python library for interacting with Android devices via the Android Debug Bridge (ADB) protocol. It provides a programmatic interface to control devices, install apps, execute shell commands, manage files, and more, without needing to directly invoke the `adb` command-line tool. The current version is 2.12.0, and it is actively maintained with frequent releases.
Common errors
-
ModuleNotFoundError: No module named 'adbutils'
cause The 'adbutils' module is not installed or not accessible in the current Python environment.fixEnsure 'adbutils' is installed by running 'pip install adbutils' and verify it's in the correct Python environment. -
AttributeError: 'APK' object has no attribute 'get_main_activities'
cause The 'apkutils' library version is incompatible, missing the 'get_main_activities' method.fixDowngrade 'apkutils' to a compatible version by running 'pip install apkutils==1.0.0'. -
adbutils.errors.AdbError: FAIL
cause This is a generic ADB command failure, often encountered during file transfer operations like `device.sync.push()`, indicating that the underlying ADB server reported a failure without a more specific error code.fixVerify the source and destination paths, ensure the device has sufficient storage and permissions for the operation, and check the ADB logs for more detailed error messages. Sometimes, restarting the ADB server (`adb kill-server` then `adb start-server`) or the device can resolve transient issues. -
RuntimeError: Multiple devices connected, but no serial specified
cause When multiple Android devices or emulators are connected, calling `adbutils.adb.device()` without specifying a `serial` argument is ambiguous, and `adbutils` raises this error to prevent an arbitrary device from being selected.fixSpecify the `serial` number of the target device when calling `adb.device()`, for example: `d = adb.device(serial='YOUR_DEVICE_SERIAL_NUMBER')`. You can get a list of connected devices and their serials using `adb.device_list()`.
Warnings
- gotcha Adbutils relies on the `adb` server (from Android SDK Platform Tools). Incompatibilities can arise between `adbutils` and specific `adb` server versions, leading to unexpected errors or connection issues.
- gotcha Older versions of `adbutils` might suffer from connection or socket leaks, especially when using `shell v2` or `create_connection`, leading to resource exhaustion over time.
- gotcha When installing APKs using `device.install()`, ensure compatibility with the `apkutils` library. Specifically, `adbutils` versions prior to 2.11.0 had compatibility issues with `apkutils 2.0.1`.
- gotcha On Windows, older versions of `adbutils` could encounter `PermissionError` when attempting to download APKs.
- gotcha The `device.send_keys()` method had a bug where it would not correctly process input strings containing a dot ('.').
Install
-
pip install adbutils
Imports
- adbutils
import adbutils
Quickstart
import adbutils
# Get a list of connected devices
devices = adbutils.adb.devices()
if devices:
print(f"Connected devices: {len(devices)}")
for i, d in enumerate(devices):
print(f" Device {i}: {d.serial} (status: {d.status})")
# Example: Get a device object by serial or index
if i == 0:
device = d
print(f" First device model: {device.getprop('ro.product.model')}")
# Example: Execute a shell command
output = device.shell("echo Hello from device").strip()
print(f" Shell output: {output}")
# Example: Push a file (requires a dummy file)
try:
with open('test.txt', 'w') as f:
f.write('This is a test file.')
device.sync.push('test.txt', '/sdcard/test.txt')
print(' Pushed test.txt to /sdcard/test.txt')
device.shell('rm /sdcard/test.txt') # Clean up
print(' Cleaned up /sdcard/test.txt')
except Exception as e:
print(f" Could not push/cleanup test.txt (ignored for quickstart): {e}")
else:
print("No ADB devices found. Make sure ADB server is running and devices are connected.")
# Ensure the ADB server is running
if not adbutils.adb.server_version():
print("ADB server not running. Starting it...")
adbutils.adb.start_server()
print("ADB server started.")
else:
print("ADB server is already running.")