MapAmapGetLocationHandle.swift 5.7 KB

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