[{"data":1,"prerenderedAt":101},["ShallowReactive",2],{"case-dev-build-log-android-file-transfer-assistant-en":3,"blog-list-en":13},{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11,"html":12},"dev-build-log-android-file-transfer-assistant","测试机连上以后，我们又做了个文件互传助手","团队测试机通常没有聊天软件，也不会登录个人账号，传一个 URL、截图或安装包都很麻烦。Android 配套 App 做完后，我们顺手在已有配对链路旁加了一条局域网互传通道。","2026-09-14",false,"DevPeek 开发实录：团队测试机没有聊天软件时，如何通过 Android 配套 App 的独立 WebSocket 与 HTTP 局域网通道，在手机和电脑之间互传文字、图片、视频和文件。","dev-build-log",6,"\u003Ch2>「把这个链接发到测试机上」\u003C/h2>\n\u003Cp>Android 配套 App 做出来以后，测试机已经可以扫配对码，把流量切到电脑上的 DevPeek。接口调到一半，我们又碰到另一件很小、但一天会发生很多次的事：\u003C/p>\n\u003Cblockquote>\n\u003Cp>「把这个链接发到测试机上，我用真机打开。」\u003C/p>\n\u003C/blockquote>\n\u003Cp>自己的手机上，这句话通常意味着发到「文件传输助手」或者自己的聊天窗口，再从手机点开。但团队测试机一般不会装这些聊天、通讯软件，也不应该登录某位同事的个人账号。\u003C/p>\n\u003Cp>链接短一点还能手敲。遇到带一长串 Query 的活动页、临时环境地址，输一次就很容易漏字符。临时生成二维码、打开一个局域网页面、接数据线跑 \u003Ccode>adb push\u003C/code>，都能解决，但为了传几行文字，每次都要先搭一座桥。\u003C/p>\n\u003Cp>反方向更麻烦：测试机刚截的异常页面要传回电脑，手机里的日志和 JSON 要拿到桌面看，录屏要交给开发复现。没有通讯软件时，往往又得插线、开临时文件服务，或者先想办法把文件传到另一台手机。\u003C/p>\n\u003Cp>\u003Ca href=\"/blog/dev-build-log-android-apk/\">上一篇\u003C/a> 解决的是测试机换人时反复改系统代理。做到配对之后，一个很自然的问题就冒出来了：\u003Cstrong>手机和电脑既然已经知道彼此，能不能顺手把这些信息也直接传过去？\u003C/strong>\u003C/p>\n\u003Ch2>我们想做的不是另一个聊天软件\u003C/h2>\n\u003Cp>互传助手不是 Android App 最初的目标。扫码切代理这条主链做完以后，手机与电脑已经有了配对关系、设备名和可达地址，我们只是顺着这些现成条件，多解决一个很窄的场景：当前测试机与当前配对电脑之间，临时交换联调资料。\u003C/p>\n\u003Cp>电脑上的 DevPeek「手机」面板和 Android App 里都有一个对话式入口。文字可以双向发送；图片、视频和普通文件也可以从任意一端选取。收到内容后：\u003C/p>\n\u003Cul>\n\u003Cli>文字可长按复制，适合 URL、JSON 片段和临时参数；\u003C/li>\n\u003Cli>图片可以直接预览，也可以复制后粘到其它应用；\u003C/li>\n\u003Cli>视频可以在会话里打开播放，不必先另存再找播放器；\u003C/li>\n\u003Cli>APK、HAR、日志等普通文件显示文件名、大小和传输进度，完成后可另存；\u003C/li>\n\u003Cli>传输失败可以重试，断开后仍能查看之前的会话记录。\u003C/li>\n\u003C/ul>\n\u003Cp>单文件当前限制为 \u003Cstrong>2 GB\u003C/strong>。这是临时互传，不做文件夹同步、云端备份，也不自动同步整块剪贴板。APK 在这里也只是一个普通文件，传到手机后仍要按 Android 的安装流程确认，不是远程安装器。\u003C/p>\n\u003Cp>界面做成聊天样式，并不是想继续长成聊天工具，只是「谁发的、发了什么、传完没有」用左右气泡最容易看清。测试机在几台电脑之间切换时，会话也按电脑分开，不会把上一位同事发来的内容混进当前窗口。\u003C/p>\n\u003Ch2>互传不能走抓包端口\u003C/h2>\n\u003Cp>第一反应可能是：手机本来就连着 DevPeek 的 HTTP 代理，文件也从 8888 传不就行了？\u003C/p>\n\u003Cp>真这么做，会把两件事搅在一起。\u003C/p>\n\u003Cp>8888 是 MITM 抓包链路。目标 App 的 HTTP(S) 经过这里，才会进入列表、SSL 解密、Mock 和 \u003Ca href=\"/docs/param-transform/\">参数转换\u003C/a>。互传的截图或安装包如果也从这里经过，大文件会被当成普通抓包请求处理，既污染列表，又给代理引擎增加一份完全没必要的正文。\u003C/p>\n\u003Cp>还有更麻烦的一层：Android 配套 App 自己就在 VpnService 里声明了 HTTP 代理。如果互传请求继续遵循这份系统代理，它会先被送到 8888，再尝试访问电脑上的互传服务。路径绕回自己建立的 VPN，稍不注意就会形成环路。\u003C/p>\n\u003Cp>所以互传没有复用抓包端口，而是在旁边开了一条 \u003Cstrong>Assist 通道\u003C/strong>：\u003C/p>\n\u003Cul>\n\u003Cli>抓包代理继续监听自己的端口，默认是 8888；\u003C/li>\n\u003Cli>Assist 服务优先使用 17891，端口被占用时自动寻找下一个可用端口；\u003C/li>\n\u003Cli>实际 Assist 端口跟着配对信息发给手机，用户不用再填一次；\u003C/li>\n\u003Cli>Assist 连不上，不影响 VPN 抓包；两条链路各自失败、各自恢复。\u003C/li>\n\u003C/ul>\n\u003Cp>二进制文件不会进入抓包引擎，也不会出现在 \u003Ca href=\"/docs/capture/\">抓包列表\u003C/a> 里。互传是配对后的附加能力，不是一次「自己抓自己」的 HTTP 请求。\u003C/p>\n\u003Ch2>手机必须绕回真实 Wi-Fi\u003C/h2>\n\u003Cp>端口分开还不够。Android 上的互传连接还要明确告诉系统：\u003Cstrong>这条 Socket 不走当前 VPN。\u003C/strong>\u003C/p>\n\u003Cp>App 建立 Assist 客户端时做了两层处理：\u003C/p>\n\u003Col>\n\u003Cli>强制 \u003Ccode>NO_PROXY\u003C/code>，不读取 VpnService 注入的 HTTP 代理；\u003C/li>\n\u003Cli>用 \u003Ccode>UnderlyingNetwork.bind()\u003C/code> 把 Socket 绑定到手机当前的真实网络，通常就是扫码时使用的 Wi-Fi。\u003C/li>\n\u003C/ol>\n\u003Cp>最终路径不是：\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-text\">手机 → VpnService → 8888 抓包代理 → Assist\n\u003C/code>\u003C/pre>\n\u003Cp>而是：\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-text\">手机 → 真实 Wi-Fi → 电脑 Assist 端口\n\u003C/code>\u003C/pre>\n\u003Cp>这条路径避免了 TUN 环路，也让互传文件不进入抓包列表。手机仍然可以同时把浏览器流量送到 DevPeek：一个 App 里有两条连接，一条为目标流量服务，一条为手机与电脑之间的信息交换服务。\u003C/p>\n\u003Cp>这也是为什么互传要求手机和电脑处于可直接访问的局域网。它不经过云端服务器，也不会为了发一张截图先上传公网再下载回来。\u003C/p>\n\u003Ch2>消息走 WebSocket，文件走 HTTP\u003C/h2>\n\u003Cp>文字和文件不适合硬塞进同一种消息。\u003C/p>\n\u003Cp>互传建立后，手机先通过 WebSocket 向桌面发送 \u003Ccode>hello\u003C/code>，带上设备 ID、机型和平台。桌面回一条 \u003Ccode>hello.ok\u003C/code>，双方才把这台设备标为可互传。之后，文字以及文件状态都走这条长连接：\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-text\">text\nfile.offer\nfile.progress\nfile.done\nfile.fail\n\u003C/code>\u003C/pre>\n\u003Cp>文件本体则走 HTTP。发送方先用 \u003Ccode>file.offer\u003C/code> 告诉对方文件名、大小和 MIME 类型，再向 \u003Ccode>/assist/files/{id}\u003C/code> 上传；接收方拿到完成消息后，从同一路径下载。这样 WebSocket 只承担轻量信令，大文件可以流式读写、显示进度，也能单独校验和保存。\u003C/p>\n\u003Cp>连接断开时，正在传的项目会标记为失败，不会一直停在「传送中」。Android 端随后按退避间隔尝试恢复 Assist 连接；恢复不了，也不影响已经建立的抓包 VPN。历史消息和已接收文件会留在本机，下次打开还能查看。\u003C/p>\n\u003Cp>我们没有为了「协议统一」把几百 MB 的视频编码进 JSON，也没有让文件传输反过来绑住代理核心。工具内部多一条通道，换来的是抓包和互传互不拖累。\u003C/p>\n\u003Ch2>本地直传，也不等于可以忽略安全边界\u003C/h2>\n\u003Cp>不要求测试机安装聊天软件、登录个人账号，也意味着临时资料不用先上传到第三方服务；但「局域网直传」不自动等于「端到端加密」。\u003C/p>\n\u003Cp>当前 Assist 使用局域网内的 \u003Ccode>ws://\u003C/code> 与 \u003Ccode>http://\u003C/code>，不提供公网中继，也没有面向不可信网络设计的账号认证和端到端加密。它遵循的仍是配对场景：手机与电脑在同一个可信局域网，配对码不要发到公网，Assist 端口也不要暴露到公共网络。\u003C/p>\n\u003Cp>传 Token、Cookie、生产数据或用户隐私之前，仍要先判断这些内容是否应该离开原设备。需要长期保存、权限控制或审计的文件，应该回到团队正式的协作与存储系统。DevPeek 的互传助手解决的是眼前这一次搬运，不替代这些系统。\u003C/p>\n\u003Cp>它与桌面的 \u003Ca href=\"/docs/collaboration/\">局域网协作\u003C/a> 也有区别：局域网协作面向两台 DevPeek，发送抓包请求和调试录制；互传助手面向 Android 测试机与当前电脑，发送文字和普通文件。\u003C/p>\n\u003Ch2>配对之后，少绕一个中转站\u003C/h2>\n\u003Cp>我们做 Android 配套 App，最初只是为了让测试机换人时不用反复修改系统代理。互传助手是这条主链完成后捎带实现的：既然配对信息和局域网连接已经有了，就再少折腾一次数据线、临时二维码或文件服务。\u003C/p>\n\u003Cp>以前，把 URL 放到没有通讯软件的测试机上，要手敲、扫临时二维码或者插线；把截图拿回电脑，又要反着走一遍。现在测试机既然已经和桌面建立了关系，就让文字和文件沿着这段局域网连接直接过去。\u003C/p>\n\u003Cp>不要求云盘，不要求联系人，也不要求在公共测试机上登录谁的个人账号。只是从电脑到手机，再从手机回来。\u003C/p>\n\u003Ch2>相关文档\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"/docs/quick-start/\">快速上手\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/capture/\">抓包与过滤\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/param-transform/\">参数转换\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/collaboration/\">局域网协作\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/faq/\">常见问题\u003C/a>\u003C/li>\n\u003C/ul>\n\u003Chr>\n\u003Cp>配套 Android App 与互传助手仍在随桌面 1.4.x 打磨，目前不上架。电脑侧可从 \u003Ca href=\"/\">DevPeek 官网\u003C/a> 下载；如果你经常在手机和电脑之间搬 URL、截图、日志或安装包，欢迎到 \u003Ca href=\"https://github.com/GYPengDev/devpeek/discussions\">GitHub Discussions\u003C/a> 说说最常传的是什么。\u003C/p>\n",{"items":14},[15,21,22,29,36,42,48,55,62,68,74,82,88,95],{"slug":16,"title":17,"summary":18,"date":7,"featured":8,"seoDescription":19,"series":10,"seriesOrder":20},"dev-build-log-android-apk","测试机借来借去，我们不想再改系统代理","测试机在团队里转一次，Wi-Fi 代理就要跟着改一次。普通 App 写不了系统代理，于是我们做了 Android 配套 App，用 VpnService 把「换 IP、换端口」收成扫码切换。","DevPeek 开发实录：为什么做 Android 配套 App。测试机在团队里流转时不再反复修改 Wi-Fi 代理，而是通过 VpnService 扫码切换当前抓包电脑。",5,{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11},{"slug":23,"title":24,"summary":25,"date":7,"featured":8,"seoDescription":26,"series":27,"seriesOrder":28},"https-origin-cert-mismatch","Origin Certificate Mismatch: Why DevPeek Still Captures the Site","When an origin certificate does not match its Host, DevPeek neither hides the failure nor stops the debugging session. The site and HTTPS plaintext remain available while request details clearly flag the certificate problem.","Why can DevPeek still open and decrypt a site after ERR_TLS_CERT_ALTNAME_INVALID? Learn how it checks origin Host and SAN, preserves HTTPS debugging, and reports the unverified peer identity.","api-debug-new-tricks",4,{"slug":30,"title":31,"summary":32,"date":33,"featured":8,"seoDescription":34,"series":27,"seriesOrder":35},"https-ssl-skip-decrypt","HTTPS Capture Breaks a Few Sites? Add Them to Skip SSL Proxy","Your proxy and CA work, but a few sites or apps fail only when HTTPS decryption is enabled. Add those Hosts to Skip SSL Proxy so they use CONNECT tunnels while other HTTPS traffic remains readable.","2026-09-01","A few sites or apps fail when DevPeek SSL proxying is enabled? If they recover with decryption off or through a CONNECT tunnel, use Include and Exclude to skip only incompatible Hosts.",3,{"slug":37,"title":38,"summary":39,"date":40,"featured":8,"seoDescription":41,"series":10,"seriesOrder":28},"dev-build-log-silent-auto-update","After Leaving Electron, Silent Updates Had to Be Ours","After the move to Tauri, electron-updater was gone and the stock updater didn't match Launcher, Core, and Shell. Checks and downloads moved into the tray; apply is a silent overwrite after you confirm. It ships in 1.3.0.","2026-08-28","DevPeek dev log: building our own silent updater after Electron. The tray checks and downloads in the background; a click runs a silent install. Windows / macOS in 1.3.0.",{"slug":43,"title":44,"summary":45,"date":46,"featured":8,"seoDescription":47,"series":10,"seriesOrder":35},"dev-build-log-ws-mock-dsl","Why We Designed a WebSocket Mock DSL Instead of YAML, JSON, or JS","Lightweight WebSocket Mock shouldn't feel heavier than HTTP Mock. YAML, JSON, and JS all work—but they're wordy for connect, login, heartbeat. We built a short DSL to keep lightweight Mock light.","2026-08-13","DevPeek dev log: why WebSocket Mock uses a custom Flow DSL. YAML, JSON, and JS handle heavy cases; sequential lightweight scripts get a shorter text format.",{"slug":49,"title":50,"summary":51,"date":52,"featured":8,"seoDescription":53,"series":10,"seriesOrder":54},"dev-build-log-electron-to-tauri","DevPeek Architecture: Dropping Electron for Tauri","A debugging proxy shouldn't ship a whole Chromium just to open a window. We moved business logic into Core and swapped the desktop shell for Tauri—lighter installs, leaner background use, and the tray brings the UI back after you close the window.","2026-08-08","DevPeek dev log: moving the desktop shell from Electron to Tauri—business stays in Core, the shell handles windows and OS features, with smaller footprint and lower resource use.",2,{"slug":56,"title":57,"summary":58,"date":59,"featured":8,"seoDescription":60,"series":10,"seriesOrder":61},"dev-build-log-sqljs-to-better-sqlite3","Why We Moved Capture History from sql.js to Native SQLite","Early DevPeek stored captures in JavaScript-based SQLite (sql.js); busy sessions ate RAM and stuttered the list. Native SQLite keeps memory flat so the proxy can run all day.","2026-08-05","DevPeek dev log: moving capture storage from sql.js to native SQLite—fixing memory growth and list lag on all-day debugging sessions.",1,{"slug":63,"title":64,"summary":65,"date":66,"featured":8,"seoDescription":67,"series":27,"seriesOrder":54},"mock-map-route-split-api","New API Is Live, Frontend Hasn't Shipped? Debug with Forward Rules","After a service split, the frontend still hits the old API while orders already live on the new service. DevPeek Forward Rules forward specific endpoints to the new host without code changes; if the new service isn't ready, Mock gets the page working first.","2026-07-26","Microservice integration and API host migration: use DevPeek Forward Rules for API forwarding—point old-host requests to the new service without changing the frontend. Mock when migration isn't done. Includes a hands-on demo.",{"slug":69,"title":70,"summary":71,"date":72,"featured":8,"seoDescription":73,"series":27,"seriesOrder":61},"api-param-encryption-debug","H5 API Encrypted? Decrypt It On the Fly with DevPeek","Stuck with AES-encrypted API params during integration? Set the key and IV once in DevPeek Param Transform, and see plaintext automatically — you can even edit and re-encrypt on resend.","2026-07-18","Use DevPeek Param Transform to auto-decrypt AES-GCM encrypted H5 API requests. Supports two-way transform, plaintext editing, and debug replay.",{"slug":75,"title":76,"summary":77,"date":78,"featured":79,"seoDescription":80,"series":81,"seriesOrder":54},"h5-debug-console-mock","H5 Debug in Practice (2): Android WebView White Screen—From Console Remote Debug to Mock Validation","A campaign H5 white-screened on some Android devices after a button tap—all requests returned 200, but the page showed nothing. Using DevPeek Console to capture WebView runtime logs, remote eval to confirm a polyfill override, then Mock to verify the fallback UI under error conditions.","2026-07-13",true,"DevPeek H5 debug practice part 2: troubleshoot Android WebView white screen via Console remote debug to locate a JavaScript polyfill conflict, then use Mock to verify page fallback behavior under abnormal API responses.","h5-debug",{"slug":83,"title":84,"summary":85,"date":86,"featured":79,"seoDescription":87,"series":81,"seriesOrder":61},"wechat-h5-storage-debug","H5 Debug in Practice (1): WeChat H5 Local Cache—Debug It on Desktop","After switching test accounts in a WeChat official-account H5, the avatar still showed the old user—capture had the new token, stale data stayed in localStorage. This post walks through a real joint-debug case and how to view and edit localStorage, sessionStorage, and IndexedDB in WeChat WebView from your PC.","2026-07-11","DevPeek H5 debug: locate localStorage, sessionStorage, and IndexedDB cache issues in WeChat H5—compared with vConsole and remote debug, with real WebView debugging workflow.",{"slug":89,"title":90,"summary":91,"date":92,"featured":79,"seoDescription":93,"series":94,"seriesOrder":54},"why-we-built-devpeek-h5-debug","Why We Built DevPeek (2): That H5 Page in the App—Debug It on Your PC","Param transform fixed login, but the activity H5 only broke inside the App WebView. Remote debug and capture lived in different windows—so we folded mirroring and our own debug panels into DevPeek.","2026-07-10","DevPeek origin series, part 2: in-app H5 bugs that only show on real devices, the split between remote debug and capture, and how the Debug tab mirrors pages with built-in DOM, Console, and Network panels.","origin",{"slug":96,"title":97,"summary":98,"date":99,"featured":79,"seoDescription":100,"series":94,"seriesOrder":61},"why-we-built-devpeek","Why We Built DevPeek (1): HTTPS Decrypted, Body Still Gibberish","The night before a release, TLS was already open—but changing one request field still meant digging up encrypt/decrypt scripts. That pushed us toward a proxy tool with business-layer crypto built in—and DevPeek started there.","2026-07-09","DevPeek origin series, part 1: the manual request-body encrypt/decrypt grind—and why we set out to build a proxy tool that owns business-layer crypto.",1789537087432]