You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.7 KiB
109 lines
3.7 KiB
import CoreLocation
|
|
import Flutter
|
|
import UIKit
|
|
|
|
public class LocationPlugin: NSObject, FlutterPlugin, CLLocationManagerDelegate {
|
|
private let locationManager = CLLocationManager()
|
|
private var pendingResult: FlutterResult?
|
|
|
|
override init() {
|
|
super.init()
|
|
locationManager.delegate = self
|
|
locationManager.desiredAccuracy = kCLLocationAccuracyBest
|
|
}
|
|
|
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
|
let channel = FlutterMethodChannel(name: "location_plugin", binaryMessenger: registrar.messenger())
|
|
let instance = LocationPlugin()
|
|
registrar.addMethodCallDelegate(instance, channel: channel)
|
|
}
|
|
|
|
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
switch call.method {
|
|
case "getPlatformVersion":
|
|
result("iOS " + UIDevice.current.systemVersion)
|
|
case "getCurrentLocation":
|
|
requestCurrentLocation(result: result)
|
|
default:
|
|
result(FlutterMethodNotImplemented)
|
|
}
|
|
}
|
|
|
|
private func requestCurrentLocation(result: @escaping FlutterResult) {
|
|
guard pendingResult == nil else {
|
|
result(FlutterError(code: "LOCATION_IN_PROGRESS", message: "A previous location request is still running.", details: nil))
|
|
return
|
|
}
|
|
guard CLLocationManager.locationServicesEnabled() else {
|
|
result(FlutterError(code: "LOCATION_DISABLED", message: "Location services are turned off.", details: nil))
|
|
return
|
|
}
|
|
|
|
pendingResult = result
|
|
|
|
switch authorizationStatus() {
|
|
case .authorizedAlways, .authorizedWhenInUse:
|
|
locationManager.requestLocation()
|
|
case .notDetermined:
|
|
locationManager.requestWhenInUseAuthorization()
|
|
case .restricted, .denied:
|
|
finishWithError(code: "PERMISSION_DENIED", message: "Location permission denied.")
|
|
@unknown default:
|
|
finishWithError(code: "PERMISSION_UNKNOWN", message: "Unknown authorization status.")
|
|
}
|
|
}
|
|
|
|
private func authorizationStatus() -> CLAuthorizationStatus {
|
|
if #available(iOS 14.0, *) {
|
|
return locationManager.authorizationStatus
|
|
}
|
|
return CLLocationManager.authorizationStatus()
|
|
}
|
|
|
|
private func finishWithLocation(_ location: CLLocation) {
|
|
pendingResult?([
|
|
"latitude": location.coordinate.latitude,
|
|
"longitude": location.coordinate.longitude,
|
|
])
|
|
pendingResult = nil
|
|
}
|
|
|
|
private func finishWithError(code: String, message: String) {
|
|
pendingResult?(FlutterError(code: code, message: message, details: nil))
|
|
pendingResult = nil
|
|
}
|
|
|
|
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
|
guard let latest = locations.last else {
|
|
finishWithError(code: "LOCATION_UNAVAILABLE", message: "Unable to obtain location.")
|
|
return
|
|
}
|
|
finishWithLocation(latest)
|
|
}
|
|
|
|
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
|
|
finishWithError(code: "LOCATION_ERROR", message: error.localizedDescription)
|
|
}
|
|
|
|
public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
|
handleAuthorizationChange(status: manager.authorizationStatus)
|
|
}
|
|
|
|
public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
|
|
handleAuthorizationChange(status: status)
|
|
}
|
|
|
|
private func handleAuthorizationChange(status: CLAuthorizationStatus) {
|
|
guard pendingResult != nil else { return }
|
|
switch status {
|
|
case .authorizedAlways, .authorizedWhenInUse:
|
|
locationManager.requestLocation()
|
|
case .denied, .restricted:
|
|
finishWithError(code: "PERMISSION_DENIED", message: "Location permission denied.")
|
|
case .notDetermined:
|
|
break
|
|
@unknown default:
|
|
finishWithError(code: "PERMISSION_UNKNOWN", message: "Unknown authorization status.")
|
|
}
|
|
}
|
|
}
|