
1. Android 模拟器抓包与自动化调试链路为什么总在最后一步断掉Android 模拟器抓包与自动化集成方案说白了就是让「看得见流量」和「点得动界面」这两件事在同一台虚拟设备上同时成立。它适合谁适合需要批量调试接口的移动开发、测试开发以及要把调试流程交接给同事的团队。能做什么把模拟器代理、ADB 端口转发、统一 Key 接入串成一条可复现的链路抓到的请求能直接喂给自动化脚本回放。我见过太多人卡在同一个地方mitmproxy 里流量哗哗地刷脚本却连不上接口或者脚本能跑但每次换台机器就要重新配一遍 Key 和代理。问题不在工具本身而在于抓包环境和自动化环境是两套割裂的配置。模拟器里装了证书、设了代理主机上的脚本却还在用另一套地址和凭证中间靠手工复制粘贴维持一旦要交接就全乱。这篇就按「模拟器代理配置 → ADB 端口转发 → 统一 Key 接入 → 抓包到脚本回放验证」的顺序走一遍。核心思路是让模拟器、抓包工具、自动化脚本共用同一份接入配置Base URL、Key、Model ID 三件套只维护一处。这样调试链路才可复现、可交接而不是某台机器上的「祖传配置」。下面所有命令和配置都以 Android Studio Emulator mitmproxy ADB 为基础TaoToken 作为统一接入层。你不需要一次全做完可以按小节逐步验证。2. TaoToken 统一 Key 接入前的环境准备与 ADB 调试链路搭建在讲接入之前先把模拟器和 ADB 这条链路搭稳。很多人跳过这步直接配 Key结果报错时根本分不清是网络问题还是凭证问题。2.1 模拟器与 ADB 基础确认启动 Android Studio Emulator 后第一件事是确认 ADB 能看到设备adb devices正常输出应该是这样List of devices attached emulator-5554 device如果显示offline或列表为空先别急着往下走。offline通常是模拟器还没完全启动等系统桌面出来再执行一次列表为空则检查 ADB 版本和模拟器是否在同一台主机上。我试过在 WSL 里跑 adb 而模拟器在 Windows 主机上这种情况需要额外做端口转发建议直接在模拟器所在系统里操作。确认设备在线后测试一下 shell 通道adb shell getprop ro.build.version.release能返回 Android 版本号说明 ADB 调试链路是通的。这一步是整个自动化方案的地基地基不稳后面全是玄学问题。2.2 模拟器代理指向主机抓包工具抓包工具跑在主机上模拟器要把流量导过去。Android 模拟器访问主机有个特殊别名10.0.2.2等价于主机的127.0.0.1。在模拟器里进入 Settings Network internet Internet长按已连接的 Wi-Fi通常是 AndroidWifi选择 Modify network展开 Advanced options把 Proxy 设为 ManualProxy hostname: 10.0.2.2 Proxy port: 8080保存后模拟器的 HTTP 流量就会走主机的 8080 端口。这里有个坑如果你主机上 mitmproxy 监听的是127.0.0.1:8080模拟器是连不上的必须让它监听所有网卡mitmweb --listen-host 0.0.0.0 --listen-port 80802.3 证书安装与 Android 7.0 的信任问题模拟器浏览器访问http://mitm.it下载对应平台的证书。安装路径是 Settings Security Encryption credentials Install a certificate CA certificate。注意 Android 7.0 及以上用户安装的 CA 证书默认不被应用信任只有系统证书才被信任。对于大多数普通 App 的调试用户证书够用如果目标 App 做了证书固定或者你抓的是系统级流量就需要把证书推到系统目录adb root adb remount adb push mitmproxy-ca-cert.pem /system/etc/security/cacerts/ adb shell chmod 644 /system/etc/security/cacerts/mitmproxy-ca-cert.pemadb root和adb remount需要模拟器镜像支持Google APIs 镜像通常可以Google Play 镜像可能受限。如果这两条命令报adbd cannot run as root in production builds说明当前镜像不支持换 Google APIs 镜像重建 AVD 即可。2.4 ADB 端口转发打通脚本与模拟器自动化脚本要控制模拟器除了adb shell有时还需要通过端口转发访问模拟器内部服务。比如模拟器里跑了个本地 HTTP 服务在 8000 端口主机想直接访问adb forward tcp:8000 tcp:8000这样主机访问127.0.0.1:8000就等于访问模拟器的 8000 端口。反向的也有adb reverse tcp:9000 tcp:9000adb reverse让模拟器访问自己的127.0.0.1:9000时实际转发到主机的 9000 端口。这个在自动化脚本里特别有用——脚本在主机跑模拟器里的 App 要回调主机服务时用 reverse 比配代理更干净。到这里模拟器、抓包、ADB 三条线都通了。接下来才是接入统一 Key 的环节。3. 可复制的 TaoToken 统一 Key 配置与自动化脚本接入这一节是重点所有配置都给你可复制的片段。核心原则Base URL、Key、Model ID 三件套集中管理抓包工具和自动化脚本读同一份配置。3.1 获取统一 Key 与接入地址先到控制台创建 API Key地址是 https://taotoken.net/console 。创建后复制出来注意 Key 只显示一次。接入地址统一用Base URL: https://taotoken.net/api模型 ID 根据你要调用的模型填比如claude-sonnet-4-5这类。三件套凑齐后下面所有配置都围绕它们展开。3.2 用 settings 片段管理接入配置在项目根目录建一个config/settings.json把三件套写进去{ base_url: https://taotoken.net/api, api_key: sk-你的Key, model_id: claude-sonnet-4-5, proxy: { host: 10.0.2.2, port: 8080 }, adb: { device: emulator-5554, forward_port: 8000 } }这个文件是整条链路的单一事实来源。抓包工具读它的 proxy 段自动化脚本读 base_url、api_key、model_idADB 操作读 adb 段。交接时只需要把这个文件去掉真实 Key和说明文档一起给同事对方填上自己的 Key 就能跑。3.3 自动化脚本读取配置并调用接口写一个 Python 脚本从 settings.json 读配置通过 ADB 操作模拟器同时调用统一接口import json import subprocess import requests with open(config/settings.json, r, encodingutf-8) as f: cfg json.load(f) def adb_shell(command): result subprocess.run( [adb, -s, cfg[adb][device], shell, command], capture_outputTrue, textTrue ) return result.stdout, result.stderr def call_model(prompt): headers { Authorization: fBearer {cfg[api_key]}, Content-Type: application/json } payload { model: cfg[model_id], messages: [{role: user, content: prompt}] } resp requests.post( f{cfg[base_url]}/v1/chat/completions, headersheaders, jsonpayload, timeout60 ) return resp.json() if __name__ __main__: out, err adb_shell(input tap 500 500) print(tap result:, out, err) result call_model(用一句话说明当前页面可能是什么) print(model result:, result)注意adb -s后面跟设备号多设备时避免歧义。base_url拼接/v1/chat/completions是常见的 OpenAI 兼容路径具体以接入文档为准。3.4 抓包工具与脚本共用代理配置mitmproxy 启动时读 settings.json 里的 proxy 段保证抓包端口和脚本认知一致python -c import json cfg json.load(open(config/settings.json)) print(f\mitmweb --listen-host 0.0.0.0 --listen-port {cfg[proxy][port]}\) | bash这样代理端口改了抓包工具和模拟器配置同步改不会出现「脚本以为走 8080模拟器实际走 9090」的错位。配置到这一步链路已经成型。下一节做一次完整的验证。4. 从抓包到自动化脚本回放的完整验证请求验证动作要能同时证明三件事抓包工具能看到流量、脚本能通过 ADB 操作模拟器、统一接口能正常返回。缺一个都说明链路有断点。4.1 启动顺序与前置检查按这个顺序启动避免依赖错乱# 1. 启动抓包 mitmweb --listen-host 0.0.0.0 --listen-port 8080 # 2. 启动模拟器Android Studio 里点启动或命令行 emulator -avd Pixel_6_API_34 # 3. 确认 ADB 在线 adb devices # 4. 确认端口转发 adb forward tcp:8000 tcp:8000模拟器里确认代理已指向10.0.2.2:8080证书已安装。4.2 触发一次可抓包的请求在模拟器里打开浏览器访问一个 HTTP 接口或者用脚本触发adb shell am start -a android.intent.action.VIEW -d https://httpbin.org/get回到 mitmproxy 的 Web 界面http://127.0.0.1:8081应该能看到这条请求。如果看不到先检查模拟器代理是否生效——在模拟器浏览器访问http://mitm.it能打开说明代理通了。4.3 脚本回放并调用统一接口运行上一节的 Python 脚本python auto_debug.py预期输出类似tap result: model result: {choices: [{message: {content: 当前页面可能是...}}]}tap result为空是正常的input tap成功时没有输出。model result里能看到choices字段说明统一接口调用成功。4.4 抓包与回放的交叉验证关键一步在 mitmproxy 里找到脚本调用接口的那条请求确认它的目标地址是taotoken.net请求头里带了Authorization: Bearer sk-...。同时确认模拟器里 App 发出的请求也出现在 mitmproxy 里。两条流量都在同一个抓包会话里说明抓包和自动化共用了一条网络路径。如果脚本调用接口的请求没出现在 mitmproxy 里说明脚本没走代理。Python 的 requests 默认读环境变量HTTP_PROXY/HTTPS_PROXY可以在脚本里显式指定proxies { http: fhttp://{cfg[proxy][host]}:{cfg[proxy][port]}, https: fhttp://{cfg[proxy][host]}:{cfg[proxy][port]} } resp requests.post(url, headersheaders, jsonpayload, proxiesproxies, timeout60)注意这里的代理地址是主机视角的10.0.2.2还是127.0.0.1取决于脚本跑在哪里。脚本跑在主机上就用127.0.0.1:8080跑在模拟器里才用10.0.2.2:8080。这个细节搞反了请求就会静默失败。验证通过后整条链路就是可复现的换台机器改 settings.json 里的 Key 和设备号重跑一遍即可。5. 抓包与自动化集成中的常见报错排查这一节按真实报错来每个都给出定位思路。5.1 401 Unauthorized最常见。先确认 Key 有没有带Bearer前缀很多人直接填 Key 忘了前缀Authorization: Bearer sk-你的Key再确认 Key 有没有多余空格或换行。从控制台复制时容易带上尾部空格。最后确认 Base URL 拼对了https://taotoken.net/api后面接的路径要和文档一致路径错了也可能返回 401 而不是 404。5.2 local proxy failed / connection refused脚本报local proxy failed或Connection refused说明代理地址或端口不对。检查三点mitmproxy 是否在跑、监听地址是不是0.0.0.0、脚本里的代理地址是主机视角还是模拟器视角。前面说过脚本在主机跑用127.0.0.1在模拟器跑用10.0.2.2。5.3 reading choices 相关报错解析响应时报reading choices或KeyError: choices说明返回结构不是预期的 OpenAI 兼容格式。先打印完整响应看看print(json.dumps(resp.json(), ensure_asciiFalse, indent2))常见原因是模型 ID 填错接口返回了错误信息而不是正常结果。确认model_id和文档里的一致。5.4 OAuth / 认证方式不匹配如果报 OAuth 相关错误说明当前接入方式用的是 OAuth 而不是 API Key。检查请求头是不是误带了 OAuth token或者配置里混入了其他认证方式。统一 Key 接入只用Authorization: Bearer不要叠加其他认证头。5.5 ADB 设备 offline 或 unauthorizedadb devices显示offline等模拟器完全启动再试。显示unauthorized在模拟器里确认 USB 调试授权弹窗或者adb kill-server adb start-server adb devices重启 ADB 服务通常能解决。如果还不行检查模拟器的开发者选项里 USB 调试是否打开。5.6 证书安装后仍抓不到 HTTPSAndroid 7.0 用户证书不被系统信任前面讲过。如果目标 App 做了证书固定用户证书和系统证书都不够需要在 App 层面处理。调试阶段建议先用浏览器或普通 App 验证抓包链路再针对特定 App 处理证书固定。排查时记住一个原则先确认网络层通不通ping、curl再确认代理层通不通mitmproxy 有没有流量最后确认应用层通不通接口返回正不正常。逐层排除比一上来就改代码高效得多。6. 把调试链路交接出去统一 Key 与配置文件的落地建议链路跑通只是第一步能交接才算真正落地。交接的核心是让接手的人不需要问你就知道改哪里。第一settings.json 里不要提交真实 Key。用占位符配一份settings.example.json接手的人复制改名后填自己的 Key。Key 从 https://taotoken.net/api-keys 创建接入细节看 https://taotoken.net/doc 。第二把启动顺序写成脚本。前面那串启动命令放进start_debug.sh接手的人一条命令拉起环境#!/bin/bash set -e mitmweb --listen-host 0.0.0.0 --listen-port 8080 emulator -avd Pixel_6_API_34 adb wait-for-device adb forward tcp:8000 tcp:8000 echo 环境就绪设备$(adb devices | tail -n 2)第三验证动作固化成测试。把第 4 节的抓包到回放流程写成一个可重复执行的脚本每次交接前跑一遍输出「抓包可见 / 脚本可操作 / 接口可调用」三个结论。这样接手的人拿到的不只是一堆配置而是一条能自证的链路。长期做编码和 Agent 自动化的团队可以考虑用 Coding Plan 把模型调用额度集中管理地址是 https://taotoken.net/coding-plan 。需要快速验证模型返回时模型对话入口在 https://taotoken.net/chat 。Claude Code 相关的接入配置参考 https://taotoken.net/claude-code 。最后说个实际经验调试链路里最容易被忽略的是「时间」。抓包会话、脚本执行、接口调用三者时间戳对不上时排查会非常痛苦。建议在脚本里给每个动作打上时间戳和 mitmproxy 的请求时间对照能快速定位是哪一环慢了或断了。链路可复现的本质是每一步都有可观测的痕迹。