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

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.")
}
}
}