fake-adb-device 是一个最小化的本地 ADB 设备服务端。它不依赖浏览器、MaaCore 或具体游戏,只把 ADB 的截图、点击和拖动请求转交给调用方提供的回调。
打个比方,fake-adb-devices 就像 “用遥控器操控电视时”,它假装成电视,接受遥控器的指令拿去自己用,并给遥控器希望得到的响应。
应用案例maaframework接入
详情参考技术实现细节
先用真实adb.exe启动服务器 由这个真daemon 注册为一台网络设备。因此任意兼容 ADB 的客户端都能通过常规 adb connect、adb shell、adb exec-out 命令访问它。但因adb特性断连后注册就失效了,客户端将无法再次连接设备,所以我们还提供定时掉线检查,一旦掉线可自动再次注册,方便重新连接



input 命令与 Sync 文件操作。未知或错误请求会获得兼容的空响应或失败响应,不会令伪设备服务崩溃。
- 为自动化引擎提供伪装 Android 设备。
- 将 ADB 输入桥接到浏览器、桌面程序、远程画面或测试夹具。
- 在不启动 Android 模拟器的情况下测试 ADB 客户端的探测与输入流程。
直接运行伪设备不需要安装任何 Python 包。Windows 下双击 启动伪设备.bat,或在项目目录执行:
python run.py它会使用项目内的 platform-tools/adb.exe,启动真实 ADB daemon,并自动连接 127.0.0.1:5555。未指定截图时,screencap 返回内置的 1280 x 720 黑色 PNG,仅用于验证 ADB 协议和输入回调:
python run.py --screenshot .\screen.png将实际 PNG 路径传入 --screenshot 后,每次截图请求都会读取该文件。输入命令会打印在启动窗口中;浏览器、桌面程序等宿主集成应使用下文的 Python API。
以下环境变量均默认关闭:
| 环境变量 | 默认值 | 作用 |
|---|---|---|
FAKE_ADB_DEVICE_ALLOW_LAN |
0 |
设为 1、true、yes 或 on 时,默认监听 0.0.0.0,允许局域网客户端连接。 |
FAKE_ADB_DEVICE_RECONNECT_INTERVAL |
0 |
掉线检查间隔,单位秒。0 表示禁用;大于 0 时仅在设备从 adb devices 消失后重连。 |
FAKE_ADB_DEVICE_PORT |
5555 |
伪设备监听端口。 |
FAKE_ADB_DEVICE_ADB_DAEMON_PORT |
5037 |
本机 ADB daemon 端口,伪设备调用的 adb start-server、connect 和 devices 均使用此端口。 |
PowerShell 示例:
$env:FAKE_ADB_DEVICE_ALLOW_LAN = "1"
$env:FAKE_ADB_DEVICE_RECONNECT_INTERVAL = "2"
$env:FAKE_ADB_DEVICE_PORT = "5555"
$env:FAKE_ADB_DEVICE_ADB_DAEMON_PORT = "5037"
python run.py命令行参数优先于环境变量:--allow-lan / --no-allow-lan 覆盖局域网设置,--reconnect-interval 0 可明确禁用掉线检查,--port 与 --adb-daemon-port 分别覆盖两个端口。局域网模式没有 ADB 身份认证,仅应在受信任网络中使用。
Linux 下先执行:
chmod +x 安装依赖.sh 启动伪设备.sh
./安装依赖.sh
./启动伪设备.sh安装依赖.sh 支持 apt、dnf 和 pacman,会安装 python3 与 adb。启动伪设备.sh 顶部集中定义 ADB_PATH、设备端口、ADB daemon 端口、局域网开关和掉线检查间隔;直接编辑这些变量即可更改配置。命令行额外参数仍会传递给 run.py。
默认伪设备地址是 127.0.0.1:5555。端口被占用时可以指定另一个端口,启动器会自动使用该地址执行 adb connect:
.\启动伪设备.bat --port 5556之后所有 ADB 命令都应指定相同地址:
.\platform-tools\adb.exe -s 127.0.0.1:5556 shell wm size传入 --port 0 会由系统分配空闲端口,启动窗口会打印实际地址。该端口是伪设备端口;真实 ADB daemon 默认监听本机 5037,可通过 FAKE_ADB_DEVICE_ADB_DAEMON_PORT 或 --adb-daemon-port 修改。外部 ADB 客户端使用自定义 daemon 端口时,应添加 -P <端口>。
默认只监听 127.0.0.1,手机无法访问。仅在受信任的同一局域网内测试时,使用:
.\启动伪设备.bat --host 0.0.0.0 --allow-lan --port 5555
ipconfig从 ipconfig 找到电脑的 IPv4 地址,例如 192.168.1.10。手机上的 ADB 客户端应连接 192.168.1.10:5555,而不是 127.0.0.1:5555。本机 daemon 仍会自动通过 127.0.0.1:5555 注册该伪设备。
若手机连接超时,检查两台设备是否在同一 Wi-Fi,并允许 Windows 防火墙入站 TCP 5555。需要时在管理员 PowerShell 中添加临时规则:
New-NetFirewallRule -DisplayName "fake-adb-device test" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 5555伪设备没有 ADB 认证;局域网内任何能访问该端口的设备都可发起截图和输入命令。测试结束后按 Ctrl+C 停止服务,并删除临时防火墙规则:
Remove-NetFirewallRule -DisplayName "fake-adb-device test"嵌入其他 Python 程序时,才需要以可编辑模式安装:
pip install -e .from pathlib import Path
from fake_adb_device import AdbDeviceSession, CallbackBackend
def get_screenshot() -> bytes:
return Path("screen.png").read_bytes()
def handle_input(action):
print(action)
backend = CallbackBackend(get_screenshot, handle_input)
with AdbDeviceSession(backend, adb_path="platform-tools/adb.exe") as device:
print(f"伪设备已连接: {device.address}")
input("按 Enter 断开设备\n")AdbDeviceSession.start() 的顺序固定为:
启动 FakeAdbServer
-> 等待端口开始监听
-> adb start-server
-> adb connect 127.0.0.1:5555
随后可从任意终端使用标准 ADB 命令:
.\platform-tools\adb.exe devices
.\platform-tools\adb.exe -s 127.0.0.1:5555 shell wm size
.\platform-tools\adb.exe -s 127.0.0.1:5555 shell input tap 640 360
.\platform-tools\adb.exe -s 127.0.0.1:5555 shell input swipe 640 600 640 200 500
cmd /c ".\platform-tools\adb.exe -s 127.0.0.1:5555 exec-out screencap -p > screen.png"
Start-Process .\screen.pngscreencap -p 的标准输出是 PNG 二进制,不能直接在终端显示。Windows PowerShell 应通过上面的 cmd /c 重定向保存,避免二进制被文本编码破坏。伪设备启动窗口会显示每次截图返回的来源和字节数。
close() 仅对该地址执行 adb disconnect 并停止伪设备,不会关闭可能被其他设备共享的 adb daemon。
只需要 ADB 协议服务端、且想自行管理 daemon 时,仍可直接使用 FakeAdbServer:
server = FakeAdbServer(backend, host="127.0.0.1", port=5555)
server.serve_forever()fake-adb-device/
|-- run.py # 免安装启动器,提供黑图或静态 PNG 回调
|-- 启动伪设备.bat # Windows 启动入口
|-- platform-tools/ # 精简的 adb.exe 运行时
|-- src/fake_adb_device/
| |-- backend.py # 截图和输入回调接口
| |-- server.py # 简化 adbd 协议与命令分发
| `-- session.py # adb daemon、connect、disconnect 生命周期
`-- README.md
无需修改代码时,启动器会在每次截图请求时读取 --screenshot 指定的文件;外部程序覆盖该 PNG 文件后,下一次 screencap 会返回新内容。
宿主程序集成时,修改或替换 CallbackBackend 的第一个回调即可。回调必须返回非空的 PNG bytes,并且图片尺寸应和 AdbDeviceSession(..., width=..., height=...) 一致:
def get_screenshot() -> bytes:
return current_png_bytes
backend = CallbackBackend(get_screenshot, handle_input)接入 Playwright、Qt 等线程敏感的界面框架时,ADB 服务线程不能直接调用页面或界面对象。应由界面所属线程定时刷新 current_png_bytes,截图回调只读取加锁后的缓存;输入回调则把 InputAction 放入队列,再由界面所属线程处理。
input tap x y 和 input swipe x1 y1 x2 y2 duration 会分别转换为 InputAction("tap", ...) 和 InputAction("swipe", ...),传入 CallbackBackend 的第二个回调:
def handle_input(action: InputAction) -> None:
if action.kind == "tap":
input_queue.put(action)
elif action.kind == "swipe":
input_queue.put(action)坐标与 width、height 所报告的设备尺寸属于同一坐标系。宿主画面尺寸不同时,应在消费队列时自行缩放坐标。
常见 shell 和 exec 请求由 FakeAdbServer.execute_command() 处理,输入命令由 _dispatch_input() 转换。新增设备探测响应或宿主能力时:
- 在
execute_command()识别新的命令字符串并返回正确的字节响应。 - 若需要向宿主请求数据,在
DeviceBackend增加方法并同步实现CallbackBackend。 - 保持
shell:、exec:、exec-out:三种 ADB 通道的输出均为原始字节。 - 使用
run.py与adb.exe -s <地址> shell <命令>手工验证。
不要为了普通 ADB 命令修改 AdbDeviceSession;它只负责启动监听器、启动真实 daemon、连接设备和关闭时断开设备。
ADB 客户端 -> adb daemon -> FakeAdbServer -> DeviceBackend -> 宿主程序回调
FakeAdbServer解析简化的 ADB 传输协议,并模拟常见设备探测命令。AdbDeviceSession管理伪设备监听、adb start-server、adb connect和定向断开。DeviceBackend是截图和输入的协议接口。CallbackBackend将接口适配为两个普通 Python 回调。- 输入回调接收
InputAction,由宿主程序决定在何处、以何种线程模型执行。
服务仅绑定本地地址时使用。它关闭 ADB 鉴权并只实现最小命令集,不应暴露到局域网或公网。
支持 CNXN、OPEN、WRTE、CLSE 以及 shell:、exec:、exec-out: 通道中的常见命令:设备属性、wm size、screencap、input tap、input swipe、input keyevent、input text、pm path、am start 与 monkey -p。同时支持 MaaFramework 需要的持续 shell cat 监视连接,以及可安全失败的 sync: 文件操作。
它不是完整 adbd 实现,不提供安装 APK、文件同步、端口转发或认证服务。