简介面向移动端开发者的腾讯地图 Android 定位项目实例适合正在学习定位接入或需要参考 SDK 集成写法的初学者与实践者。资源围绕腾讯地图定位能力展开完整演示了 SDK 集成、定位权限申请、定位服务启动及结果回调等关键环节并结合实际工程目录给出了可直接参考的配置与代码组织方式。压缩包共 76 个文件约 4.16MB包含 TencentLocationSDK_v5.0.1 与 TencentMapSDK_Raster_v1.0.6 等 jar 库、适配 armeabi/armeabi-v7a/x86 的 so 文件、Java 源码、布局与配置 xml、APK 成品及 Android 工程元文件基本覆盖了从依赖库到运行验证的完整链路。工程内还包含可运行的 APK 与完整工程结构便于对照代码理解定位模式、更新频率和回调逻辑并应对定位延迟、权限与电量等常见问题已有 727 人学习。对于想快速跑通腾讯地图定位、理解 Android 工程结构或排查定位集成问题的人来说这份资源提供了拿来即用的参考工程可按目录结构逐层阅读源码与配置节省自行搭建环境的时间。1. 腾讯地图定位室外能定、室内漂移先搞清楚它在解决什么问题做 Android 和 iOS 的定位功能时第一次接入腾讯地图定位 SDK 的开发者通常有两种反应:一种是觉得太简单初始化完调一个接口就能拿坐标另一种是被坑到怀疑人生——同一部手机、同一个地点早中晚三次拿到的坐标能差出几百米室内办公位直接飘到隔壁写字楼。这两种反应其实都正常因为定位这个功能从表面看是一个接口但背后是一整套由 GPS、基站、Wi-Fi、传感器和缓存策略组成的决策链路。这篇笔记要解决的问题很具体腾讯地图定位 SDK 从集成到上线每一步怎么做、参数怎么设、哪些坑必须提前避。定位是地图类 App 的地基位置不准后面的逆地理编码、POI 搜索、路线规划全是错的。适合正在做或者准备做定位相关功能的应用开发者包括用原生 Android/iOS 开发、用 Flutter/uni-app 等跨平台方案接 SDK 的场景。读完你可以直接照着搭一套能上生产环境的定位方案而不是停留在 Demo 能跑通的水平。2. 接入腾讯地图定位 SDK配置清单、最小工程与三种接入路径怎么选2.1 腾讯地图定位在技术栈里的位置不是坐标系是一套融合决策在动手写代码之前有必要说清楚腾讯地图定位 SDK 到底做了什么事。它不只是一个 GPS 读取器而是一个多源融合定位引擎。它的输入包括卫星定位信号GPS/北斗、基站信号Cell ID、Wi-Fi 信号BSSID 和 RSSI 指纹、传感器数据加速度计、陀螺仪、磁力计甚至是上一次定位的缓存结果。SDK 内部有一套决策逻辑根据当前环境的信号质量和变化情况动态选择最优信源或者多个信源融合。这套决策逻辑决定了它的几个行为特征在开阔地带GPS 信号强定位精度能达到 10 米以内在室内或高架下GPS 失效SDK 会退化成基站Wi-Fi 的定位模式精度通常 30~100 米甚至更差在完全没有网络信号的区域基站和 Wi-Fi 都不工作只能依赖缓存这时候精度不可控。理解这一点是配置一切参数的前提——你不是在配置一个开关你是在配置当信号环境下滑时SDK 应该怎么表现。对于做业务开发的工程师SDK 封装了上述融合逻辑对外暴露的是统一的定位回调。这意味着你不需要自己去拼 GPS 和网络信号但你必须理解返回值里的精度参数精度半径是什么含义以及在不同场景下如何判断这个定位结果是否可信。后文会具体讲这两个问题。2.2 腾讯地图定位的最小集成配置Android 权限、Key 与初始化接入腾讯地图定位 SDK 的第一步是在腾讯位置服务官网创建应用并申请 Key。需要注意Key 是绑定应用包名Android或 Bundle IDiOS的申请时填错了后面排查起来非常隐蔽——SDK 初始化不报错但定位回调永远走 onError 或超时。这条坑第 5 章会细说。以下是 Android 侧的最小集成步骤。Android Studio 工程Gradle 使用 Groovy DSL版本选用目前常见的 4.x// 工程根目录 build.gradle 的 allprojects.repositories 里添加 maven { url https://mirrors.tencent.com/repository/maven/tencent-public/ } // app/build.gradle 的 dependencies 中添加 implementation com.tencent.map:tencent-map-location:8.0.8!-- AndroidManifest.xml 中申请权限定位权限是运行时权限还需要在代码中动态申请 -- uses-permission android:nameandroid.permission.INTERNET / uses-permission android:nameandroid.permission.ACCESS_COARSE_LOCATION / uses-permission android:nameandroid.permission.ACCESS_FINE_LOCATION / uses-permission android:nameandroid.permission.ACCESS_WIFI_STATE / uses-permission android:nameandroid.permission.CHANGE_WIFI_STATE / uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE / uses-permission android:nameandroid.permission.CHANGE_NETWORK_STATE / uses-permission android:nameandroid.permission.WAKE_LOCK /// 在 Application 或首个 Activity 的 onCreate 中初始化 public class MainActivity extends AppCompatActivity { private TencentLocationManager locationManager; private TencentLocationListener locationListener; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化定位 SDK参数依次为Context、AppKey locationManager TencentLocationManager.getInstance(this); locationManager.setAppKey(你的Key); // 创建定位监听器 locationListener new TencentLocationListener() { Override public void onLocationChanged(TencentLocation location, int errorCode, String errorReason) { if (errorCode TencentLocation.ERROR_OK) { double lat location.getLatitude(); double lng location.getLongitude(); float accuracy location.getAccuracy(); // 业务中使用坐标和精度后续也可以调用逆地理编码接口 } else { // 定位失败errorReason 是失败原因描述 } } }; } }上面的代码是最小可用的初始化骨架。重点看TencentLocationManager.getInstance(this)返回的是单例setAppKey只对当前实例生效如果多次初始化会复用同一个实例。TencentLocationListener里的onLocationChanged是异步回调不要在这个回调里做耗时操作因为定位回调本身来自 SDK 的内部线程。权限方面要特别注意Android 6.0 以上必须在代码中动态申请定位权限只用 Manifest 声明不够。定位权限申请失败时SDK 的onLocationChanged会回调errorCode 1权限错误而不会直接崩溃。2.3 三种常见的集成路径及选型建议腾讯地图定位 SDK 除了原生 AndroidJava/Kotlin和 iOSObjective-C/Swift官方还提供了 Flutter 插件、React Native 插件以及 uni-app 插件。实际项目里怎么选取决于现有技术栈但有几个决策点值得注意第一种是原生开发。如果你的 App 核心功能就是地图建议直接用原生方式。原因有三个原生 API 最全所有参数都能调定位 SDK 是系统级服务原生方式对生命周期控制最精准比如onStop停止定位释放资源排错时看日志最直观SDK 的 logcat 输出在原生环境下是无损的。缺点是双端要维护两套代码。第二种是跨平台框架。Flutter 和 RN 生态里都有腾讯地图定位的插件flutter_tencent_location、react-native-tencent-location这类插件本质是 MethodChannel 封装了原生 SDK。选这条路的前提是你的项目已经有完善的跨平台基础不希望为了定位单独起两个原生工程。注意插件版本和原生 SDK 版本不是一一对应的升级插件可能不会同步升级底层 SDK遇到定位行为异常时先检查插件锁定的原生 SDK 版本。第三种是 uni-app 环境。uni-app 的定位模块通常配合内置的uni.getLocation使用但如果你需要高精度定位、连续定位或后台定位uni.getLocation的能力是不够的需要原生插件市场里的腾讯定位插件。此时要注意插件是基于哪个原生 SDK 版本封装的以及是否支持离线打包这两个问题直接决定了你的打包流程复杂度。选型建议的总结论如果预算和人力允许优先原生如果跨平台是硬约束优先选插件维护活跃的方案并把插件锁定的原生 SDK 版本写进技术文档如果只是业务功能里需要一次获取当前位置而不是持续追踪那么考虑直接用uni.getLocation这类系统级 API 就够了不必引入腾讯地图定位 SDK。3. 定位模式怎么选GPS 优先、网络优先和低功耗的适用边界3.1 腾讯地图定位的三种模式行为差异比参数差异更明显腾讯地图定位 SDK 的TencentLocationManager提供了三种定位模式通过setLocationMode设置。这个参数没有绝对的好坏只有适配场景上的差异理解它的机制比记住选哪个更重要。第一种是 GPS 优先模式TencentLocationManager.GPS_MODE。在这种模式下SDK 先等 GPS 定位结果如果等待时间内 GPS 没有返回 (比如室内)会切换或补充网络定位。这个模式的特点是定位结果精度高但耗时可能长冷启动时 GPS 星历没有缓存首次定位可能要 10~30 秒。这个模式适合室外持续定位场景比如跑步轨迹记录、骑行导航。第二种是网络定位模式TencentLocationManager.NETWORK_MODE。SDK 直接使用基站和 Wi-Fi 进行定位不等待 GPS。速度快通常 1~3 秒返回结果但对环境敏感城区基站密度高精度尚可郊区基站覆盖稀疏可能差出 200 米以上。这个模式适合那些不需要高精度、但需要快速返回的业务比如城市级签到、区域进入判断。第三种是低功耗模式TencentLocationManager.LOW_POWER_MODE。这个模式不是单纯的省电而是 SDK 优先使用缓存和传感器进行位置估算尽量不触发 GPS 和网络扫描。结果可能很旧也可能不准但耗电极低。适合对位置实时性要求极低的应用比如后台统计路径、设备管理类应用。3.2 设置定位模式与定位间隔参数组合与回调频率的关系// 设置定位模式为 GPS 优先 locationManager.setLocationMode(TencentLocationManager.GPS_MODE); // 设置定位结果回调的间隔单位毫秒 locationManager.setInterval(5000); // 发起定位参数 true 表示进行一次定位后自动停止false 表示连续定位 int result locationManager.requestLocationUpdates(collection, locationListener);setInterval(5000)并不是严格意义上的每 5 秒回调一次而是 SDK 最多 5 秒回调一次。如果信号环境差实际的回调间隔会拉长。另外requestLocationUpdates的第一个参数collection是一个TencentLocationRequest对象可以通过它设置更细粒度的参数:TencentLocationRequest request new TencentLocationRequest(); // 设置是否需要逆地理编码返回附近的地址描述 request.setNeedAddress(true); // 设置定位精度级别精准定位或粗略定位 request.setLevel(TencentLocationRequest.REQUEST_LEVEL_GENERAL); // 是否需要包含 POI 信息 request.setNeedPoi(true); // 是否需要包含室内定位信息 request.setNeedIndoorLocation(true);setNeedAddress如果设为 true回调里TencentLocation对象会携带getAddress()、getAreaStat()等描述信息但代价是每次定位在拿到坐标后还要多一次网络请求耗时和流量都会增加。如果业务只需要坐标建议设为 false等需要地址描述时再用逆地理编码接口这样定位过程更干净。定位间隔和精度的组合逻辑是间隔越短功耗越高但轨迹连续性越好精度级别设得越高REQUEST_LEVEL_GENERAL表示一般精度REQUEST_LEVEL_GLOBAL表示全球精度REQUEST_LEVEL_ADMIN表示行政区级别回调越慢。建议按业务实际需求设置不要盲目追求高精度连续回调——那等于让用户的手机一直处于高功耗模式耗电曲线会很糟糕。3.3 场景化参数配置一套刚落地就能用的推荐值不同的业务场景对定位参数的要求完全不一样下面是几种常见场景的推荐配置组合可以直接参考使用。外卖/打车类应用需要持续上报位置追求的是精度和更新频率的平衡使用 GPS 优先模式间隔 2~3 秒REQUEST_LEVEL_GENERALsetNeedAddress(false)让轨迹点自己叠加逆地理编码信息反而更合理。签到/打卡类应用只求快速拿一个坐标使用网络定位模式间隔设 0值设为 0 表示只定位一次就停止RETURN_TYPE_LOCATION拿到坐标后立即调用逆地理编码接口获取地址描述。运动健康类应用要长时间在后台记录轨迹使用 GPS 优先模式间隔 5 秒同时防止手机休眠导致定位中断需要申请WAKE_LOCK权限并且在前台服务中运行。这里要注意setInterval设得太短低于 2 秒并不会显著提高轨迹平滑度——GPS 信号本身有抖动5 秒间隔配合轨迹抽稀算法通常就够了。4. 把坐标变成业务能用的东西逆地理编码、坐标系与 Web 服务兜底4.1 腾讯地图坐标系你拿到的坐标要到哪个坐标系里用腾讯地图定位 SDK 返回的经纬度是基于 GCJ-02国测局坐标系的。这个坐标系是国内通用的加密坐标系它和 GPS 原始坐标WGS-84之间有一个非线性偏移偏移量在城市尺度上通常在 100~700 米之间。这意味着一个很常见的坑把腾讯定位 SDK 拿到的坐标直接丢到高德地图或者谷歌地图的 SDK 里去标点——位置一定偏。反过来也是。如果你要用腾讯定位的坐标去调用其他地图服务必须先做坐标转换如果你用的是腾讯系的地图 SDK腾讯地图和腾讯位置服务那坐标直接可用不需要转换。// 如果你需要把 GCJ-02 坐标转成 WGS-84 坐标常见做法是使用公开的转换算法 // 注意这个转换是近似逆变换最大误差在几米量级业务上通常可接受 public double[] gcj02ToWgs84(double lat, double lng) { double a 6378245.0; double ee 0.00669342162296594323; double dLat transformLat(lng - 105.0, lat - 35.0); double dLng transformLng(lng - 105.0, lat - 35.0); double radLat lat / 180.0 * Math.PI; double magic Math.sin(radLat); magic 1 - ee * magic * magic; double sqrtMagic Math.sqrt(magic); dLat (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * Math.PI); dLng (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI); double mgLat lat dLat; double mgLng lng dLng; return new double[]{lat * 2 - mgLat, lng * 2 - mgLng}; }上面的代码摘了一段近似逆变换的方法。transformLat和transformLng是两个公式函数网上有公开版本这里不展开贴全本质是模拟 GCJ-02 的偏移多项式。这个转换方法的核心价值在于当你的 App 需要把腾讯定位坐标传给使用 WGS-84 的海外地图服务时不至于直接把偏移量带给用户。当然如果业务完全跑在腾讯系产品内这段代码根本不需要写直接消费坐标就行。4.2 逆地理编码从坐标到地址描述的完整调用链拿到坐标之后业务往往还需要我现在在哪的可读描述比如北京市朝阳区某街道某园区 3 号楼。这就是逆地理编码的活。腾讯定位 SDK 的setNeedAddress(true)可以让你在定位回调里直接拿到地址描述但如果定位成功后你还需要 POI 信息、周边行政区域等结构化数据建议单独调用 Web 服务 API。// 使用腾讯位置服务 Web API 进行逆地理编码 // 请求地址https://apis.map.qq.com/ws/geocoder/v1/ // 参数lat、lngGCJ-02 坐标系、key你的 API Key String url https://apis.map.qq.com/ws/geocoder/v1/?location lat , lng key apiKey; // 使用 OkHttp 或 HttpURLConnection 发送 GET 请求 // 返回值是 JSON其中 result.address 是格式化地址result.formatted_addresses 是推荐地址// 如果你在 Node.js 后端做聚合服务可以这样调腾讯逆地理接口 const http require(https); const url /ws/geocoder/v1/?location${lat},${lng}key${apiKey}; http.get({ hostname: apis.map.qq.com, path: url }, (res) { let data ; res.on(data, (chunk) data chunk); res.on(end, () { const json JSON.parse(data); if (json.status 0) { console.log(json.result.address); console.log(json.result.formatted_addresses.recommend); } else { console.log(geocoder failed:, json.message); } }); });上面给出了客户端和服务端两种调用方式。需要强调的是逆地理编码 Web API 的调用域名是apis.map.qq.com不是定位 SDK 的域名所以你的服务器如果开了防火墙白名单需要确保这个域名可用。另外腾讯的 Web API 对 QPS 有限制基础配额通常几百次/秒如果业务有批量坐标解析的需求建议把解析结果做缓存不要每次都打接口。4.3 定位失败时让业务兜底的缓存与降级策略定位不可能永远成功。具体表现为GPS 定位超时、网络定位因为信号不可用失败、用户在系统设置里关掉了定位权限、SDK 回调 errorCode 非 0。这些情况在真实用户环境里不是噪声是确定会发生的场景。我一般会在客户端做两层兜底第一层维护上次定位成功的坐标缓存。定位失败时直接使用缓存坐标返回给业务并附带一个标志字段比如isCachedtrue这样业务方知道这份坐标不是实时坐标在有严格精度要求的业务比如计费触发里可以拒绝使用在非关键业务里则可以直接消费。第二层在服务端设计一个位置查询的降级顺序客户端线上定位 → 客户端缓存 → 服务端根据用户最近上报的位置估算 → 默认值。越靠后的兜底精度越差但至少不会让业务流程中断。// 客户端缓存定位结果的示例逻辑 private TencentLocation lastLocation; private static final long CACHE_VALID_MS 5 * 60 * 1000; // 缓存有效期5分钟 Override public void onLocationChanged(TencentLocation location, int errorCode, String errorReason) { if (errorCode TencentLocation.ERROR_OK) { lastLocation location; deliverLocation(location, false); } else { if (lastLocation ! null System.currentTimeMillis() - lastLocation.getTime() CACHE_VALID_MS) { deliverLocation(lastLocation, true); // 标记为缓存结果 } else { deliverLocation(null, false); // 业务自行处理 } } }缓存有效期是根据业务场景设置的签到类业务缓存有效期可以放宽到 10 分钟也没问题外卖配送轨迹类业务缓存有效期建议缩短到 1 分钟以内。核心原则是宁可给一个标记过期的坐标也不要在关键业务里用未知来源的坐标。坐标本身没有绝对真值它是一个概率判断SDK 返回的getAccuracy()就是这个概率判断的量化表达——值越小越可信。5. 避坑指南定位 SDK 最常见的五个坑现象、原因、解决5.1 室内定位漂移严重模拟器上测试也异常现象在写字楼或者商场室内腾讯地图定位返回的坐标点在地图上无规律跳动有时候偏离真实位置几百米。在 Android 模拟器里测试时同样出现离谱结果明明模拟器设置了某个位置返回的坐标却完全不匹配。原因室内场景下 GPS 信号极弱或不可用SDK 退化为基站和 Wi-Fi 定位。楼内 Wi-Fi 信号被多个 AP 覆盖AP 的 MAC 地址和信号强度指纹可能不在腾讯的定位数据库中或者数据库里的位置已过时比如 AP 挪过位置。模拟器的问题更直接——模拟器大多数底层不提供真正的 GPS 硬件定位实现依赖于模拟器宿主机的网络位置但默认的模拟器网络配置不会上报 Wi-Fi 扫描结果所以 SDK 只能用 GeoIP 方式粗定位误差必然大。解决对于室内场景建议接入腾讯的室内定位方案通过 Wi-Fi 指纹和气压计楼层识别普通定位 SDK 不做室内精确定位的承诺如果室内定位是核心需求还需要额外部署或接入室内地图数据。对于模拟器测试不要用模拟器验证定位精度改用真机并到开阔室外测试如果确实需要在模拟器上验证流程可以直接在测试代码里 mock 定位结果或者使用 Android 模拟器的 Extended Controls 设置 GPS 坐标并把模拟器的 GPS 信号设置为最强。5.2 定位回调偶尔完全没有响应现象requestLocationUpdates之后回调迟迟不触发等待几十秒也没有结果也没有 error 回调。Logcat 里看不到明显的异常。抓包发现没有向腾讯定位服务器发起请求。原因由于定位属于系统敏感权限部分 ROM 在用户拒绝过一次定位权限后后续申请权限时展示的弹窗行为不同有的 ROM 会勾选下次不再询问此时权限弹窗不再弹出代码里的requestPermissions直接回调失败但没有明显错误而 SDK 的上层没有感知到权限变化就出现了没有回调的现象。另一种可能是 App 在 MIUI/EMUI 等系统中被限制了后台定位权限即使前台没有杀死进程系统也不允许应用访问定位服务。解决在onResume里检查checkSelfPermission如果权限不是 granted 状态立即重新申请或引导用户去设置页打开。更稳妥的是把权限申请和定位启动解耦先申请权限成功后再调用requestLocationUpdates。另外建议在 SDK 初始化前检测定位开关是否开启如果没有开启直接提示用户。定位开关和权限是两个完全不同的体系都缺失时定位是不可能成功的。5.3 定位结果在部分手机上系统性偏移现象同一部手机、同一个地点用腾讯地图定位 SDK 和系统自带 GPS 工具读取到的坐标显示的位置不一致偏移方向一致且偏移量相对固定。换一台手机可能又变成另一个偏移量。原因这是典型的厂商定位芯片差异问题。某些手机厂商在系统层面做了 GNSS 原始定位的滤波或者坐标偏置处理导致 APP 通过 SDK 拿到的原始定位数据和系统输出的位置不一样。特别是国产手机里一些系统级优化定位的 ROM 设置会在系统层面修改定位输出的行为。解决这个问题没有完全根治的办法因为 SD 无法控制系统对 GPS 芯片数据的加工。可操作的手段包括连续发起多次定位请求使用getAccuracy()过滤掉精度差的点再对剩余点做平均处理或者在业务允许的情况下直接使用最近一次定位结果。如果偏移总是固定且可复现比如始终向北偏 50 米可以在客户端做硬编码补偿但这个办法不优雅别轻易进入生产代码——它不通用还有被手机系统更新推翻的风险。5.4 服务端用逆地理编码接口时频繁限流或报错现象服务端调用腾讯逆地理编码 Web API 频繁返回status7无权限或配额不足或status120请求阻塞。原因腾讯位置服务的 Web API 默认有每分钟请求配额通常是每分钟几十次到几百次具体看账号等级。业务侧批量处理用户坐标时使用同步串行方式或者没有做去重缓存时单位请求数很容易超配额。另外如果请求参数里带了不合法坐标比如超出经纬度范围也会计入错误配额从而额外消耗额度。解决服务端务必加缓存层同一个坐标近期重复请求直接返回缓存结果对超出配额的情况做指数退避重试同时在代码里过滤掉明显非法的坐标——lat不在[-90, 90]范围、lng不在[-180, 180]范围就直接丢弃不发起请求。还有一个额外建议如果单日调用量真的很大可以考虑申请更高配额而不是在代码里不断挑战上限。5.5 SDK 升级后原有定位代码不工作了现象项目从旧版本腾讯定位 SDK比如 7.x升级到 8.x 之后代码里部分接口报编译错误或者运行时行为异常原先正常的定位回调不再触发。原因SDK 大版本升级包含 API 兼容性改动部分旧接口被标记为废弃或调整了调用线程规则。最典型的是TencentLocationManager.requestLocationUpdates这个方法的签名在后续版本里增加了参数或者必须要求传入一个TencentLocationRequest对象而不是一个空集合初始化setAppKey的位置也可能变了。旧代码没有跟着变导致行为错误。解决升级时仔细看 SDK 的 release notes 和 breaking changes不要只换依赖包版本而忽略 API 变更。升级前后用同一台真机做对比测试重点看初始化、权限回调和连续定位三个环节。如果升级后问题排查困难官方技术支持渠道或看门狗日志都是可用的排查入口但我们一般先自己看setAppKey和requestLocationUpdates这两个最容易被改的方法签名的编译错误信息——通常错误提示足够明确。6. 定位结果可用性验证用 accuracy 做过滤用轨迹平滑做可视化的进阶技巧定位不止是拿坐标还要关心坐标什么时候用、怎么用。最后一章放到验证方法和一个很实用的小技巧上。getAccuracy()返回的是一个近似估计的精度半径单位米含义就是真实位置在这个半径为圆心的圆内的概率大约在 68% 左右。这个值有几个典型用法。第一个是过滤在轨迹记录场景把 acc 50 的点直接丢弃或标记为低质量在做位置签到场景acc 200 可以判定为不可信引导用户重新定位。第二个是业务依据两个定位点之间距离计算出来只有 10 米但如果 acc 是 100 米这个 10 米的位移毫无意义不能作为用户动了的依据。第二个进阶技巧是轨迹平滑。原始定位点天生带抖动静止时坐标也会小幅浮动。直接在业务里消费原始轨迹会出问题路径看起来是锯齿状的、总距离被高估、速度计算忽高忽低。简单的做法是加一个卡尔曼滤波器或者更朴素的滑动窗口平均。我之前在一个模拟项目X里用的是窗口为 5 个定位点的加权移动平均每个点的权重根据自己的 accuracy 反比确定——acc 越小权重越大。效果是路径自然被拉直抖动量明显下降同时没有引入明显的延迟窗口只有 5 个点2 秒回一次大约是 10 秒延迟对大多数业务可接受。// 按 accuracy 加权的滑动窗口平均示例 private final ArrayDequeTencentLocation window new ArrayDeque(); private static final int WINDOW_SIZE 5; public TencentLocation smooth(TencentLocation newLoc) { window.addLast(newLoc); while (window.size() WINDOW_SIZE) { window.removeFirst(); } double totalWeight 0; double latSum 0; double lngSum 0; for (TencentLocation loc : window) { double w 1.0 / Math.max(loc.getAccuracy(), 1.0); latSum loc.getLatitude() * w; lngSum loc.getLongitude() * w; totalWeight w; } // 用新的平均位置更新到返回的坐标中示意实际业务可能复制一个对象 TencentLocation result window.getLast(); result.setLatitude(latSum / totalWeight); result.setLongitude(lngSum / totalWeight); return result; }最后建议做一个你自己的验收清单在一个真实城市环境中分别在写字楼、室外开阔地、高架桥下三个位置连续定位 10 次记录每次的 latency 和 accuracy如果室外 median latency 超过 5 秒或 median accuracy 超过 30 米多半不是 SDK 的问题而是你的环境问题——比如机器开了省电模式、系统对定位权限有额外限制。做定位功能别只看能不能拿到坐标要把 accuracy 分布当成产品质量指标来验收。这是我看过太多团队在定位功能上翻车后的血泪经验希望帮到你。本文还有配套的精品资源点击获取