25、ADB 与自动化框架:ADB + Python(subprocess 调用)、ADB + Appium 简介、实战:编写一个自动安装脚本
说实话,到了这一章,才算真正进入「自动化」的大门。
前面我们一直在手动敲命令,对吧?
敲一次两次还行,要是让你每天重复 50 次同样的 adb install,你肯定想骂人。
所以,我们需要把 ADB 和脚本结合起来。
我个人习惯用 Python,因为它写起来快,生态也好。你想想看,一个 subprocess 模块就能搞定所有 shell 调用,再配合 Appium 做 UI 自动化,基本上手机上的重复劳动都能交给机器了。
25.1 ADB + Python:用 subprocess 调用 ADB 命令
Python 调用外部命令,最常用的就是 subprocess 模块。
我刚开始用的时候也踩过坑——直接用 os.system(),结果拿不到输出,调试起来特别痛苦。后来老老实实换成了 subprocess,真香。
先看一个最简单的例子:
import subprocess
# 执行 adb devices
result = subprocess.run(
['adb', 'devices'],
capture_output=True,
text=True,
encoding='utf-8'
)
print(result.stdout)
这里要注意几个点:
capture_output=True才能拿到标准输出和错误输出text=True让输出以字符串形式返回,而不是字节encoding='utf-8'避免中文乱码——嗯,这个坑我踩过
如果你需要实时获取输出(比如看 logcat),可以用 Popen:
import subprocess
proc = subprocess.Popen(
['adb', 'logcat', '-c'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
# 清空日志后,再启动实时读取
proc = subprocess.Popen(
['adb', 'logcat'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True
)
for line in proc.stdout:
print(line.strip())
我曾经在做一个自动化测试框架时,需要同时监控多台设备的日志。用 Popen 配合线程,每台设备开一个子进程,完美解决。
adb -s 设备序列号 封装成一个函数,避免每次拼字符串。
25.2 ADB + Appium 简介
Appium 是什么?
说白了,它是一个跨平台的 UI 自动化框架。底层还是调用的 ADB(Android 端),但它帮你封装了元素定位、手势操作、等待机制这些麻烦事。
我个人的理解:
- ADB 是「手」,能执行命令、安装应用、点击屏幕
- Appium 是「大脑」,能理解 UI 结构、找到按钮、判断页面状态
安装 Appium 很简单:
npm install -g appium
appium
然后写一个 Python 客户端脚本:
from appium import webdriver
desired_caps = {
'platformName': 'Android',
'deviceName': 'emulator-5554',
'appPackage': 'com.android.settings',
'appActivity': '.Settings',
'noReset': True
}
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# 点击 "关于手机"
driver.find_element_by_xpath("//*[@text='关于手机']").click()
# 获取 Android 版本
version = driver.find_element_by_xpath("//*[@text='Android 版本']/following-sibling::*").text
print(f'Android 版本: {version}')
driver.quit()
你看,代码比纯 ADB 直观多了吧?
但要注意,Appium 启动比较慢,每次都要启动一个 Appium Server。我建议在调试阶段先用 ADB 验证可行性,再用 Appium 做精细化操作。
25.3 实战:编写一个自动安装脚本
好了,理论说完了,咱们直接写一个能用的脚本。
这个脚本的功能:
- 自动检测连接的设备
- 如果有多台设备,让用户选择
- 安装指定的 APK 文件
- 如果已安装,先卸载再安装
- 显示安装进度和结果
import subprocess
import sys
import os
def get_devices():
"""获取已连接的设备列表"""
result = subprocess.run(
['adb', 'devices'],
capture_output=True,
text=True,
encoding='utf-8'
)
lines = result.stdout.strip().split('\n')[1:]
devices = []
for line in lines:
if line.strip() and 'device' in line and 'offline' not in line:
serial = line.split('\t')[0]
devices.append(serial)
return devices
def select_device(devices):
"""让用户选择设备"""
if not devices:
print('没有检测到设备,请检查连接。')
sys.exit(1)
if len(devices) == 1:
return devices[0]
print('检测到多台设备:')
for i, dev in enumerate(devices):
print(f' [{i}] {dev}')
choice = input('请选择设备编号(默认0):').strip()
if not choice:
choice = '0'
return devices[int(choice)]
def install_apk(serial, apk_path):
"""安装 APK,如果已存在则先卸载"""
# 获取包名
result = subprocess.run(
['aapt', 'dump', 'badging', apk_path],
capture_output=True,
text=True,
encoding='utf-8'
)
# 简单解析包名
for line in result.stdout.split('\n'):
if line.startswith('package:'):
package_name = line.split("name='")[1].split("'")[0]
break
else:
print('无法解析 APK 包名,请检查 aapt 是否安装。')
sys.exit(1)
# 检查是否已安装
check = subprocess.run(
['adb', '-s', serial, 'shell', 'pm', 'list', 'packages', package_name],
capture_output=True,
text=True,
encoding='utf-8'
)
if package_name in check.stdout:
print(f'设备 {serial} 上已安装 {package_name},正在卸载...')
subprocess.run(
['adb', '-s', serial, 'uninstall', package_name],
capture_output=True
)
print('卸载完成。')
# 安装
print(f'正在安装 {apk_path} 到设备 {serial}...')
result = subprocess.run(
['adb', '-s', serial, 'install', '-r', apk_path],
capture_output=True,
text=True,
encoding='utf-8'
)
if 'Success' in result.stdout:
print('安装成功!')
else:
print('安装失败:')
print(result.stdout)
print(result.stderr)
if __name__ == '__main__':
if len(sys.argv) < 2:
print('用法:python install_apk.py <apk_path>')
sys.exit(1)
apk_path = sys.argv[1]
if not os.path.exists(apk_path):
print(f'文件不存在:{apk_path}')
sys.exit(1)
devices = get_devices()
serial = select_device(devices)
install_apk(serial, apk_path)
这个脚本我实际在项目里用过,当时需要给 20 台测试机批量安装同一个应用。手动装一台要 2 分钟,用这个脚本,加上一个循环,5 分钟全部搞定。
你可以把它扩展一下:
- 加上
--multi参数,一键安装到所有设备 - 加上
--log参数,把安装结果写入日志文件 - 加上重试机制,安装失败自动重试 3 次
25.4 本章知识体系
下面这张图,帮你理清 ADB、Python、Appium 三者的关系:
说白了,这一章的核心就三句话:
- Python + subprocess 是调用 ADB 最灵活的方式
- Appium 适合做 UI 层面的自动化,但启动慢、依赖多
- 实战脚本 把前面学的 ADB 命令串起来,解决真实问题
我建议你先把那个安装脚本跑通,然后试着改一改——比如加上批量安装、日志记录、失败重试。改着改着,你就发现 ADB 自动化其实没那么神秘。
公众号:蓝海资料掘金营,微信deep3321