Files
ios-location-track/README.md
T

17 KiB
Raw Blame History

iOS 虚拟定位轨迹工具(macOS / Windows)

中文 | English

在电脑上给 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.1_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 隧道。本工具有三种方式:

  1. 免 root(默认,推荐):自动执行 pymobiledevice3 remote start-tunnel --native --script-mode,借用 Apple 自带 remoted 的隧道。打包版通过 tunnel-helper 自调用实现,不依赖外部 Python。
  2. 管理员模式:界面上点「以管理员权限重建隧道」(会弹系统密码框),或直接 sudo ./scripts/run.sh。
  3. 手动填 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. 沿真实道路跑一条轨迹

  1. 连接设备 → 「连接设备」(iOS 17+ 会自动建隧道,最长约 1 分钟)
  2. 点「添加途经点」,在地图上点起点、中间点、终点(至少 2 个)
  3. 点「加载 OSRM 路线」→ 生成真实路网折线(无网络时自动退化为直线)
  4. 调「播放倍速」(例如 20x 可以在几秒内跑完 10 公里)
  5. 点「播放」→ 手机定位会沿轨迹移动;地图上定位点与进度实时更新
  6. 点「停止」→ 手机立刻恢复真实定位

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。