adb客户端的纯python实现
项目描述
软件包名称已从“adb”重命名为“ppadb”
从v0.2.1-dev版本开始,包名已从 'adb' 重命名为 'ppadb' 以避免与 Google google/python-adb冲突
介绍
这是 ADB 客户端的纯 python 实现。
您可以使用它与 adb 服务器(而不是设备/模拟器上的 adb 守护程序)进行通信。
当你使用adb命令时
现在您可以使用pure-python-adb作为 adb 命令行连接到 adb 服务器
这个包支持大多数 adb 命令行工具的功能。
亚行设备
亚行外壳
亚行转发
adb 拉/推
adb 安装/卸载
要求
Python 3.6+
安装
$pip install -U pure-python-adb
例子
连接 adb 服务器并获取版本
from ppadb.client import Client as AdbClient
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
print(client.version())
>>> 39
连接到设备
from ppadb.client import Client as AdbClient
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
列出所有设备( adb devices )并在所有设备上安装/卸载 APK
from ppadb.client import Client as AdbClient
apk_path = "example.apk"
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
devices = client.devices()
for device in devices:
device.install(apk_path)
# Check apk is installed
for device in devices:
print(device.is_installed("example.package"))
# Uninstall
for device in devices:
device.uninstall("example.package")
亚行外壳
from ppadb.client import Client as AdbClient
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
device.shell("echo hello world !")
def dump_logcat(connection):
while True:
data = connection.read(1024)
if not data:
break
print(data.decode('utf-8'))
connection.close()
from ppadb.client import Client as AdbClient
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
device.shell("logcat", handler=dump_logcat)
逐行读取logcat
from ppadb.client import Client
def dump_logcat_by_line(connect):
file_obj = connect.socket.makefile()
for index in range(0, 10):
print("Line {}: {}".format(index, file_obj.readline().strip()))
file_obj.close()
connect.close()
client = Client()
device = client.device("emulator-5554")
device.shell("logcat", handler=dump_logcat_by_line)
截屏
from ppadb.client import Client as AdbClient
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
result = device.screencap()
with open("screen.png", "wb") as fp:
fp.write(result)
推送文件或文件夹
from ppadb.client import Client as AdbClient
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
device.push("example.apk", "/sdcard/example.apk")
拉
from ppadb.client import Client as AdbClient
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
device.shell("screencap -p /sdcard/screen.png")
device.pull("/sdcard/screen.png", "screen.png")
连接到设备
from ppadb.client import Client as AdbClient
client = AdbClient(host="127.0.0.1", port=5037)
client.remote_connect("172.20.0.1", 5555)
device = client.device("172.20.0.1:5555")
# Disconnect all devices
client.remote_disconnect()
##Disconnect 172.20.0.1
# client.remote_disconnect("172.20.0.1")
##Or
# client.remote_disconnect("172.20.0.1", 5555)
启用调试记录器
logging.getLogger("ppadb").setLevel(logging.DEBUG)
异步客户端
import asyncio
import aiofiles
from ppadb.client_async import ClientAsync as AdbClient
async def _save_screenshot(device):
result = await device.screencap()
file_name = f"{device.serial}.png"
async with aiofiles.open(f"{file_name}", mode='wb') as f:
await f.write(result)
return file_name
async def main():
client = AdbClient(host="127.0.0.1", port=5037)
devices = await client.devices()
for device in devices:
print(device.serial)
result = await asyncio.gather(*[_save_screenshot(device) for device in devices])
print(result)
asyncio.run(main())
如何运行测试用例
准备
安装 Docker
安装 Docker Compose
pip install docker-compose
修改test/conftest.py
将adb_host的值更改为“模拟器”
adb_host="emulator"
运行测试用例
docker-compose up
结果
Starting purepythonadb_emulator_1 ... done
Recreating purepythonadb_python_environment_1 ... done
Attaching to purepythonadb_emulator_1, purepythonadb_python_environment_1
emulator_1 | + echo n
emulator_1 | + /home/user/android-sdk-linux/tools/bin/avdmanager create avd -k system-images;android-25;google_apis;x86 -n Docker -b x86 -g google_apis --device 8 --force
Parsing /home/user/android-sdk-linux/emulator/package.xmlParsing /home/user/android-sdk-linux/patcher/v4/package.xmlParsing /home/user/android-sdk-linux/platform-tools/package.xmlParsing /home/user/android-sdk-linux/platforms/android-25/package.xmlParsing /home/user/android-sdk-linux/system-images/android-25/google_apis/x86/package.xmlParsing /home/user/android-sdk-linux/tools/package.xml+ echo hw.keyboard = true
emulator_1 | + adb start-server
emulator_1 | * daemon not running; starting now at tcp:5037
python_environment_1 | ============================= test session starts ==============================
python_environment_1 | platform linux -- Python 3.6.1, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
python_environment_1 | rootdir: /code, inifile:
python_environment_1 | collected 27 items
python_environment_1 |
emulator_1 | * daemon started successfully
emulator_1 | + exec /usr/bin/supervisord
emulator_1 | /usr/lib/python2.7/dist-packages/supervisor/options.py:298: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
emulator_1 | 'Supervisord is running as root and it is searching '
emulator_1 | 2018-07-07 17:19:47,560 CRIT Supervisor running as root (no user in config file)
emulator_1 | 2018-07-07 17:19:47,560 INFO Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing
emulator_1 | 2018-07-07 17:19:47,570 INFO RPC interface 'supervisor' initialized
emulator_1 | 2018-07-07 17:19:47,570 CRIT Server 'unix_http_server' running without any HTTP authentication checking
emulator_1 | 2018-07-07 17:19:47,570 INFO supervisord started with pid 1
emulator_1 | 2018-07-07 17:19:48,573 INFO spawned: 'socat-5554' with pid 74
emulator_1 | 2018-07-07 17:19:48,574 INFO spawned: 'socat-5555' with pid 75
emulator_1 | 2018-07-07 17:19:48,576 INFO spawned: 'socat-5037' with pid 76
emulator_1 | 2018-07-07 17:19:48,578 INFO spawned: 'novnc' with pid 77
emulator_1 | 2018-07-07 17:19:48,579 INFO spawned: 'socat-9008' with pid 78
emulator_1 | 2018-07-07 17:19:48,582 INFO spawned: 'emulator' with pid 80
emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5554 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5555 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5037 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,607 INFO success: novnc entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,608 INFO success: socat-9008 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,608 INFO success: emulator entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
python_environment_1 | test/test_device.py .............. [ 51%]
python_environment_1 | test/test_host.py .. [ 59%]
python_environment_1 | test/test_host_serial.py ........ [ 88%]
python_environment_1 | test/test_plugins.py ... [100%]
python_environment_1 |
python_environment_1 | ------------------ generated xml file: /code/test_result.xml -------------------
python_environment_1 | ========================= 27 passed in 119.15 seconds ==========================
purepythonadb_python_environment_1 exited with code 0
Aborting on container exit...
Stopping purepythonadb_emulator_1 ... done
更多信息
用于 Android 调试桥的纯 Node.js 客户端
亚行文件
0.2.1 (2019-10-14)
修复 #21:将包名从“adb”重命名为“ppadb”
修复 #23:支持将目录推送到设备
修复 #25:不要在模块中调用 logging.basicConfig()
0.1.6 (2019-01-21)
修复 #4 推送不保留原始时间戳,这与命令行中的等效 adb 推送不同
修复 #6 forward_list 还应该检查串行
修复 #8:adb/command/host/__init__.py 可以在解析“设备”数据时出现异常
0.1.0 (2018-06-23)
PyPI 上的第一个版本。