【uni-app UTS 插件】三端后台保活定位方案:Android / iOS / 鸿蒙 Next 一套 API 搞定外勤轨迹
·
一、为什么后台定位这么难?
做过外勤、物流、配送、巡检类 App 的开发者,几乎都踩过这些坑:
Android
- 8.0 以后后台限制越来越严,普通定位服务很容易被系统杀掉
- 必须前台服务(FGS)+ 常驻通知,Android 13+ 还要单独申请通知权限
- 各厂商(小米、华为、OPPO、vivo)电池优化、自启动白名单各不相同
- Android 14 还要声明
foregroundServiceType=location
iOS
- 后台定位必须开 Background Modes
location - 「始终允许」权限要分步申请,App Store 审核对用途说明要求很严
- App 挂起后定位回调可能中断,需要额外处理恢复逻辑
鸿蒙 Next
- 权限要写在
module.json5,只写config.json不会进包 - 后台定位需要长时任务(LOCATION 类型),还要定时续期
- 平板 / 2in1 要在主工程和插件两侧分别配置
deviceTypes
自己从零写三端原生代码,周期以周计,还要持续跟进系统策略变化。有没有一套 uni-app 能直接用的方案?
二、keepalive-location:三端统一的 UTS 后台定位插件
keepalive-location 是一个 UTS 原生插件,用一套 JavaScript API 覆盖 Android、iOS、鸿蒙 Next 的后台持续 GPS 定位场景,典型用途包括:
- 外勤巡检轨迹记录
- 物流配送实时位置
- 司机出车路线留痕
- 现场作业任务核验
核心能力一览
| 能力 | 说明 |
|---|---|
| 后台定位启停 | startLocation() / stopLocation() |
| 点位回调 | 经纬度、精度、速度、高度、时间戳、provider |
| 权限内置 | 检测、申请、跳系统设置,无需另装权限插件 |
| 状态监听 | 权限丢失、长时任务过期、服务异常、上报失败等 |
| 本地环缓 | 可配置最大缓存点数,断网不丢点 |
| 可选 HTTPS 上报 | 批量 POST 到业务服务器,不默认上传第三方 |
| 坐标转换 | WGS84 ↔ 高德 GCJ-02 ↔ 百度 BD-09 |
| 统一错误码 | 803xxxx 分段,便于日志与客服排查 |
三、三端分别做了什么?
Android:前台服务 + 唤醒锁 + 厂商白名单
- 内置
TrackForegroundService,适配 Android 8.0–14 - 支持常驻通知、WakeLock
openVendorKeepAliveSettings()深链跳转小米 / 华为荣耀 / OPPO / vivo / 三星常见保活设置页- 正式包务必
initTrack({ enableForegroundService: true })
iOS:Background Modes + Always 分步授权
- 支持 Background Modes
location - Always 权限分步申请,挂起状态持续出点
- readme 附带 App Store 审核文案模板,可直接改写提交
鸿蒙 Next:长时任务自动续期
- 权限声明在
module.json5(含平板tablet、2in1 支持) - 长时任务类型
LOCATION,定时续期,监听取消事件(8031004) ContinuousLocationRequest持续定位,intervalMs最高 60 秒- 普通授权版买家无需改插件源码,主工程配好
harmony-configs即可
四、5 分钟快速接入
1. 安装插件
从 DCloud 插件市场导入 keepalive-location,放入项目 uni_modules/keepalive-location,制作自定义调试基座后运行。
2. 最小代码示例
import {initTrack,requestPermissions,onLocationUpdate,onStatusChange,startLocation,stopLocation,destroy} from '@/uni_modules/keepalive-location'
// 注册回调(全局注册一次即可)
onLocationUpdate((point) => {
console.log('定位点', point.latitude, point.longitude, point.accuracy)
})
onStatusChange((status) => {
console.log('状态变化', status.eventType, status.lastError)
})
// 初始化 → 申请权限 → 开启定位
async function startTrack() {
await initTrack({
notificationTitle: '位置服务运行中',
notificationContent: '正在进行后台定位',
enableForegroundService: true, // Android 正式包必须 true
enableCache: true,
cacheMaxPoints: 2000
})
await requestPermissions()
await startLocation({
distanceFilter: 0, // 0 = 不按位移过滤
desiredAccuracy: 10, // 期望精度(米)
intervalMs: 60000 // 出点间隔,1000–60000ms
})
}
// 停止
async function stopTrack() {
await stopLocation()
destroy()
}
注意:对外初始化方法名为initTrack,不是init——避免 iOS/Swift 保留字导致云打包失败。
3. 封装成 Vue 插件(业务层示例)
很多项目会封一层 Service,统一管理出点间隔、上传队列、前后台切换:
// utils/locationPlugin.js 思路
class LocationService {
async ensureInit() {
return initTrack({
notificationTitle: '定位服务通知',
notificationContent: '正在后台持续定位...',
enableForegroundService: true,
enableCache: true
})
}
async startService({ interval = 60 } = {}) {
await this.ensureInit()
const perm = checkPermissions()
if (!perm.permission.location) await requestPermissions()
await startLocation({
distanceFilter: 0,
desiredAccuracy: 10,
intervalMs: Math.min(Math.max(interval * 1000, 1000), 60000)
})
}
}
五、几个实用特性详解
1. 定时出点策略(三端一致)
系统定位只刷新内存中的最近点;插件内部定时器按 intervalMs 回调:
- 有新 GPS → 用新点
- 无新 GPS → 复用最近点,更新 timestamp
这样即使司机等红灯、人员站立不动,也能按固定间隔产生轨迹点,适合「每分钟上报一次」的业务需求。
2. 坐标转换(系统 WGS84 → 国内地图)
插件返回的是系统原始 WGS84。上传高德/百度前需转换:
import { toGaode, wgs84ToGcj02 } from '@/uni_modules/keepalive-location'
onLocationUpdate((point) => {
const gaode = JSON.parse(wgs84ToGcj02(point.latitude, point.longitude))
// gaode.latitude / gaode.longitude 用于高德地图展示或上报
})
UTS 自定义对象跨 JS 桥可能丢字段,坐标转换结果以 JSON 字符串返回,需 JSON.parse。
3. 可选 HTTPS 批量上报
await initTrack({
enableCache: true,
upload: {
url: 'https://your-api.com/track',
headers: [{ key: 'Authorization', value: 'Bearer xxx' }],
batchSize: 20,
intervalMs: 15000,
includeDeviceId: false
}
})
上报 JSON 格式:
{
"deviceId": "optional",
"platform": "android|ios|harmony",
"points": [
{
"latitude": 0,
"longitude": 0,
"accuracy": 0,
"speed": 0,
"altitude": 0,
"timestamp": 0,
"provider": "gps"
}
]
}
插件不默认向任何第三方服务器上传,只有业务配置了 upload.url 才会 POST。
4. 统一错误码(节选)
| 错误码 | 含义 |
|---|---|
| 8030001 | 未授权定位 |
| 8030002 | 无后台定位 / Always |
| 8031004 | 长时任务取消 |
更多推荐


所有评论(0)