
文章目录
- 前言
- [一. 原理先行:虚拟定位是怎么"骗"过系统的](#一. 原理先行:虚拟定位是怎么“骗”过系统的)
-
- [1.1 Mock Location:系统自留的"正门"](#1.1 Mock Location:系统自留的“正门”)
- [1.2 坐标系:90% 的翻车都栽在这里](#1.2 坐标系:90% 的翻车都栽在这里)
- [二. 准备工作:装对工具,备好坐标](#二. 准备工作:装对工具,备好坐标)
-
- [2.1 下载安装 Fake GPS(附避坑)](#2.1 下载安装 Fake GPS(附避坑))
- [2.2 目标坐标从哪来:两条路任选](#2.2 目标坐标从哪来:两条路任选)
- [三. 一次性设置:打开"模拟位置"闸门](#三. 一次性设置:打开“模拟位置”闸门)
-
- [3.1 开启开发者选项](#3.1 开启开发者选项)
- [3.2 指定"模拟位置信息应用"](#3.2 指定“模拟位置信息应用”)
- [四. 日常使用:三步完成一次虚拟定位](#四. 日常使用:三步完成一次虚拟定位)
-
- [4.1 第一步:输入目标坐标](#4.1 第一步:输入目标坐标)
- [4.2 第二步:点播放,开始注入](#4.2 第二步:点播放,开始注入)
- [4.3 第三步:验证是否生效](#4.3 第三步:验证是否生效)
- [4.4 三个进阶技巧](#4.4 三个进阶技巧)
- [五. 排查手册:定位偏了先看这里](#五. 排查手册:定位偏了先看这里)
-
- [5.1 经典案例:坐标填错,蓝点"跑"到 600 米外](#5.1 经典案例:坐标填错,蓝点“跑”到 600 米外)
- [5.2 高频问题速查表](#5.2 高频问题速查表)
- [5.3 定位模式补充设置](#5.3 定位模式补充设置)
- [六. 风险与合规提醒](#六. 风险与合规提醒)
- 总结
前言

你有没有遇到过这样的场景:人在宿舍,某个 App 却要求"必须在教学区"才能完成签到;想测试一个带定位功能的小程序,又不可能真的跑到几公里外去点那一下。于是你搜到了"虚拟定位"这个词,装了个 App,兴致勃勃地输进去一串坐标------结果定位纹丝不动,或者干脆跑到了隔壁商圈。
先别急着卸载,大概率不是软件的问题,而是一个关键概念没有搞清楚:坐标系。
今天我们以 vivo / iQOO 手机(OriginOS 系统)+ Fake GPS(by Lexa)为例,从原理讲到实操,把"安装 → 设置 → 使用 → 验证 → 排查"整条链路完整走一遍。跟着做完,你会得到一套可复用的虚拟定位工作流:以后想定位到哪里,复制坐标、点一下播放就完成。
本期目标:掌握安卓端模拟定位的完整操作流程,并学会在"定位跑偏"时 3 分钟内锁定原因。
一. 原理先行:虚拟定位是怎么"骗"过系统的
1.1 Mock Location:系统自留的"正门"
很多同学以为虚拟定位要 root、要改系统文件,其实 Android 早就预留了官方通道------模拟位置(Mock Location) 。它本来是给开发者测试地图类 App 用的:系统允许某个被指定的 App 通过 LocationManager 向系统注入经纬度。注入生效后,GPS 芯片的真实上报会被"晾在一边",所有 App 拿到的都是这组注入坐标。
我们先把整条注入链路画出来:

从左到右拆开看:
- Fake GPS 只负责"播放"一组坐标,它自己不碰系统;
- 坐标能不能进系统,取决于开发者选项里是否把它指定为**"模拟位置信息应用"**,这是唯一的闸门;
- 闸门打开后,系统定位服务把注入坐标当作当前定位分发给所有 App,地图上的蓝点就落过去了。
核心结论:虚拟定位不是"攻击"系统,而是走系统自带的测试通道,这也是它无需 root 的根本原因。闸门没打开时,播放再多坐标都不会生效------后面排查问题会反复用到这一点。
1.2 坐标系:90% 的翻车都栽在这里
如果整篇文章只允许我讲一个概念,我会选坐标系。先看一个真实案例的落点差异:

同一栋教学楼,两套坐标系下的落点相差约 600 米。国内日常会碰到两套坐标系(百度地图还有第三套 BD-09,本文场景用不到):
| 坐标系 | 谁在用 | 特点 |
|---|---|---|
| WGS-84 | GPS 卫星、Fake GPS 注入 | 国际标准坐标 |
| GCJ-02 | 高德、腾讯地图 | 加密偏移坐标,俗称"火星坐标" |
问题就出在这里:在高德地图上搜索或长按得到的坐标是 GCJ-02 ,而 Fake GPS 期望输入的是 WGS-84。把高德坐标直接粘进去,等于在一个已经偏移过的坐标上再叠加一次系统级偏移------蓝点会落到目标地点东南方向约 500~600 米外,还偏偏是固定的方向和量级,非常有辨识度。
核心结论:给 Fake GPS 填 WGS-84(GPS 坐标);高德、腾讯地图里看到的坐标是 GCJ-02,必须先换算再输入。
二. 准备工作:装对工具,备好坐标
2.1 下载安装 Fake GPS(附避坑)
核心工具只需要一个:Fake GPS location(by Lexa),免费、界面干净、不需要 root,Google Play 上长期维护的老牌应用。
Google Play 直接搜索 "Fake GPS - by Lexa" 即可。如果 Play 商店登不上(就像我当时的情况),可以走正规 APK 镜像站:APKPure 或 APKMirror,同样搜应用名。这里有一个新坑要提醒大家:镜像站的"下载"按钮周围布满广告位,点错会直接跳转到广告域名,比如这种页面:

识别方法很简单:真正的下载按钮点击后会弹出确认框,写明应用名、版本号和文件大小;直接开始跳转广告页的基本都是广告位。认准带应用名和版本号的那一个。
提示:从第三方来源安装时,系统会提示"未知来源应用",允许一次即可;装完后建议用手机自带的安全扫描过一遍再用。
2.2 目标坐标从哪来:两条路任选
工具就位,接下来是坐标。推荐两条路线:
路线 A:直接用换算好的 GPS 坐标(推荐)。 我把学校常用地点整理成了一张坐标清单,每个地点都标好了 WGS-84 坐标,复制即用。节选几条给大家参考:
| 地点 | GPS 坐标(Fake GPS 直接输入) |
|---|---|
| 北门(杨桥西路) | 26.081023, 119.267192 |
| 东门(工业路) | 26.077496, 119.271480 |
| 图书馆(东北门) | 26.078112, 119.267534 |
| 科学楼 | 26.078129, 119.267929 |
| 子兴教学楼 | 26.079457, 119.268101 |
清单可以按需自己扩充,扩充方法就是路线 B。
路线 B:把高德坐标换算成 GPS 坐标。 如果目标地点不在清单里,在高德地图上取到坐标后换算即可。福州本地有一个经验公式,实测误差在 1 米左右:
text
GPS 纬度 ≈ 高德纬度 + 0.00314
GPS 经度 ≈ 高德经度 − 0.00477
换城市后这个近似就不能直接用了,通用解法是标准的 GCJ-02 → WGS-84 逆向偏移算法(用加密公式算出偏移量,再反向扣除),核心代码如下:
python
import math
A = 6378245.0 # 克拉索夫斯基椭球长半轴
EE = 0.00669342162296594323 # 第一偏心率平方
PI = math.pi
def out_of_china(lng, lat):
return not (73.66 < lng < 135.05 and 3.86 < lat < 53.55)
def _tlat(lng, lat):
ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat \
+ 0.1 * lng * lat + 0.2 * math.sqrt(abs(lng))
ret += (20.0 * math.sin(6.0 * lng * PI) + 20.0 * math.sin(2.0 * lng * PI)) * 2.0 / 3.0
ret += (20.0 * math.sin(lat * PI) + 40.0 * math.sin(lat / 3.0 * PI)) * 2.0 / 3.0
ret += (160.0 * math.sin(lat / 12.0 * PI) + 320.0 * math.sin(lat * PI / 30.0)) * 2.0 / 3.0
return ret
def _tlng(lng, lat):
ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng \
+ 0.1 * lng * lat + 0.1 * math.sqrt(abs(lng))
ret += (20.0 * math.sin(6.0 * lng * PI) + 20.0 * math.sin(2.0 * lng * PI)) * 2.0 / 3.0
ret += (20.0 * math.sin(lng * PI) + 40.0 * math.sin(lng / 3.0 * PI)) * 2.0 / 3.0
ret += (150.0 * math.sin(lng / 12.0 * PI) + 300.0 * math.sin(lng / 30.0 * PI)) * 2.0 / 3.0
return ret
def gcj02_to_wgs84(lng, lat):
if out_of_china(lng, lat):
return lng, lat
dlat = _tlat(lng - 105.0, lat - 35.0)
dlng = _tlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * PI
magic = 1 - EE * math.sin(radlat) * math.sin(radlat)
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((A * (1 - EE)) / (magic * sqrtmagic) * PI)
dlng = (dlng * 180.0) / (A / sqrtmagic * math.cos(radlat) * PI)
mglat, mglng = lat + dlat, lng + dlng
return lng * 2 - mglng, lat * 2 - mglat
print(gcj02_to_wgs84(119.272500, 26.074923)) # 某教学楼的 GCJ-02 坐标
测试环境:Windows 11、Python 3.10.11。实际运行输出如下:
text
(119.26772934538576, 26.078054330957105)
对照验证一下:GCJ-02 的 (119.272500, 26.074923) 换算回 GPS 坐标是 (119.267729, 26.078054)------经度差 0.00477、纬度差 0.00313,和福州经验公式完全对得上,两条路线互相印证,换算结果是可靠的。
三. 一次性设置:打开"模拟位置"闸门
接下来这两步只需要做一次,之后日常使用完全不用再碰。
3.1 开启开发者选项
进入 设置 → 关于手机,找到"软件版本号",连续点击 7 次,看到"您已处于开发者模式"的提示就成功了。
开启后,开发者选项的入口出现在系统设置里。以 OriginOS 为例,在 设置 → 系统管理与升级 页面就能看到它:

不同品牌手机的入口位置略有差异:小米 / 红米在 设置 → 更多设置 里,OPPO / 一加在 设置 → 其他设置 里,华为 / 荣耀则在 设置 → 系统和更新 里。路径不同,但"连点 7 次"和接下来要做的"选择模拟位置信息应用"这两个关键动作完全一致,大家可以按自己的机型对号入座。
提示:开发者选项本身只多开放一些调试能力,不影响日常使用;介意的话,全部设置完成后可以随时在开发者选项页面顶部把它关闭(关闭不影响已生效的模拟,直到下次播放前需要重新打开)。
3.2 指定"模拟位置信息应用"
这一步就是 1.1 节链路图里的"闸门"。进入 开发者选项,在"位置"分组找到**"选择模拟位置信息应用"**:

点击后会弹出系统应用选择框,勾选 Fake GPS:

设置成功后,开发者选项页面会显示"模拟位置信息应用:Fake GPS"。到这里,注入链路的闸门就打开了,接下来只差把坐标"播放"出去。
四. 日常使用:三步完成一次虚拟定位
设置完成后,每次使用的流程固定为"复制坐标 → 输入播放 → 验证",我们先用一张图把它串起来:
#mermaid-svg-YYLdfq9jf8gxEpT1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YYLdfq9jf8gxEpT1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YYLdfq9jf8gxEpT1 .error-icon{fill:#552222;}#mermaid-svg-YYLdfq9jf8gxEpT1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YYLdfq9jf8gxEpT1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YYLdfq9jf8gxEpT1 .marker.cross{stroke:#333333;}#mermaid-svg-YYLdfq9jf8gxEpT1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YYLdfq9jf8gxEpT1 p{margin:0;}#mermaid-svg-YYLdfq9jf8gxEpT1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YYLdfq9jf8gxEpT1 .cluster-label text{fill:#333;}#mermaid-svg-YYLdfq9jf8gxEpT1 .cluster-label span{color:#333;}#mermaid-svg-YYLdfq9jf8gxEpT1 .cluster-label span p{background-color:transparent;}#mermaid-svg-YYLdfq9jf8gxEpT1 .label text,#mermaid-svg-YYLdfq9jf8gxEpT1 span{fill:#333;color:#333;}#mermaid-svg-YYLdfq9jf8gxEpT1 .node rect,#mermaid-svg-YYLdfq9jf8gxEpT1 .node circle,#mermaid-svg-YYLdfq9jf8gxEpT1 .node ellipse,#mermaid-svg-YYLdfq9jf8gxEpT1 .node polygon,#mermaid-svg-YYLdfq9jf8gxEpT1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YYLdfq9jf8gxEpT1 .rough-node .label text,#mermaid-svg-YYLdfq9jf8gxEpT1 .node .label text,#mermaid-svg-YYLdfq9jf8gxEpT1 .image-shape .label,#mermaid-svg-YYLdfq9jf8gxEpT1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-YYLdfq9jf8gxEpT1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YYLdfq9jf8gxEpT1 .rough-node .label,#mermaid-svg-YYLdfq9jf8gxEpT1 .node .label,#mermaid-svg-YYLdfq9jf8gxEpT1 .image-shape .label,#mermaid-svg-YYLdfq9jf8gxEpT1 .icon-shape .label{text-align:center;}#mermaid-svg-YYLdfq9jf8gxEpT1 .node.clickable{cursor:pointer;}#mermaid-svg-YYLdfq9jf8gxEpT1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YYLdfq9jf8gxEpT1 .arrowheadPath{fill:#333333;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YYLdfq9jf8gxEpT1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YYLdfq9jf8gxEpT1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YYLdfq9jf8gxEpT1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YYLdfq9jf8gxEpT1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YYLdfq9jf8gxEpT1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YYLdfq9jf8gxEpT1 .cluster text{fill:#333;}#mermaid-svg-YYLdfq9jf8gxEpT1 .cluster span{color:#333;}#mermaid-svg-YYLdfq9jf8gxEpT1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YYLdfq9jf8gxEpT1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YYLdfq9jf8gxEpT1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-YYLdfq9jf8gxEpT1 .icon-shape,#mermaid-svg-YYLdfq9jf8gxEpT1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YYLdfq9jf8gxEpT1 .icon-shape p,#mermaid-svg-YYLdfq9jf8gxEpT1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YYLdfq9jf8gxEpT1 .icon-shape .label rect,#mermaid-svg-YYLdfq9jf8gxEpT1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YYLdfq9jf8gxEpT1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YYLdfq9jf8gxEpT1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YYLdfq9jf8gxEpT1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 从坐标清单复制 WGS-84 坐标
打开 Fake GPS
打开菜单并选择 Go to
粘贴坐标并点确定
点右下角绿色播放按钮
打开目标 App 验证蓝点
4.1 第一步:输入目标坐标
打开 Fake GPS,主界面是一张世界地图。点左上角的汉堡菜单(☰) ,选择 Go to:

在弹出的对话框中粘贴坐标。注意格式:纬度, 经度,中间用英文逗号加空格 ,例如 26.078129, 119.267929:

点"确定"后,地图会跳转到目标位置,图钉落在目标区域。此时只是"预览",还没有真正注入。
4.2 第二步:点播放,开始注入
点右下角的绿色播放按钮 ▶,模拟正式开始(旁边灰色的是暂停按钮):

播放后 Fake GPS 会在后台常驻,通知栏出现它的常驻通知。如果某次打开发现定位不对,先检查这个按钮是否处于播放状态。
4.3 第三步:验证是否生效
验证有两个层次,先系统后应用。
第一层:看通知栏。 下拉通知栏,Fake GPS 的通知会显示当前注入的 Lat / long 数值,同时系统会给出一条提示"当前仅可使用模拟的位置信息":

通知栏数值等于你输入的 GPS 坐标 + 系统提示出现,说明系统层面注入成功。
第二层:看目标 App 的蓝点。 打开高德地图,蓝点应落在目标地点附近:

再打开真正要用的目标 App 验证。比如我用的签到类 App,蓝点进入打卡范围后,页面会明确显示"当前定位在打卡范围内":

小坑预警:目标 App 内显示的坐标数值可能和你输入的不一样,比如输入 26.078129、App 里却显示 26.0759 一类的数字。这是因为 App 内部把 WGS-84 转成了自己的坐标系(高德系 App 转 GCJ-02)。所以别拿显示值和输入值做直接对比,看蓝点是否落在目标范围内即可。
4.4 三个进阶技巧
基础流程之外,Fake GPS 还有三个功能值得顺手掌握:
- 搜索地名:Go to 对话框本身也支持按名称搜索地点(对英文名称效果最好),搜到再播放,临时用一次时可以省掉查坐标的步骤;
- Favorites 收藏:把常用坐标加星收藏,之后从菜单里一键直达,和 2.2 节的坐标清单配合使用最顺手------清单存数据、收藏管调用;
- Routes 路线:设置起点、终点和移动速度后,蓝点会沿着路线匀速"走"过去,适合测试轨迹类、里程类的功能,玩法比单点定位更丰富。
五. 排查手册:定位偏了先看这里
如果验证不通过,别慌,95% 的问题都能用下面这张决策树在几分钟内定位原因:
#mermaid-svg-145t8BCIU2uZlbhH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-145t8BCIU2uZlbhH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-145t8BCIU2uZlbhH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-145t8BCIU2uZlbhH .error-icon{fill:#552222;}#mermaid-svg-145t8BCIU2uZlbhH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-145t8BCIU2uZlbhH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-145t8BCIU2uZlbhH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-145t8BCIU2uZlbhH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-145t8BCIU2uZlbhH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-145t8BCIU2uZlbhH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-145t8BCIU2uZlbhH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-145t8BCIU2uZlbhH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-145t8BCIU2uZlbhH .marker.cross{stroke:#333333;}#mermaid-svg-145t8BCIU2uZlbhH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-145t8BCIU2uZlbhH p{margin:0;}#mermaid-svg-145t8BCIU2uZlbhH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-145t8BCIU2uZlbhH .cluster-label text{fill:#333;}#mermaid-svg-145t8BCIU2uZlbhH .cluster-label span{color:#333;}#mermaid-svg-145t8BCIU2uZlbhH .cluster-label span p{background-color:transparent;}#mermaid-svg-145t8BCIU2uZlbhH .label text,#mermaid-svg-145t8BCIU2uZlbhH span{fill:#333;color:#333;}#mermaid-svg-145t8BCIU2uZlbhH .node rect,#mermaid-svg-145t8BCIU2uZlbhH .node circle,#mermaid-svg-145t8BCIU2uZlbhH .node ellipse,#mermaid-svg-145t8BCIU2uZlbhH .node polygon,#mermaid-svg-145t8BCIU2uZlbhH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-145t8BCIU2uZlbhH .rough-node .label text,#mermaid-svg-145t8BCIU2uZlbhH .node .label text,#mermaid-svg-145t8BCIU2uZlbhH .image-shape .label,#mermaid-svg-145t8BCIU2uZlbhH .icon-shape .label{text-anchor:middle;}#mermaid-svg-145t8BCIU2uZlbhH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-145t8BCIU2uZlbhH .rough-node .label,#mermaid-svg-145t8BCIU2uZlbhH .node .label,#mermaid-svg-145t8BCIU2uZlbhH .image-shape .label,#mermaid-svg-145t8BCIU2uZlbhH .icon-shape .label{text-align:center;}#mermaid-svg-145t8BCIU2uZlbhH .node.clickable{cursor:pointer;}#mermaid-svg-145t8BCIU2uZlbhH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-145t8BCIU2uZlbhH .arrowheadPath{fill:#333333;}#mermaid-svg-145t8BCIU2uZlbhH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-145t8BCIU2uZlbhH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-145t8BCIU2uZlbhH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-145t8BCIU2uZlbhH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-145t8BCIU2uZlbhH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-145t8BCIU2uZlbhH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-145t8BCIU2uZlbhH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-145t8BCIU2uZlbhH .cluster text{fill:#333;}#mermaid-svg-145t8BCIU2uZlbhH .cluster span{color:#333;}#mermaid-svg-145t8BCIU2uZlbhH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-145t8BCIU2uZlbhH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-145t8BCIU2uZlbhH rect.text{fill:none;stroke-width:0;}#mermaid-svg-145t8BCIU2uZlbhH .icon-shape,#mermaid-svg-145t8BCIU2uZlbhH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-145t8BCIU2uZlbhH .icon-shape p,#mermaid-svg-145t8BCIU2uZlbhH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-145t8BCIU2uZlbhH .icon-shape .label rect,#mermaid-svg-145t8BCIU2uZlbhH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-145t8BCIU2uZlbhH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-145t8BCIU2uZlbhH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-145t8BCIU2uZlbhH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不一致
一致
是
否
是
否
是
否
定位结果不符合预期
通知栏坐标与输入一致吗
Fake GPS 未在播放状态
重新点播放按钮
蓝点整体偏移约 600 米吗
输入了 GCJ-02 坐标
先换算成 WGS-84 再输入
目标 App 纹丝不动吗
App 缓存了旧定位
强制停止后重新打开
蓝点在两地来回跳吗
关闭 Wi-Fi 与蓝牙扫描
定位模式改为仅设备
重启后模拟已失效
重新播放即可
5.1 经典案例:坐标填错,蓝点"跑"到 600 米外
我自己踩过的坑,拿出来给大家复盘。当时目标是校园里的一栋楼,我直接把地图上查到的坐标输了进去,蓝点却始终落在校园东南约 600 米的商圈方向(西禅寺、万象城一带),怎么调都不对。回头看通知栏,显示的是这个:

可以看到注入的坐标是 26.074246, 119.272678------这正是那栋楼的 GCJ-02 坐标。GCJ-02 相对 WGS-84 在福州整体向东南偏移约 600 米,把它当作 GPS 坐标注入,等于"错上加错",蓝点自然稳稳落在 600 米外。
修正方法:用 2.2 节的换算脚本把它转回 WGS-84(26.077377, 119.267907),重新输入播放,蓝点立刻回到楼栋上。
顺带解释一下为什么偏偏是"东南"方向:GCJ-02 的加密偏移是非线性算法,在全国不同区域偏移方向和量级都不一样,福州一带恰好是"南偏 + 东偏",所以填错时蓝点会稳定出现在东南方向。反过来想,固定的偏移方向反而成了判断坐标系填错的最有力线索------看到它,别犹豫,直接查坐标。
经验:出现"固定方向、固定量级(约半公里)的偏移"时,优先怀疑坐标系填错,而不是反复拖动地图、反复重启 App。
5.2 高频问题速查表
| 现象 | 原因 | 解决办法 |
|---|---|---|
| 定位偏到目标东南约 500~600 米 | 填了 GCJ-02(高德)坐标 | 换算成 WGS-84 后重新输入 |
| 通知栏数值不对 / 没有系统提示 | Fake GPS 没在播放状态 | 重新打开 App 点播放按钮 |
| 换了坐标,目标 App 纹丝不动 | App 缓存了旧定位 | 强制停止目标 App 后重开 |
| 蓝点在真实位置和模拟位置之间跳 | 网络定位(Wi-Fi / 基站)与 GPS 模拟冲突 | 关闭"Wi-Fi 扫描 / 蓝牙扫描",定位模式选"仅设备(GPS)" |
| Fake GPS 地图上图钉位置不对 | 谷歌底图与国内坐标系不一致 | 不用管它,以目标 App 蓝点为准 |
| 重启手机后失效 | 模拟状态不随重启保留 | 重新打开 Fake GPS 点播放 |
| 想恢复真实定位 | --- | Fake GPS 点停止按钮,或把"模拟位置信息应用"设回"无" |
5.3 定位模式补充设置
如果遇到蓝点来回跳动,除了决策树里的两步,还可以做一次彻底设置:进入地图 App 或系统设置,把定位模式改为**"仅设备(GPS)",并关闭"Wi-Fi 扫描"和"蓝牙扫描"**两个辅助定位项。这样系统只能走 GPS 通道,而 GPS 通道正被我们模拟,蓝点就稳定了。
六. 风险与合规提醒
工具讲完了,最后几句实在话必须说在前面:
- 模拟可被检测:Android 的模拟位置自带标记,考勤、银行、游戏类 App 都可能识别"正在使用模拟位置",轻则拒绝服务,重则留下风控记录;
- 系统可能交叉验证:部分签到系统会结合 Wi-Fi 环境、基站、登录记录等多渠道核验,单一 GPS 模拟并不是万能的;
- 用完即恢复:模拟挂太久,外卖、打车、微信"附近的人"拿到的都是假位置,容易造成误下单、误导航,给自己添麻烦;
- 合规使用:本文内容仅用于开发测试、学习研究和功能体验,请遵守所在平台的服务条款与相关规定。
总结
到这里,安卓端虚拟定位的整条链路我们就完整走通了。回顾一下今天的收获:
- 原理:虚拟定位走的是系统自带的 Mock Location 通道,闸门是开发者选项里的"选择模拟位置信息应用";
- 关键概念:WGS-84 与 GCJ-02 两套坐标不能混填,给 Fake GPS 的必须是 GPS 坐标,高德坐标要先换算;
- 流程:复制坐标 → Go to 粘贴 → 点播放 → 通知栏和目标 App 双重验证;
- 排查:固定 600 米偏移查坐标系,纹丝不动查播放状态和 App 缓存,来回跳动查定位模式。
最要紧的一条,还是分清坐标系------它解释了为什么"照着教程做却差了半公里"。下一步,你可以把自己常用的地点坐标整理成一张清单,配合 Fake GPS 的 Favorites(收藏)功能一键选取;遇到新的偏移问题,回到第五节的决策树按图索骥即可。如果这篇文章帮你少走了弯路,欢迎点赞收藏,评论区聊聊你踩过的定位坑~