TUTORIAL-DRAW-AND-PLAY.txt,中英双语纯文本,1305 行 / 64 KB。
内容按真实界面元素写(对照 web/index.html 与 web/js/app.js 的实际按钮 / 交互):
- A 开始之前:三件必须做完的事(连接设备 / 挂载镜像 / 手机在手边)
- B 界面总览:四块区域 + 三个最关键按钮
- C 地图操作:平移缩放全览、切换底图、快速定位到坐标
- D 三种造轨迹方式
D1 折线绘制(点击加点、双击或 Esc 结束、至少 2 点)
D2 途经点 + OSRM 路线规划(拖拽排序、双击改坐标、改完要重新加载)
D3 导入 GPX
- E 编辑:撤销 / 删除 / 移动 / 排序
- F 出行模式(驾车/骑行/步行/飞行)与播放倍速(0.1x-50x)的区别
- G 真实感参数逐个讲解:漂移 / 速度浮动 / 节奏抖动 / 位移推算速度 / 粗差跳点
- H 开始播放:前置检查清单 + 逐步现象 + 失败提示对照
- I 播放中控制:暂停 / 继续 / 拖动跳转 / 停止 的区别
- J 结束与恢复真实定位(三种方式 + 恢复不了的例外)
- K 保存复用(localStorage 与 GPX 的区别)
- L 快捷键总表
- M 常见问题(含错误提示原文对照)
- N 参数速查表
编码:UTF-8 with BOM + CRLF(记事本友好),.gitattributes 锁定 eol=crlf。
README.md / README.en.md 加入口,Location.spec 随 Windows 包一起装到安装目录。
17 KiB
iOS 虚拟定位轨迹工具(macOS / Windows)
在电脑上给 iPhone / iPad 做虚拟定位与轨迹模拟的桌面工具:在地图上绘制路线、添加途经点、按真实速度沿轨迹驱动手机定位。
支持 iOS 17 ~ iOS 27.2(RSD 隧道 + DVT SimulateLocation),应用内内置了全系共用的开发者镜像素材,不需要安装 Python 环境。
界面为本机网页应用,用 Chrome / Edge 的应用窗口打开(无地址栏,像原生 App),也可以直接用浏览器访问 http://127.0.0.1:8787。地图、轨迹、播放引擎、设备通信全部在本机完成,只有地图瓦片和(可选的)路线规划需要联网。
Windows 用户请看 docs/README-WINDOWS.md。 Windows 版:免管理员建立隧道(纯 Python 用户态协议栈,不需要 Wintun 驱动)、 启动时自动检测并安装 Apple Mobile Device Support、带「环境准备」自检窗口。 构建产物:
dist\iOSLocationTrack\iOSLocationTrack.exe与dist\installer\iOSLocationTrack-1.1.0_win-setup.exe。📄 快速上手(中英双语纯文本,可直接用记事本打开):USAGE.txt 📄 详细教程:画轨迹 · 折线绘制 · 开始虚拟轨迹:TUTORIAL-DRAW-AND-PLAY.txt
1. 快速开始
方式一:直接下载安装包(推荐)
从 Releases 下载对应平台的安装包:
| 平台 | 文件名 | 说明 |
|---|---|---|
| Windows | iOSLocationTrack-<版本>_win-setup.exe |
安装包。也可用绿色版压缩包,解压即用 |
| macOS | iOSLocationTrack-<版本>_mac.dmg |
打开 DMG,把 App 拖进 Applications |
Windows 版首次启动会请求管理员权限并弹出「环境准备」窗口自动补齐依赖, 详见 docs/README-WINDOWS.md。
macOS 版:打开 DMG,把 虚拟定位轨迹.app 拖进 Applications;首次打开若提示
「来自身份不明的开发者」→ 右键 → 打开 → 再点「打开」。
不需要安装 Python、不需要任何依赖,Python 运行时与全部依赖都已打包在应用内(约 80 MB)。
数据(配置、瓦片缓存)写到 ~/Library/Application Support/iOSLocationTrack/。
只支持 Apple Silicon(M 系列)。Intel Mac 可用下方源码方式,或在 Intel 机器上执行
./scripts/build_app.sh(脚本通用)。
方式二:源码运行
git clone https://github.com/jbjf6666/ios-location-track.git
cd ios-location-track
# 首次运行会自动创建虚拟环境并安装依赖(走国内镜像)
./scripts/run.sh
启动后会自动打开界面。命令行等价方式:
./.venv/bin/python main.py # 正常启动(自动打开界面)
./.venv/bin/python main.py --mock # 无设备模拟模式(演示/验收轨迹与播放)
./.venv/bin/python main.py --port 8899 --no-browser
./.venv/bin/python main.py --window browser # 用默认浏览器打开而不是应用窗口
三种运行形态
| 形态 | 路径 | 是否需要环境 | 适用场景 |
|---|---|---|---|
| DMG 安装包 | Release 附件(45 MB) | 不需要 | 分发 / 换机器 |
| 独立版 | dist/虚拟定位轨迹.app(约 80 MB 展开) |
不需要:Python、依赖、前端、图标、镜像素材全在包内 | 双击即用 |
| 源码版 | ./scripts/run.sh |
需要 Python 3.11+(首次自动装依赖) | 改代码、调试 |
# 重新打包(一步完成:图标 → 打包 → ad-hoc 签名 → 制作 DMG → 验证)
./scripts/build_app.sh
DMG 里放了应用本体、Applications 快捷方式(拖进去即安装)和一份安装说明。
如需自定义 DMG 外观:改 tools/make_dmg.py 顶部的常量。
首次运行会请求「控制 Chrome/Edge」的权限(用于以应用窗口方式打开界面)。
2. 支持的系统
| 系统 | 支持 | 说明 |
|---|---|---|
| iOS 17 ~ 27.2 | ✅ | 走 RSD 隧道 + DVT。应用内置全系共用的个性化镜像素材 |
| iOS 16 及更早 | ❌ | 其开发者镜像必须由 Apple 按系统构建号签发,第三方镜像会被设备拒签(实测 Failed to verify the disk image signature,换 libimobiledevice 同样失败) |
为什么一套镜像就够:iOS 17 起 Apple 改用「个性化」开发者镜像 —— 一份基础镜像(Image.dmg)+ BuildManifest.plist,全系统版本共用;挂载时由 Apple TSS 服务器按当前设备在线签发,因此不需要逐版本素材。本工具把这套素材打包在内(约 16 MB),点「挂载开发者镜像」即可离线使用(仅签名步骤需要联网)。
3. 设备准备(关键)
| 要求 | 说明 |
|---|---|
| 数据线连接 | 建议用 USB;Wi-Fi 连接在传输大文件时容易断 |
| 解锁并「信任」 | 手机弹出「要信任此电脑吗」必须点信任并输入锁屏密码 |
| 开启开发者模式 | 设置 → 隐私与安全性 → 开发者模式 → 打开 → 重启手机 → 重启后确认开启 |
| 挂载开发者镜像 | 点界面上的「挂载开发者镜像」(应用已内置素材),或用 Xcode 连接一次自动完成 |
| 关闭同类工具 | 爱思助手 / i4Tools / Xcode 等会与本工具争抢同一条 RSD 连接,同一时间只能开一个 |
挂载开发者镜像
界面上点 「挂载开发者镜像」 即可,过程实时输出到右侧运行日志。命令行等价方式:
# 查看是否已挂载(返回 [] 表示没挂)
./.venv/bin/python -m pymobiledevice3 mounter list
# 自动挂载
./.venv/bin/python -m pymobiledevice3 mounter auto-mount --udid <你的UDID>
也可以直接用 Xcode:连接设备 → Window → Devices and Simulators → 等待 "Preparing device for development" 完成。
macOS 装有 Xcode 时,系统自带的
CoreDeviceService通常会在设备接入后自动挂载 (/Library/Developer/DeveloperDiskImages/),此时无需任何操作。
打包版(.app)内部用 pymobiledevice3 的 Python API 完成挂载,不依赖任何命令行工具。
关于 iOS 17+ 的隧道(RSD)
iOS 17 起,虚拟定位服务不再走 usbmux,必须先建立 RSD 隧道。本工具有三种方式:
- 免 root(默认,推荐):自动执行
pymobiledevice3 remote start-tunnel --native --script-mode,借用 Apple 自带remoted的隧道。打包版通过tunnel-helper自调用实现,不依赖外部 Python。 - 管理员模式:界面上点「以管理员权限重建隧道」(会弹系统密码框),或直接
sudo ./scripts/run.sh。 - 手动填 RSD:界面「手动 RSD」按钮,填入
HOST PORT(例如从其它工具或tunneld拿到)。
remote tunneld、lockdown start-tunnel、经典remote start-tunnel都必须 root,本工具不会静默提权。
4. 界面功能
顶部:设备区
- 设备名 / 型号 / iOS 版本 / 连接方式(USB/网络)
- 隧道状态、虚拟定位状态、开发者模式状态
- 「刷新设备」「连接设备」「断开」
左侧:轨迹设置
- 出行模式:驾车 / 骑行 / 步行 / 飞行(决定基准速度与是否走真实路网)
- 播放倍速:0.1x ~ 50x(只影响轨迹推进速度,不影响下发频率)
- 循环播放:到终点自动回到起点
- 真实感模拟(可随时开关、播放中也能改):
- 定位漂移:模拟 GPS 误差导致的缓慢游走,半径 0~50 米(默认 4 米)。 用多尺度平滑噪声实现——沿轨迹连续变化、有惯性,不会出现随机跳点。
- 速度浮动:瞬时速度在设定值上下平滑波动,幅度 0~60%(默认 ±8%)。
- 发送节奏抖动(默认开):真实手机 GPS 不是精确每秒一次,而是 0.85~1.15 秒抖动、 偶发丢一次采样(约 2%)。间隔完全均匀是最容易被数据侧识别的特征之一。
- 速度由位移推算(默认开):上报速度 = 实际位移 ÷ 实际时间间隔,与 iOS 从坐标序列
推算
CLLocation.speed的方式一致,因此速度、位移、时间戳三者自洽。 - 注入粗差跳点(默认关):按概率插入多径/城市峡谷导致的坏点,
用来测你自己 App 的
horizontalAccuracy过滤与跳点剔除逻辑是否生效。 - 所有开关与幅度都会持久化,下次启动沿用。
- 快速定位到坐标:输入经纬度直接跳转,可收藏常用位置
- 路线概览:总距离、预计耗时、路径点数、途经点数、路线引擎(OSRM 真实路网 / 直线)
- 途经点列表:拖拽排序、双击改坐标、删除、定位到该点
- 本地保存的路线:保存 / 载入 / 删除(浏览器本地存储)
- 底图:高德矢量(GCJ-02,带中文标注)/ 高德卫星 / 全球卫星(Esri) / OpenStreetMap
- 操作:「加载 OSRM 路线」「清空」「导出 GPX」「导入 GPX」「恢复真实定位」
- 瓦片缓存:显示缓存目录与占用,「清理瓦片缓存」
地图工具条
- 选择:拖动地图、拖拽途经点、点击编辑
- 添加途经点:在地图上连续点击加点(最常用的绘制方式)
- 折线绘制:连续点击画折线,双击或 Esc 结束
- 撤销上一步、删除选中点、全览
底部:播放条
- 播放 / 暂停 / 继续 / 停止
- 进度条(可拖动跳转,即 seek)
- 已用时间、剩余时间、序号
- 实时速度、当前坐标、倍速
右侧:运行日志
实时显示设备连接、隧道建立、镜像挂载、每次定位下发的日志,便于排查问题。
5. 典型用法
A. 沿真实道路跑一条轨迹
- 连接设备 → 「连接设备」(iOS 17+ 会自动建隧道,最长约 1 分钟)
- 点「添加途经点」,在地图上点起点、中间点、终点(至少 2 个)
- 点「加载 OSRM 路线」→ 生成真实路网折线(无网络时自动退化为直线)
- 调「播放倍速」(例如 20x 可以在几秒内跑完 10 公里)
- 点「播放」→ 手机定位会沿轨迹移动;地图上定位点与进度实时更新
- 点「停止」→ 手机立刻恢复真实定位
B. 单点定位(钉在某处不动)
在「选择」工具下双击地图任意位置,或点「快速定位到坐标」输入经纬度。用完点「恢复真实定位」。
C. 导入已有轨迹
点「导入 GPX」选择 .gpx 文件 → 轨迹出现在地图上 → 播放。导出的 GPX 也能导入 Google Earth、Strava 等工具。
D. 没有设备时预览效果
./.venv/bin/python main.py --mock
界面、轨迹绘制、播放引擎、进度条全部可用,只是定位不会真正下发到手机(顶部会显示「当前为模拟模式」)。
6. 命令行工具与自检
# 列出设备 + 开发者模式 + DVT 可用性
./.venv/bin/python tools/probe_device.py
./.venv/bin/python tools/probe_device.py --probe # 实际连一次 DVT
# 单点虚拟定位(命令行版)
./.venv/bin/python tools/probe_location.py --lat 39.9088 --lon 116.3975
./.venv/bin/python tools/probe_location.py --clear # 恢复真实定位
# 离线自检:83 项单元 + 端到端(不需要真机)
./.venv/bin/python tests/selftest.py
# 真实感模拟(GPS 漂移 + 速度浮动 + 节奏抖动,40 项)
./.venv/bin/python tests/drift_sim.py
# 瓦片本地缓存(13 项) / 浏览器级离线可用(9 项)
./.venv/bin/python tests/offline_tiles.py
./.venv/bin/python tests/offline_browser.py
# 图形界面验收(20 项,自动起浏览器)
./.venv/bin/python tests/ui_acceptance.py
# 独立版打包产物验证:干净环境启动 + 全部接口(22 项)
./.venv/bin/python tools/verify_bundle.py
# 真机端到端:会真的改变手机定位,结束后自动恢复
./.venv/bin/python tests/real_device_e2e.py --confirm --duration 5 --speed 20
# 给界面截图(视觉验收)
./.venv/bin/python tools/screenshot.py http://127.0.0.1:8787/ /tmp/ui.png --wait 9
打包相关:
./.venv/bin/python tools/make_icon.py # 生成应用图标(程序化绘制)
./.venv/bin/python tools/fetch_ddi.py # 获取开发者镜像素材
./.venv/bin/python tools/make_dmg.py # 制作 DMG
7. 故障排查
| 现象 | 原因与处理 |
|---|---|
| 界面显示「本地服务未连接」 | 服务端没起来或端口被占。看终端是否有报错;换端口 --port 8899 |
| 未检测到设备 | 数据线 + 解锁 + 点「信任」 |
| 提示「需要开发者模式」 | 设置 → 隐私与安全性 → 开发者模式 → 打开并重启手机 |
| 「挂载开发者镜像」失败,提示签名被拒 | 设备是 iOS 16 或更早(不支持);或网络不通导致 TSS 签名失败,检查网络后重试 |
| 连接设备报「隧道」相关错误 | ① 关闭爱思助手等同类工具(会抢 RSD 连接);② 点「以管理员权限重建隧道」;③ 确认开发者镜像已挂载 |
| 定位不生效(手机没动) | 确认「虚拟定位」显示"模拟中";iOS 17+ 必须隧道正常 |
| 地图一片空白 | 瓦片源被网络限制,换底图(高德卫星 / Esri);已浏览过的区域断网也能显示(瓦片落在 ~/.ios-location-tiles,上限 1GB,LRU 淘汰) |
| 隧道建好后手机定位立刻恢复 | 有别的程序(爱思/i4Tools/Xcode)在抢同一条 RSD 连接,关掉它们 |
8. 技术说明(实现要点)
- 通信:Python 标准库
http.server+ 手写 WebSocket(RFC 6455),无第三方 Web 框架;设备侧用pymobiledevice3。 - 虚拟定位:DVT 服务
com.apple.instruments.dtservicehub(iOS 17+,走 RSD 隧道),调用LocationSimulation.set(lat, lon)/clear()。 连接必须长连接保持——DVT 会话一断,模拟定位立即失效,这决定了播放引擎不能每发一个点就重连。 - 播放引擎:按弧长积分推进;速度剖面按转弯角度生成(急弯自动减速)再做滑动平均,因此加减速自然。独立线程 + 单一在途请求,保证下发顺序严格不乱。
- 真实感模型:位置漂移用多尺度值噪声(慢漂 120m + 中尺度 30m + 快抖 15m 相关长度,接近真实 GPS 误差的幂律谱),幅值标定到设定半径并做上限裁剪(1.8 倍);相邻上报点之间平滑过渡,不会出现随机跳点造成的毛刺。
- 坐标:内部与后端一律 WGS84;高德瓦片是 GCJ-02,由前端在请求瓦片与落点时做转换,避免"地图上的点和实际定位差 500 米"。
- 瓦片:服务端代理 + 磁盘缓存(默认
~/.ios-location-tiles,上限 1GB,LRU 淘汰)。会自动识别并丢弃服务商返回的"全透明空瓦片"。 - 路线:优先 OSRM 真实路网(
router.project-osrm.org),无网络时退化为直线并在地图上标注引擎类型。 - 独立打包:PyInstaller onedir + ad-hoc 签名。隧道建立通过「自调用」实现(
<应用自身> tunnel-helper),因此打包后不需要机器上有 Python。 - 接口契约:见 docs/PROTOCOL.md。
- Windows 移植:见 docs/WINDOWS_PORT.md(可移植性审计、隧道方案替换、 打包链路改造、验收基线)。核心逻辑层约 90% 可直接复用,只有隧道建立与分发链路需重写。
9. 已知限制
- DVT 只能改经纬度:
simulateLocationWithLatitude:longitude:仅接受两个参数。horizontalAccuracy、verticalAccuracy、altitude、floor、sourceInformation.isSimulatedBySoftware以及加速度计/陀螺仪/计步器由 iOS 自行合成或来自硬件,DVT 通道无法注入。这是所有同类工具(含 Xcode 自带的模拟定位)的共同边界。 - 部分 App 不受影响:使用独立定位通道、或在服务端做运动学交叉校验的 App 可能不会跟随模拟定位,或跟随了但数据被判定无效。
- 同一时间只能有一个工具占隧道:iOS 17+ 设备只有一条 RSD 连接,爱思助手/Xcode 与本工具会互相挤掉。
- 首次挂载镜像的签名步骤需要能访问 Apple TSS 服务器。
- 地图瓦片来自公开服务,仅供个人测试使用,请遵守相应服务条款。
10. 合法使用
本工具用于软件测试、开发调试、位置相关功能的回归验证等正当用途,例如:
- 测试 App 在不同城市/国家的展示与逻辑
- 验证轨迹回放、电子围栏、打卡类功能的边界情况
- 演示与教学
请勿用于欺骗他人、伪造行程记录、规避考勤或任何违法违规用途。使用本工具产生的一切后果由使用者承担。
特别说明:本工具不提供针对第三方应用风控/反作弊的绕过能力。如果你需要测试依赖海拔、气压计、计步器等硬件数据的功能,唯一可靠的方式是在你自己 App 的 Debug 构建里加入定位注入入口、自行构造完整的 CLLocation。