{"id":20340024,"url":"https://github.com/openatx/adbutils","last_synced_at":"2025-04-13T23:54:43.664Z","repository":{"id":37752257,"uuid":"176463231","full_name":"openatx/adbutils","owner":"openatx","description":"pure python adb library for google adb service.","archived":false,"fork":false,"pushed_at":"2024-05-21T03:48:50.000Z","size":483,"stargazers_count":691,"open_issues_count":17,"forks_count":163,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-05-21T10:30:32.473Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openatx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-19T08:31:58.000Z","updated_at":"2024-06-18T13:51:01.300Z","dependencies_parsed_at":"2024-04-28T10:39:49.384Z","dependency_job_id":"b98a26eb-df93-4dd9-92dd-528d05258196","html_url":"https://github.com/openatx/adbutils","commit_stats":{"total_commits":163,"total_committers":17,"mean_commits":9.588235294117647,"dds":"0.13496932515337423","last_synced_commit":"6bbaa150d66b53c38791eb1f5eeb5111e083dcc8"},"previous_names":[],"tags_count":113,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openatx%2Fadbutils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openatx%2Fadbutils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openatx%2Fadbutils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openatx%2Fadbutils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openatx","download_url":"https://codeload.github.com/openatx/adbutils/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248799914,"owners_count":21163403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T21:19:22.717Z","updated_at":"2025-04-13T23:54:43.643Z","avatar_url":"https://github.com/openatx.png","language":"Python","funding_links":[],"categories":["🔥 最近收录"],"sub_categories":[],"readme":"# adbutils\n[![PyPI](https://img.shields.io/pypi/v/adbutils.svg?color=blue)](https://pypi.org/project/adbutils/#history)\n[![codecov](https://codecov.io/gh/openatx/adbutils/graph/badge.svg?token=OuGOMZUkmi)](https://codecov.io/gh/openatx/adbutils)\n\nPython adb library for adb service\n\n# Requires\nPython 3.8+\n\n**Table of Contents**\n\n\u003c!--ts--\u003e\n   * [adbutils](#adbutils)\n   * [Install](#install)\n   * [Usage](#usage)\n      * [Connect ADB Server](#connect-adb-server)\n      * [List all the devices and get device object](#list-all-the-devices-and-get-device-object)\n      * [Connect remote device](#connect-remote-device)\n      * [adb forward and adb reverse](#adb-forward-and-adb-reverse)\n      * [Create socket connection to the device](#create-socket-connection-to-the-device)\n      * [Run shell command](#run-shell-command)\n      * [Transfer files](#transfer-files)\n      * [Extended Functions](#extended-functions)\n      * [Run in command line 命令行使用](#run-in-command-line-命令行使用)\n         * [Environment variables](#environment-variables)\n         * [Color Logcat](#color-logcat)\n      * [Experiment](#experiment)\n      * [Examples](#examples)\n   * [Develop](#develop)\n      * [Watch adb socket data](#watch-adb-socket-data)\n   * [Thanks](#thanks)\n   * [Ref](#ref)\n   * [LICENSE](#license)\n\n\u003c!-- Added by: shengxiang, at: 2021年 3月26日 星期五 15时05分04秒 CST --\u003e\n\n\u003c!--te--\u003e\n\n# Install\n```\npip3 install adbutils\n```\n\n# Usage\nExample\n\n## Connect ADB Server\n```python\nimport adbutils\n\nadb = adbutils.AdbClient(host=\"127.0.0.1\", port=5037)\nfor info in adb.list():\n    print(info.serial, info.state)\n    # \u003cserial\u003e \u003cdevice|offline\u003e\n\n# only list state=device\nprint(adb.device_list())\n\n# Set socket timeout to 10 (default None)\nadb = adbutils.AdbClient(host=\"127.0.0.1\", port=5037, socket_timeout=10)\nprint(adb.device_list())\n```\n\nThe above code can be short to `from adbutils import adb`\n\n## List all the devices and get device object\n```python\nfrom adbutils import adb\n\nfor d in adb.device_list():\n    print(d.serial) # print device serial\n\nd = adb.device(serial=\"33ff22xx\")\n\n# or\nd = adb.device(transport_id=24) # transport_id can be found in: adb devices -l\n\n# You do not need to offer serial if only one device connected\n# RuntimeError will be raised if multi device connected\nd = adb.device()\n```\n\nThe following code will not write `from adbutils import adb` for short\n\n## Connect or disconnect remote device\nSame as command `adb connect`\n\n```python\noutput = adb.connect(\"127.0.0.1:5555\")\nprint(output)\n# output: already connected to 127.0.0.1:5555\n\n# connect with timeout\ntry:\n    adb.connect(\"127.0.0.1:5555\", timeout=3.0)\nexcept AdbTimeout as e:\n    print(e)\n\nadb.disconnect(\"127.0.0.1:5555\")\nadb.disconnect(\"127.0.0.1:5555\", raise_error=True) # if device is not present, AdbError will raise\n\n# wait-for-device\nadb.wait_for(\"127.0.0.1:5555\", state=\"device\") # wait for device online, state default value is \"device\"\nadb.wait_for(\"127.0.0.1:5555\", state=\"disconnect\") # wait device disconnect\n```\n\n## adb forward and adb reverse\nSame as `adb forward --list` and `adb reverse --list`\n\n```python\n# list all forwards\nfor item in adb.forward_list():\n    print(item.serial, item.local, item.remote)\n    # 8d1f93be tcp:10603 tcp:7912\n    # 12345678 tcp:10664 tcp:7912\n\n# list only one device forwards\nfor item in adb.forward_list(\"8d1f93be\"):\n    print(item.serial, item.local, item.remote)\n    # 8d1f93be tcp:10603 tcp:7912\n    # 12345678 tcp:10664 tcp:7912\n\n\nfor item in adb.reverse_list():\n    print(item.serial, item.local, item.remote)\n\n# 监控设备连接 track-devices\nfor event in adb.track_devices():\n    print(event.present, event.serial, event.status)\n\n## When plugin two device, output\n# True WWUDU16C22003963 device\n# True bf755cab device\n# False bf755cab absent\n\n# When adb-server killed, AdbError will be raised\n```\n\n## Create socket connection to the device\n\nFor example\n\n```python\n# minitouch: https://github.com/openstf/minitouch\nc = d.create_connection(\"unix\", \"minitouch\")\nprint(c.recv(500))\nc.close()\n```\n\n```python\nc = d.create_connection(\"tcp\", 7912) # the second argument must be int\nc.send(b\"GET / HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\n\")\nprint(c.recv(500))\nc.close()\n```\n\n```python\n# read device file\nwith d.create_connection(adbutils.Network.DEV, \"/data/local/tmp/hello.txt\") as c:\n    print(c.recv(500))\n```\n\nThere are many other usage, see [SERVICES.TXT](https://cs.android.com/android/platform/superproject/+/master:packages/modules/adb/SERVICES.TXT;l=175) for more details\n\nThanks for Pull Request from [@hfutxqd](https://github.com/openatx/adbutils/pull/27)\n\n## Run shell command\nI assume there is only one device connected.\n\n```python\nimport io\nfrom adbutils import adb\n\nd = adb.device()\n\nprint(d.serial) # 获取序列号\n\n# Argument support list, str\nserial = d.shell([\"getprop\", \"ro.serial\"]) # 获取Prop信息\n\n# Same as\nserial = d.shell(\"getprop ro.serial\")\n\n# Set timeout for shell command\nd.shell(\"sleep 1\", timeout=0.5) # Should raise adbutils.AdbTimeout\n\n# The advanced shell (returncode archieved by add command suffix: ;echo EXIT:$?)\nret = d.shell2(\"echo 1\")\nprint(ret)\n# expect: ShellReturn(args='echo 1', returncode=0, output='1\\n')\n\n# show property, also based on d.shell\nprint(d.prop.name) # output example: surabaya\nd.prop.model\nd.prop.device\nd.prop.get(\"ro.product.model\")\nd.prop.get(\"ro.product.model\", cache=True) # a little faster, use cache data first\n\nd.get_serialno() # same as adb get-serialno\nd.get_devpath() # same as adb get-devpath\nd.get_state() # same as adb get-state\n```\n\nTake screenshot\n\n```python\n# Method 1 (Recommend)\npil_image = d.screenshot()\n# default display_id=0, error_ok=True\ntry:\n    pil_image = d.screenshot(display_id=1, error_ok=False)\nexcept AdbError:\n    print(\"failed to takeScreenshot\")\n\n# Method 2\n# adb exec-out screencap -p p.png\npng_data = d.shell(\"screencap -p\", encoding=None)\npathlib.Path(\"p.png\").write_bytes(png_data)\n```\n\n## Transfer files\n```python\nd.sync.push(b\"Hello Android\", \"/data/local/tmp/hi.txt\") # 推送二进制文本\nd.sync.push(io.BytesIO(b\"Hello Android\"), \"/data/local/tmp/hi.txt\") # 推送可读对象Readable object\nd.sync.push(\"/tmp/hi.txt\", \"/data/local/tmp/hi.txt\") # 推送本地文件\nd.sync.push(pathlib.Path(\"/tmp/hi.txt\"), \"/data/local/tmp/hi.txt\") # 推送本地文件\n\n# 读取文件\nfor chunk in d.sync.iter_content(\"/data/local/tmp/hi.txt\"):\n    print(\"Chunk\", chunk)\n\nd.sync.push(b\"Hello world\", \"/data/local/tmp/hi.txt\")\noutput = d.sync.read_text(\"/data/local/tmp/hi.txt\", encoding=\"utf-8\")\n# Expect output: \"Hello world\"\noutput = d.sync.read_bytes(\"/data/local/tmp/hi.txt\")\n# Expect output: b\"Hello world\"\n\n# 拷贝到本地\nd.sync.pull(\"/data/local/tmp/hi.txt\", \"hi.txt\")\n\n# 获取包的信息\ninfo = d.app_info(\"com.example.demo\")\nif info:\n    print(info) \n\t# output example:\n    # {\n\t# \"version_name\": \"1.2.3\", \"version_code\": \"12\", \"signature\": \"0xff132\", \n    # \"first_install_time\": datetime-object, \"last_update_time\": datetime-object,\n    # }\n```\n\n## Extended Functions\n\nAdbUtils provided some custom functions for some complex operations.\n\nYou can use it like this:\n\n```python\n# save screenshot\npilimg = d.screenshot()\npilimg.save(\"screenshot.jpg\")\n\n# get current app info\napp_info = d.app_current()\nprint(app_info.package)\nprint(app_info.activity)\nprint(app_info.pid) # might be 0\n\n# install apk\nd.install(\"apidemo.apk\") # use local path\nd.install(\"http://example.com/apidemo.apk\") # install from url\n# raise AdbInstallError if something went wrong\n\n# simulate click\nd.click(100, 100)\nd.click(0.5, 0.5) # center, should be float and \u003c= 1.0\n\n# swipe from(10, 10) to(200, 200) 500ms\nd.swipe(10, 10, 200, 200, 0.5)\n\nd.list_packages()\n# example output: [\"com.example.hello\"]\n\nd.window_size()\n# example output: (1080, 1920) when phone is portrait\n# example output: (1920, 1080) when phone is landscape\nd.window_size(landscape=True) # force landscape mode\n# example output: (1920, 1080)\n\nd.rotation() -\u003e int\n# example output: 0\n# 0: natural, 1: left, 2: right, 3: upsidedown\n\nd.app_info(\"com.github.uiautomator\")\n# example output: {\"version_name\": \"1.1.7\", \"version_code\": \"1007\"}\n\nd.keyevent(\"HOME\")\n\nd.volume_up()\nd.volume_down()\n# default times=1, If you want to adjust the volume multiple times, you can use：d.volume_up(times=xxx)\n\nd.volume_mute()  # device mute\n\nd.send_keys(\"hello world$%^\u0026*\") # simulate: adb shell input text \"hello%sworld\\%\\^\\\u0026\\*\"\n\nd.open_browser(\"https://www.baidu.com\") # 打开百度\n# There still too many functions, please see source codes\n\n# check if screen is on\nd.is_screen_on() # 返回屏幕是否亮屏 True or False\n\n# adb root\nd.root()\n\n# adb tcpip \u003cport\u003e\nd.tcpip(5555)\n\nprint(d.battery())  # get battery info\nBatteryInfo(ac_powered=False, usb_powered=False, wireless_powered=False, dock_powered=False, max_charging_current=0, max_charging_voltage=0, charge_counter=10000, status=4, health=2, present=True, level=100, scale=100, voltage=5000, temperature=25.0, technology='Li-ion')\n\nprint(d.brightness_value)  # get brightness value, return int value in 0-255\nd.brightness_value = 100  # set brightness value\n\n# you can also set brightness mode\nfrom adbutils import BrightnessMode\nprint(d.brightness_mode)  # output BrightnessMode.AUTO or BrightnessMode.MANUAL\nd.brightness_mode = BrightnessMode.MANUAL  # set brightness mode is manual\nd.brightness_mode = BrightnessMode.AUTO  # set brightness mode is auto\n\n```\n\nScreenrecord (mp4)\n\n```python\nd.start_recording(\"video.mp4\")\ntime.sleep(5)\nd.stop_recording()\n```\n\nLogcat\n\n```python\n# filter logcat to file\nlogcat = d.logcat(\"logcat.txt\", clear=True, re_filter=\".*FA.*\") # clear default False\n# do something else\nlogcat.stop(timeout=3) # tell thread to stop write, wait for 3s, if not stopped, raise TimeoutError\nlogcat.stop_nowait() # tell thread to stop write and close file\n```\n\n\n\u003e Screenrecord will try to use scrcpy first if scrcpy found in $PATH, then fallback to `adb shell screenrecord`\n\n_Note: The old method d.screenrecord() is removed after 0.16.2_\n\n\u003c!-- # run screenrecord to record screen\nr = d.screenrecord()\n# sleep for a while, can not large then 3 minutes\nr.stop() # stop recording\nr.stop_and_pull(\"video.mp4\") # stop recording and pull video to local, then remove video from device\n\n# control start time manually\nr = d.screenrecord(no_autostart=True)\nr.start() # start record\nr.stop_and_pull(\"video.mp4\") # stop recording and pull video to local, then remove video from device\n``` --\u003e\n\nFor further usage, please read [_device.py](adbutils/_device.py) for details.\n\n## Run in command line 命令行使用\n\n```bash\n# List devices\n$ python -m adbutils -l\n8d1f93be              MI 5s\n192.168.190.101:5555  Google Nexus 5X - 7.0.0 - API 24 - 1080x1920\n\n# Show adb server version\n$ python -m adbutils -V\n39\n\n# Install apk from local filesystem 安装本地apk(带有进度)\n$ python -m adbutils -i some.apk\n# Install apk from URL 通过URL安装apk(带有进度)\n$ python -m adbutils -i http://example.com/some.apk\n# Install and launch (-L or --launch)\n$ python -m adbutils -i http://example.com/some.apk -L\n\n# Parse apk info (support URL and local)\n$ python -m adbutils --parse http://example.com/some.apk\n$ python -m adbutils --parse some.apk\npackage: com.example.some\nmain-activity: com.example.some.MainActivity\nversion-name: 1.0.0\nversion-code: 100\n\n# Uninstall 卸载应用\n$ python -m adbutils -u com.github.example\n\n# Push\n$ python -m adbutils --push local.txt:/sdcard/remote.txt\n\n# Pull\n$ python -m adbutils --pull /sdcard/remote.txt # save to ./remote.txt\n\n# List installed packages 列出所有应用\n$ python -m adbutils --list-packages\ncom.android.adbkeyboard\ncom.buscode.whatsinput\ncom.finalwire.aida64\ncom.github.uiautomator\n\n# Show URL of file QRCode \n$ python -m adbutils --qrcode some.apk\n.--------.\n|        |\n| qrcode |\n|        |\n\\--------/\n\n# screenshot with screencap\n$ python -m adbutils --screenshot screen.jpg \n\n# download minicap, minicap.so to device\n$ python -m adbutils --minicap\n\n# take screenshot with minicap\n$ python -m adbutils --minicap --screenshot screen.jpg # screenshot with minicap\n\n# Show more info for developers\n$ python -m adbutils --dump-info\n==== ADB Info ====\nPath: /usr/local/bin/adb\nServer version: 41\n\n\u003e\u003e List of devices attached\n- 9de75303 picasso Redmi K30 5G\n\n# Track device status, function like: watch adb devices\n$ python -m adbutils --track\n15:09:59.534 08a3d291 -\u003e device\n15:10:02.683 08a3d291 -\u003e absent\n15:10:05.196 08a3d291 -\u003e offline\n15:10:06.545 08a3d291 -\u003e absent\n15:10:06.545 08a3d291 -\u003e device\n```\n\n### Environment variables\n\n```bash\nANDROID_SERIAL  serial number to connect to\nANDROID_ADB_SERVER_HOST adb server host to connect to\nANDROID_ADB_SERVER_PORT adb server port to connect to\n```\n\n### Color Logcat\n\nFor convenience of using logcat, I put put pidcat inside.\n\n```bash\npython3 -m adbutils.pidcat [package]\n```\n\n![](assets/images/pidcat.png)\n\n\n## Experiment\nInstall Auto confirm supported(Beta), you need to famillar with [uiautomator2](https://github.com/openatx/uiautomator2) first\n\n```bash\n# Install with auto confirm (Experiment, based on github.com/openatx/uiautomator2)\n$ python -m adbutils --install-confirm -i some.apk\n```\n\nFor more usage, please see the code for details.\n\n## Examples\nRecord video using screenrecord\n\n```python\nstream = d.shell(\"screenrecord /sdcard/s.mp4\", stream=True)\ntime.sleep(3) # record for 3 seconds\nwith stream:\n\tstream.send(b\"\\003\") # send Ctrl+C\n\tstream.read_until_close()\n\nstart = time.time()\nprint(\"Video total time is about\", time.time() - start)\nd.sync.pull(\"/sdcard/s.mp4\", \"s.mp4\") # pulling video\n```\n\nReading Logcat\n\n```python\nd.shell(\"logcat --clear\")\nstream = d.shell(\"logcat\", stream=True)\nwith stream:\n    f = stream.conn.makefile()\n    for _ in range(100): # read 100 lines\n        line = f.readline()\n        print(\"Logcat:\", line.rstrip())\n    f.close()\n```\n\n# Develop\n```sh\ngit clone https://github.com/openatx/adbutils adbutils\npip3 install -e adbutils # install as development mode\n```\n\nNow you can edit code in `adbutils` and test with\n\n```python\nimport adbutils\n# .... test code here ...\n```\n\nRun tests requires one device connected to your computer\n\n```sh\n# change to repo directory\ncd adbutils\n\npip3 install pytest\npytest tests/\n```\n\n# Environment\nSome environment can affect the adbutils behavior\n\n- ADBUTILS_ADB_PATH: specify adb path, default search from PATH\n- ANDROID_SERIAL: default adb serial\n- ANDROID_ADB_SERVER_HOST: default 127.0.0.1\n- ANDROID_ADB_SERVER_PORT: default 5037\n\n## Watch adb socket data\nWatch the adb socket data using `socat`\n\n```\n$ socat -t100 -x -v TCP-LISTEN:5577,reuseaddr,fork TCP4:localhost:5037\n```\n\nopen another terminal, type the following command then you will see the socket data\n\n```bash\n$ export ANDROID_ADB_SERVER_PORT=5577\n$ adb devices\n```\n\n## Changes from 1.x to 2.x\n\n### Remove\n- current_app removed, use app_current instead\n- package_info is going to remove, use app_info instead\n\n### Add\n- add volume_up, volume_down, volume_mute\n\n## Generate TOC\n```bash\ngh-md-toc --insert README.md\n```\n\n\u003chttps://github.com/ekalinin/github-markdown-toc\u003e\n\n# Thanks\n- [swind pure-python-adb](https://github.com/Swind/pure-python-adb)\n- [openstf/adbkit](https://github.com/openstf/adbkit)\n- [ADB Source Code](https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/adb.c)\n- [Awesome ADB](https://github.com/mzlogin/awesome-adb)\n- [JakeWharton/pidcat](https://github.com/JakeWharton/pidcat)\n\n# Develop\n[PROTOCOL.md](docs/PROTOCOL.md)\n\n# Alternative\n- https://github.com/Swind/pure-python-adb\n\n# Ref\n- \u003chttps://github.com/imageio/imageio-ffmpeg/blob/80e37882d0/imageio_ffmpeg/_utils.py\u003e\n\n# LICENSE\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenatx%2Fadbutils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenatx%2Fadbutils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenatx%2Fadbutils/lists"}