LocationManager.swift 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. //
  2. // LocationManager.swift
  3. // Pods
  4. //
  5. // Created by Groot on 2025/5/15.
  6. //
  7. import Foundation
  8. import CoreLocation
  9. import Flutter
  10. class LocationManager: NSObject {
  11. static let shared = LocationManager()
  12. private var locationUpdateEventChannel: FlutterEventChannel?
  13. private var locationEventSink: FlutterEventSink?
  14. private let locationManager = CLLocationManager()
  15. #if DEBUG
  16. private let filterDistance: CLLocationDistance = 5
  17. #else
  18. private let filterDistance: CLLocationDistance = 20
  19. #endif
  20. private var lastLocation: CLLocation?
  21. private var lastUpdateTime: Date?
  22. var onLocationUpdate: ((CLLocation) -> Void)?
  23. private override init() {
  24. super.init()
  25. locationManager.delegate = self
  26. setup()
  27. }
  28. func start(withMessenger messenger: FlutterBinaryMessenger) -> Bool {
  29. // permission detect
  30. switch CLLocationManager.authorizationStatus() {
  31. case .authorizedWhenInUse, .authorizedAlways:
  32. locationManager.startUpdatingLocation()
  33. setupMessenger(messenger: messenger)
  34. return true
  35. case .notDetermined:
  36. return false
  37. default:
  38. print("LocationManager: authorizationStatus: \(CLLocationManager.authorizationStatus())")
  39. return false
  40. }
  41. }
  42. func stop() {
  43. locationManager.stopUpdatingLocation()
  44. }
  45. func setupMessenger(messenger: FlutterBinaryMessenger) {
  46. guard locationUpdateEventChannel == nil && locationEventSink == nil else { return }
  47. locationUpdateEventChannel = FlutterEventChannel(name: MapKitConstans.locationUpdateEventChannelName, binaryMessenger: messenger)
  48. locationUpdateEventChannel?.setStreamHandler(self)
  49. }
  50. func setup() {
  51. locationManager.allowsBackgroundLocationUpdates = true
  52. locationManager.pausesLocationUpdatesAutomatically = false
  53. locationManager.desiredAccuracy = kCLLocationAccuracyBest
  54. // locationManager.distanceFilter = filterDistance
  55. locationManager.activityType = .automotiveNavigation
  56. locationManager.showsBackgroundLocationIndicator = false
  57. }
  58. static func getAddress(location: CLLocation) async -> String? {
  59. let geocoder = CLGeocoder()
  60. return await withCheckedContinuation { continuation in
  61. geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
  62. if let error = error {
  63. print("反向地理编码失败: \(error.localizedDescription)")
  64. continuation.resume(returning: nil)
  65. return
  66. }
  67. if let placemark = placemarks?.first {
  68. // 获取完整地址
  69. let address = [
  70. placemark.country,
  71. placemark.administrativeArea,
  72. placemark.locality,
  73. placemark.subLocality,
  74. placemark.thoroughfare,
  75. placemark.subThoroughfare,
  76. placemark.name
  77. ].compactMap { $0 }.joined(separator: "")
  78. continuation.resume(returning: address)
  79. } else {
  80. continuation.resume(returning: nil)
  81. }
  82. }
  83. }
  84. }
  85. }
  86. extension LocationManager: CLLocationManagerDelegate {
  87. func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
  88. guard let location = locations.last, isLocationCanUpdate(location: location) else { return }
  89. onLocationUpdate?(location)
  90. if let eventSink = locationEventSink {
  91. Task {
  92. // 转换GPS坐标系到中国坐标系
  93. let transformedCoordinate = location.coordinate.wgc84ToGCJ02
  94. let atLocation = ATMapLocation.fromLocation(location: location)
  95. atLocation.longitude = transformedCoordinate.longitude
  96. atLocation.latitude = transformedCoordinate.latitude
  97. // 获取地址
  98. atLocation.address = await LocationManager.getAddress(location: location)
  99. let jsonMessage = atLocation.toJson()
  100. print(jsonMessage)
  101. await MainActor.run {
  102. eventSink(jsonMessage)
  103. }
  104. }
  105. }
  106. }
  107. func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
  108. print("LocationManager: didFailWithError: \(error)")
  109. }
  110. func isLocationCanUpdate(location: CLLocation) -> Bool {
  111. if let lastLocation = lastLocation {
  112. let distance = location.distance(from: lastLocation)
  113. let timeInterval = location.timestamp.timeIntervalSince(lastUpdateTime ?? Date())
  114. if distance < filterDistance && timeInterval < 5.0 {
  115. return false
  116. }
  117. }
  118. lastLocation = location
  119. lastUpdateTime = location.timestamp
  120. return true
  121. }
  122. }
  123. extension LocationManager: FlutterStreamHandler {
  124. func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
  125. locationEventSink = events
  126. return nil
  127. }
  128. func onCancel(withArguments arguments: Any?) -> FlutterError? {
  129. locationEventSink = nil
  130. return nil
  131. }
  132. }