feat: add background gps tracking support
This commit is contained in:
151
miniprogram/engine/sensor/locationController.ts
Normal file
151
miniprogram/engine/sensor/locationController.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
export interface LocationUpdate {
|
||||
latitude: number
|
||||
longitude: number
|
||||
accuracy?: number
|
||||
speed?: number
|
||||
}
|
||||
|
||||
export interface LocationControllerCallbacks {
|
||||
onLocation: (update: LocationUpdate) => void
|
||||
onStatus: (message: string) => void
|
||||
onError: (message: string) => void
|
||||
}
|
||||
|
||||
function hasLocationPermission(settings: WechatMiniprogram.AuthSetting): boolean {
|
||||
const authSettings = settings as Record<string, boolean | undefined>
|
||||
return !!authSettings['scope.userLocation']
|
||||
}
|
||||
|
||||
function hasBackgroundLocationPermission(settings: WechatMiniprogram.AuthSetting): boolean {
|
||||
const authSettings = settings as Record<string, boolean | undefined>
|
||||
return !!authSettings['scope.userLocationBackground']
|
||||
}
|
||||
|
||||
export class LocationController {
|
||||
callbacks: LocationControllerCallbacks
|
||||
listening: boolean
|
||||
boundLocationHandler: ((result: WechatMiniprogram.OnLocationChangeCallbackResult) => void) | null
|
||||
|
||||
constructor(callbacks: LocationControllerCallbacks) {
|
||||
this.callbacks = callbacks
|
||||
this.listening = false
|
||||
this.boundLocationHandler = null
|
||||
}
|
||||
|
||||
start(): void {
|
||||
if (this.listening) {
|
||||
this.callbacks.onStatus('后台持续定位进行中')
|
||||
return
|
||||
}
|
||||
|
||||
wx.getSetting({
|
||||
success: (result) => {
|
||||
const settings = result.authSetting || {}
|
||||
if (hasBackgroundLocationPermission(settings)) {
|
||||
this.startBackgroundLocation()
|
||||
return
|
||||
}
|
||||
|
||||
if (hasLocationPermission(settings)) {
|
||||
this.requestBackgroundPermissionInSettings()
|
||||
return
|
||||
}
|
||||
|
||||
wx.authorize({
|
||||
scope: 'scope.userLocation',
|
||||
success: () => {
|
||||
this.requestBackgroundPermissionInSettings()
|
||||
},
|
||||
fail: () => {
|
||||
this.requestBackgroundPermissionInSettings()
|
||||
},
|
||||
})
|
||||
},
|
||||
fail: (error) => {
|
||||
const message = error && error.errMsg ? error.errMsg : 'getSetting 失败'
|
||||
this.callbacks.onError(`GPS授权检查失败: ${message}`)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
requestBackgroundPermissionInSettings(): void {
|
||||
this.callbacks.onStatus('请在授权面板开启后台定位')
|
||||
wx.openSetting({
|
||||
success: (result) => {
|
||||
const settings = result.authSetting || {}
|
||||
if (hasBackgroundLocationPermission(settings)) {
|
||||
this.startBackgroundLocation()
|
||||
return
|
||||
}
|
||||
|
||||
this.callbacks.onError('GPS启动失败: 未授予后台定位权限')
|
||||
},
|
||||
fail: (error) => {
|
||||
const message = error && error.errMsg ? error.errMsg : 'openSetting 失败'
|
||||
this.callbacks.onError(`GPS启动失败: ${message}`)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
startBackgroundLocation(): void {
|
||||
wx.startLocationUpdateBackground({
|
||||
success: () => {
|
||||
this.bindLocationListener()
|
||||
this.listening = true
|
||||
this.callbacks.onStatus('后台持续定位已启动')
|
||||
},
|
||||
fail: (error) => {
|
||||
const message = error && error.errMsg ? error.errMsg : 'startLocationUpdateBackground 失败'
|
||||
this.callbacks.onError(`GPS启动失败: ${message}`)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
if (!this.listening) {
|
||||
this.callbacks.onStatus('后台持续定位未启动')
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof wx.offLocationChange === 'function' && this.boundLocationHandler) {
|
||||
wx.offLocationChange(this.boundLocationHandler)
|
||||
}
|
||||
this.boundLocationHandler = null
|
||||
|
||||
wx.stopLocationUpdate({
|
||||
complete: () => {
|
||||
this.listening = false
|
||||
this.callbacks.onStatus('后台持续定位已停止')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
if (typeof wx.offLocationChange === 'function' && this.boundLocationHandler) {
|
||||
wx.offLocationChange(this.boundLocationHandler)
|
||||
}
|
||||
this.boundLocationHandler = null
|
||||
|
||||
if (this.listening) {
|
||||
wx.stopLocationUpdate({ complete: () => {} })
|
||||
this.listening = false
|
||||
}
|
||||
}
|
||||
|
||||
bindLocationListener(): void {
|
||||
if (this.boundLocationHandler) {
|
||||
return
|
||||
}
|
||||
|
||||
this.boundLocationHandler = (result) => {
|
||||
this.callbacks.onLocation({
|
||||
latitude: result.latitude,
|
||||
longitude: result.longitude,
|
||||
accuracy: result.accuracy,
|
||||
speed: result.speed,
|
||||
})
|
||||
}
|
||||
|
||||
wx.onLocationChange(this.boundLocationHandler)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user