Browse Source

上传定位优化逻辑

newdev_shunjiawei
liwei1dao 1 year ago
parent
commit
4ab2da85cb
  1. 1
      local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt
  2. 2
      local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift
  3. 273
      local_plugins/location_service/ios/location_service/Sources/location_service/LocationService.swift
  4. 2
      pubspec.yaml

1
local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt

@ -1181,6 +1181,7 @@ private class GetCurrentLocationHandler(private val context: Context?) : Functio
put("latitude", cachedLocation.latitude)
put("longitude", cachedLocation.longitude)
put("address", cachedLocation.address)
put("location", "${cachedLocation.latitude},${cachedLocation.longitude}")
put("source", "cache")
put("timestamp", cachedLocation.timestamp)
put("cacheAgeMinutes", cacheAgeMinutes)

2
local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift

@ -461,6 +461,7 @@ private class GetCurrentLocationHandler: FunctionHandler {
// 解析位置数据
guard let latStr = locationInfo["user_lat"] as? String,
let lngStr = locationInfo["user_lng"] as? String,
let latitude = Double(latStr),
let longitude = Double(lngStr) else {
print("[GetCurrentLocationHandler] 位置数据格式错误")
@ -491,6 +492,7 @@ private class GetCurrentLocationHandler: FunctionHandler {
"data": [
"latitude": latitude,
"longitude": longitude,
"location": "\(latitude),\(longitude)",
"timestamp": Date().timeIntervalSince1970 * 1000
]
]

273
local_plugins/location_service/ios/location_service/Sources/location_service/LocationService.swift

@ -23,37 +23,33 @@ public class LocationService: NSObject {
private var authorizationStatus: CLAuthorizationStatus = .notDetermined
private var isLocationServicesEnabled: Bool = false
// 高精度定位属性
private var locationAttempts: Int = 0
private let maxLocationAttempts: Int = 3
private let requiredAccuracy: CLLocationAccuracy = 10.0 // 要求精度在10米以内
private var bestLocation: CLLocation?
private var locationTimer: Timer?
// MARK: - 权限回调
private var permissionCallback: ((Result<Bool, Error>) -> Void)?
private override init() {
super.init()
setupLocationManager()
}
private func setupLocationManager() {
DispatchQueue.main.async { [weak self] in
self?.locationManager = CLLocationManager()
self?.locationManager?.delegate = self
self?.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
self?.locationManager?.distanceFilter = 10
// 不需要手动获取状态,delegate 方法会自动被调用
// 高精度定位设置
self?.locationManager?.desiredAccuracy = kCLLocationAccuracyBestForNavigation // 最高精度
self?.locationManager?.distanceFilter = 1 // 降低距离过滤器,更敏感
print("[LocationService] LocationManager 初始化完成,等待权限状态回调")
}
}
// private func setupLocationManager() {
// DispatchQueue.main.async { [weak self] in
// self?.locationManager = CLLocationManager()
// self?.locationManager?.delegate = self
// self?.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
// self?.locationManager?.distanceFilter = 10
// // 初始化时获取当前状态
// self?.authorizationStatus = CLLocationManager.authorizationStatus()
// self?.isLocationServicesEnabled = CLLocationManager.locationServicesEnabled()
// print("[LocationService] LocationManager 初始化完成")
// print("[LocationService] 初始权限状态: \(self?.authorizationStatus.rawValue ?? -1)")
// print("[LocationService] 位置服务启用: \(self?.isLocationServicesEnabled ?? false)")
// }
// }
/// 获取当前位置 - 主要接口
public func getCurrentLocation(completion: @escaping (Result<[String: Any], Error>) -> Void) {
@ -98,20 +94,14 @@ public class LocationService: NSObject {
/// 异步更新位置缓存
private func asyncUpdateLocation() {
// 检查权限
guard checkLocationPermission() else {
print("[LocationService] 异步更新失败:无位置权限")
return
}
// 异步请求位置更新
DispatchQueue.global(qos: .background).async { [weak self] in
self?.requestLocationUpdate { result in
if checkLocationPermission() {
requestHighAccuracyLocation { [weak self] result in
switch result {
case .success(let locationData):
print("[LocationService] 异步更新位置缓存成功")
self?.cachedLocationData = locationData
print("[LocationService] 异步更新缓存成功")
case .failure(let error):
print("[LocationService] 异步更新位置缓存失败: \(error.localizedDescription)")
print("[LocationService] 异步更新缓存失败: \(error.localizedDescription)")
}
}
}
@ -119,14 +109,22 @@ public class LocationService: NSObject {
/// 同步获取位置
private func syncGetLocation(completion: @escaping (Result<[String: Any], Error>) -> Void) {
// 检查权限
guard checkLocationPermission() else {
print("[LocationService] 无位置权限,尝试请求权限")
if checkLocationPermission() {
requestHighAccuracyLocation { [weak self] result in
switch result {
case .success(let locationData):
self?.cachedLocationData = locationData
let locationInfo = self?.formatLocationData(locationData) ?? [:]
completion(.success(locationInfo))
case .failure(let error):
completion(.failure(error))
}
}
} else {
requestLocationPermission { [weak self] result in
switch result {
case .success(let granted):
if granted {
print("[LocationService] 权限获取成功,重新获取位置")
self?.syncGetLocation(completion: completion)
} else {
completion(.failure(NSError(domain: "LocationService", code: -1, userInfo: [NSLocalizedDescriptionKey: "位置权限被拒绝"])))
@ -135,116 +133,76 @@ public class LocationService: NSObject {
completion(.failure(error))
}
}
return
}
// 有权限,直接获取位置
requestLocationUpdate { [weak self] result in
switch result {
case .success(let locationData):
print("[LocationService] 同步获取位置成功")
self?.cachedLocationData = locationData
let locationInfo = self?.formatLocationData(locationData) ?? [:]
completion(.success(locationInfo))
case .failure(let error):
print("[LocationService] 同步获取位置失败: \(error.localizedDescription)")
completion(.failure(error))
}
}
}
/// 检查位置权限 - 使用缓存的状态
/// 检查位置权限
private func checkLocationPermission() -> Bool {
return authorizationStatus == .authorizedWhenInUse || authorizationStatus == .authorizedAlways
}
/// 请求位置权限 - 异步处理
/// 请求位置权限
private func requestLocationPermission(completion: @escaping (Result<Bool, Error>) -> Void) {
print("[LocationService] 当前缓存的权限状态: \(authorizationStatus.rawValue)")
switch authorizationStatus {
case .notDetermined:
print("[LocationService] 请求位置权限")
// 保存回调,等待权限结果
permissionCallback = completion
DispatchQueue.main.async { [weak self] in
self?.locationManager?.requestWhenInUseAuthorization()
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
guard let locationManager = self.locationManager else {
completion(.failure(NSError(domain: "LocationService", code: -3, userInfo: [NSLocalizedDescriptionKey: "LocationManager 未初始化"])))
return
}
// 设置权限回调
self.permissionCallback = completion
// 请求权限
switch self.authorizationStatus {
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .denied, .restricted:
completion(.success(false))
case .authorizedWhenInUse, .authorizedAlways:
completion(.success(true))
@unknown default:
completion(.failure(NSError(domain: "LocationService", code: -2, userInfo: [NSLocalizedDescriptionKey: "未知权限状态"])))
}
case .denied, .restricted:
print("[LocationService] 位置权限被拒绝或受限")
completion(.success(false))
case .authorizedWhenInUse, .authorizedAlways:
print("[LocationService] 已有位置权限")
completion(.success(true))
@unknown default:
completion(.failure(NSError(domain: "LocationService", code: -2, userInfo: [NSLocalizedDescriptionKey: "未知权限状态"])))
}
}
/// 请求位置更新 - 优化版本
private func requestLocationUpdate(completion: @escaping (Result<LocationData, Error>) -> Void) {
/// 高精度定位方法
private func requestHighAccuracyLocation(completion: @escaping (Result<LocationData, Error>) -> Void) {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
guard let locationManager = self.locationManager else {
print("[LocationService] 错误:LocationManager 未初始化")
completion(.failure(NSError(domain: "LocationService", code: -3, userInfo: [NSLocalizedDescriptionKey: "LocationManager 未初始化"])))
return
}
// 检查是否已有请求在进行
if self.currentLocationCallback != nil {
print("[LocationService] 错误:位置请求正在进行中,拒绝新请求")
completion(.failure(NSError(domain: "LocationService", code: -4, userInfo: [NSLocalizedDescriptionKey: "位置请求正在进行中"])))
return
}
// 使用缓存的状态信息
// print("[LocationService] 开始位置请求")
// print("[LocationService] 缓存的权限状态: \(self.authorizationStatus.rawValue)")
// print("[LocationService] 缓存的位置服务状态: \(self.isLocationServicesEnabled)")
// print("[LocationService] 当前线程: \(Thread.current)")
// print("[LocationService] 是否主线程: \(Thread.isMainThread)")
// 验证权限状态
// 检查权限
if !self.checkLocationPermission() {
print("[LocationService] 错误:无位置权限")
completion(.failure(NSError(domain: "LocationService", code: -5, userInfo: [NSLocalizedDescriptionKey: "无位置权限"])))
return
}
if !self.isLocationServicesEnabled {
print("[LocationService] 错误:位置服务未启用")
completion(.failure(NSError(domain: "LocationService", code: -6, userInfo: [NSLocalizedDescriptionKey: "位置服务未启用"])))
return
}
// 强制重新设置 delegate
if locationManager.delegate == nil {
print("[LocationService] 警告:Delegate 为空,重新设置")
locationManager.delegate = self
}
// 验证 delegate
if locationManager.delegate === self {
print("[LocationService] Delegate 验证成功")
} else {
print("[LocationService] 错误:Delegate 设置失败")
completion(.failure(NSError(domain: "LocationService", code: -8, userInfo: [NSLocalizedDescriptionKey: "Delegate 设置失败"])))
return
}
// 重置状态
self.locationAttempts = 0
self.bestLocation = nil
// 设置回调
self.currentLocationCallback = { result in
switch result {
case .success(let locationInfo):
print("[LocationService] 位置回调成功,开始解析数据")
if let latStr = locationInfo["user_lat"] as? String,
let lngStr = locationInfo["user_lng"] as? String,
let latitude = Double(latStr),
let longitude = Double(lngStr) {
print("[LocationService] 位置数据解析成功: lat=\(latitude), lng=\(longitude)")
let locationData = LocationData(
latitude: latitude,
longitude: longitude,
@ -252,31 +210,61 @@ public class LocationService: NSObject {
)
completion(.success(locationData))
} else {
print("[LocationService] 错误:位置数据格式错误,原始数据: \(locationInfo)")
completion(.failure(NSError(domain: "LocationService", code: -7, userInfo: [NSLocalizedDescriptionKey: "位置数据格式错误"])))
}
case .failure(let error):
print("[LocationService] 位置回调失败: \(error.localizedDescription)")
completion(.failure(error))
}
}
print("[LocationService] 调用 locationManager.requestLocation()")
locationManager.requestLocation()
print("[LocationService] requestLocation() 调用完成,等待回调")
print("[LocationService] 开始高精度连续定位")
// 开始连续定位
locationManager.startUpdatingLocation()
// 30秒超时机制
DispatchQueue.main.asyncAfter(deadline: .now() + 30) {
if self.currentLocationCallback != nil {
print("[LocationService] 位置请求超时")
// 设置超时定时器(15秒)
self.locationTimer = Timer.scheduledTimer(withTimeInterval: 15.0, repeats: false) { _ in
self.stopLocationUpdates()
if let bestLocation = self.bestLocation {
self.processLocation(bestLocation)
} else {
let callback = self.currentLocationCallback
self.currentLocationCallback = nil
callback?(.failure(NSError(domain: "LocationService", code: -9, userInfo: [NSLocalizedDescriptionKey: "位置请求超时"])))
callback?(.failure(NSError(domain: "LocationService", code: -9, userInfo: [NSLocalizedDescriptionKey: "无法获取满足精度要求的位置"])))
}
}
}
}
/// 停止位置更新
private func stopLocationUpdates() {
locationManager?.stopUpdatingLocation()
locationTimer?.invalidate()
locationTimer = nil
}
/// 处理位置数据
private func processLocation(_ location: CLLocation) {
let locationInfo: [String: Any] = [
"user_lat": String(location.coordinate.latitude),
"user_lng": String(location.coordinate.longitude),
"timestamp": Date().timeIntervalSince1970 * 1000,
"accuracy": location.horizontalAccuracy // 添加精度信息
]
print("[LocationService] 处理最终位置,精度: \(location.horizontalAccuracy)m")
// 更新缓存
cachedLocationData = LocationData(
latitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
timestamp: Date().timeIntervalSince1970 * 1000
)
let callback = currentLocationCallback
currentLocationCallback = nil
callback?(.success(locationInfo))
}
/// 格式化位置数据
private func formatLocationData(_ locationData: LocationData) -> [String: Any] {
return [
@ -285,14 +273,11 @@ public class LocationService: NSObject {
"timestamp": locationData.timestamp
]
}
// MARK: - 权限回调
private var permissionCallback: ((Result<Bool, Error>) -> Void)?
}
// MARK: - CLLocationManagerDelegate
extension LocationService: CLLocationManagerDelegate {
// 替换 didUpdateLocations 方法中的逆地理编码部分
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("[LocationService] didUpdateLocations 被调用,位置数量: \(locations.count)")
@ -301,22 +286,47 @@ extension LocationService: CLLocationManagerDelegate {
return
}
print("[LocationService] 位置更新成功: lat=\(location.coordinate.latitude), lng=\(location.coordinate.longitude)")
print("[LocationService] 位置精度: \(location.horizontalAccuracy)m")
print("[LocationService] 位置更新: lat=\(location.coordinate.latitude), lng=\(location.coordinate.longitude)")
print("[LocationService] 水平精度: \(location.horizontalAccuracy)m, 垂直精度: \(location.verticalAccuracy)m")
print("[LocationService] 位置时间: \(location.timestamp)")
// 直接使用经纬度,不进行逆地理编码
let locationInfo: [String: Any] = [
"user_lat": String(location.coordinate.latitude),
"user_lng": String(location.coordinate.longitude),
"timestamp": Date().timeIntervalSince1970 * 1000
]
// 过滤无效位置
guard location.horizontalAccuracy >= 0 else {
print("[LocationService] 位置精度无效,忽略此次更新")
return
}
print("[LocationService] 准备调用位置回调")
// 调用回调
let callback = currentLocationCallback
currentLocationCallback = nil
callback?(.success(locationInfo))
print("[LocationService] 位置回调已调用")
// 过滤过旧的位置(超过5秒)
let locationAge = -location.timestamp.timeIntervalSinceNow
guard locationAge < 5.0 else {
print("[LocationService] 位置数据过旧(\(locationAge)秒),忽略")
return
}
locationAttempts += 1
// 检查是否满足精度要求
if location.horizontalAccuracy <= requiredAccuracy {
print("[LocationService] 获得高精度位置,精度: \(location.horizontalAccuracy)m")
stopLocationUpdates()
processLocation(location)
return
}
// 保存最佳位置
if bestLocation == nil || location.horizontalAccuracy < bestLocation!.horizontalAccuracy {
bestLocation = location
print("[LocationService] 更新最佳位置,精度: \(location.horizontalAccuracy)m")
}
// 达到最大尝试次数,使用最佳位置
if locationAttempts >= maxLocationAttempts {
print("[LocationService] 达到最大尝试次数,使用最佳位置")
stopLocationUpdates()
if let bestLocation = bestLocation {
processLocation(bestLocation)
}
}
}
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
@ -325,11 +335,10 @@ extension LocationService: CLLocationManagerDelegate {
print("[LocationService] 错误代码: \((error as NSError).code)")
print("[LocationService] 错误域: \((error as NSError).domain)")
stopLocationUpdates()
let callback = currentLocationCallback
currentLocationCallback = nil
print("[LocationService] 准备调用错误回调")
callback?(.failure(error))
print("[LocationService] 错误回调已调用")
}
public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

2
pubspec.yaml

@ -1,7 +1,7 @@
name: voitrans
description: "Voitrans - AI Voice Assistant."
publish_to: "none"
version: 1.0.6+20
version: 1.0.7+20
environment:
sdk: ">=3.3.0 <4.0.0"

Loading…
Cancel
Save