LocationManager.swift 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. locationManager.requestWhenInUseAuthorization()
  37. return false
  38. default:
  39. print("LocationManager: authorizationStatus: \(CLLocationManager.authorizationStatus())")
  40. return false
  41. }
  42. }
  43. func stop() {
  44. locationManager.stopUpdatingLocation()
  45. }
  46. func setupMessenger(messenger: FlutterBinaryMessenger) {
  47. guard locationUpdateEventChannel == nil && locationEventSink == nil else { return }
  48. locationUpdateEventChannel = FlutterEventChannel(name: MapKitConstans.locationUpdateEventChannelName, binaryMessenger: messenger)
  49. locationUpdateEventChannel?.setStreamHandler(self)
  50. }
  51. func setup() {
  52. locationManager.allowsBackgroundLocationUpdates = true
  53. locationManager.pausesLocationUpdatesAutomatically = false
  54. locationManager.desiredAccuracy = kCLLocationAccuracyBest
  55. locationManager.distanceFilter = filterDistance
  56. locationManager.activityType = .automotiveNavigation
  57. locationManager.showsBackgroundLocationIndicator = false
  58. }
  59. static func getAddress(location: CLLocation) async -> String? {
  60. let geocoder = CLGeocoder()
  61. return await withCheckedContinuation { continuation in
  62. geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
  63. if let error = error {
  64. print("反向地理编码失败: \(error.localizedDescription)")
  65. continuation.resume(returning: nil)
  66. return
  67. }
  68. if let placemark = placemarks?.first {
  69. // 获取完整地址
  70. let address = [
  71. placemark.country,
  72. placemark.administrativeArea,
  73. placemark.locality,
  74. placemark.subLocality,
  75. placemark.thoroughfare,
  76. placemark.subThoroughfare,
  77. placemark.name
  78. ].compactMap { $0 }.joined(separator: "")
  79. continuation.resume(returning: address)
  80. } else {
  81. continuation.resume(returning: nil)
  82. }
  83. }
  84. }
  85. }
  86. }
  87. extension LocationManager: CLLocationManagerDelegate {
  88. func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
  89. guard let location = locations.last, isLocationCanUpdate(location: location) else { return }
  90. onLocationUpdate?(location)
  91. if let eventSink = locationEventSink {
  92. Task {
  93. // 转换GPS坐标系到中国坐标系
  94. let transformedCoordinate = location.coordinate.wgc84ToGCJ02
  95. let atLocation = ATMapLocation.fromLocation(location: location)
  96. atLocation.longitude = transformedCoordinate.longitude
  97. atLocation.latitude = transformedCoordinate.latitude
  98. // 获取地址
  99. atLocation.address = await LocationManager.getAddress(location: location)
  100. let jsonMessage = atLocation.toJson()
  101. print(jsonMessage)
  102. await MainActor.run {
  103. eventSink(jsonMessage)
  104. }
  105. }
  106. }
  107. }
  108. func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
  109. print("LocationManager: didFailWithError: \(error)")
  110. }
  111. func isLocationCanUpdate(location: CLLocation) -> Bool {
  112. if let lastLocation = lastLocation {
  113. let distance = location.distance(from: lastLocation)
  114. let timeInterval = location.timestamp.timeIntervalSince(lastUpdateTime ?? Date())
  115. if distance < filterDistance && timeInterval < 5.0 {
  116. return false
  117. }
  118. }
  119. lastLocation = location
  120. lastUpdateTime = location.timestamp
  121. return true
  122. }
  123. }
  124. extension LocationManager: FlutterStreamHandler {
  125. func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
  126. locationEventSink = events
  127. return nil
  128. }
  129. func onCancel(withArguments arguments: Any?) -> FlutterError? {
  130. locationEventSink = nil
  131. return nil
  132. }
  133. }