LocationManager.swift 5.6 KB

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