Files
cmr-mini/miniprogram/engine/sensor/locationController.ts

152 lines
4.2 KiB
TypeScript

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)
}
}