1. I have to get location of iOS device, but I am not using flutter packages. I need to get it from swift code and pass it to flutter.
I don't have any experience in swift. I have used the following code yet. Can someone please help.
import UIKit
import Flutter
import CoreLocation
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let testChannel = FlutterMethodChannel(name: "com.example.testFlutter/test",
binaryMessenger: controller.binaryMessenger)
testChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
// This method is invoked on the UI thread.
if call.method == "getLocation"{
self?.getLocation(result: result)
}
else{
result(FlutterMethodNotImplemented)
return
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func getLocation(result: FlutterResult){
var locationManager: CLLocationManager?
locationManager?.requestAlwaysAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager?.startUpdatingLocation()
result("updating location")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation], result: FlutterResult) {
result("testing")
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
result("location = \(locValue.latitude) \(locValue.longitude)")
}
}
2. Code on the Flutter side is
static const platform = MethodChannel('com.example.testFlutter/test');
printMsgFromiOS() async {
try {
final String result = await platform.invokeMethod('getLocation');
print(result);
} on PlatformException catch (e) {
print(e.message);
}
}
@override
void initState() {
// TODO: implement initState
super.initState();
printMsgFromiOS();
}
OUTPUT While running the code, it is error free and im getting the String as an output. The String is "updating location", which is the statement in getLocation() function of Swift code.
PART A - ONE TIME LOCATION
I am providing an answer to my question which gives me one time location from Swift to Flutter using following code. However, I am attempting to find a solution to get updates of the location every time it changes, and I will post that if successful.
(Update - solution for getting location multiple times is available in Part B below).
1. Updated Swift Code as compared to the one in question
import UIKit
import Flutter
import CoreLocation
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let testChannel = FlutterMethodChannel(name: "com.example.testFlutter/test",
binaryMessenger: controller.binaryMessenger)
testChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
// This method is invoked on the UI thread.
if call.method == "getLocation"{
self?.getLocation(result: result)
}
else{
result(FlutterMethodNotImplemented)
return
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func getLocation(result: FlutterResult){
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
if let location = locationManager.location?.coordinate {
let string = "\(location.latitude), \(location.longitude)"
result(string)
} else {
// Handle error
result("Error")
}
}
}
2. Flutter code remains the same as in question
3. OUTPUT
PART B - MULTIPLE TIMES LOCATION
EventChannel is used in the following code to obtain location multiple times from swift. I have attempted to use delete, however, that didn't work and I'm still working on it. For now, I have settled on using a timer.
1. Swift Code
import UIKit
import Flutter
import CoreLocation
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let testChannel = FlutterEventChannel(name: "com.example.testFlutter/test",
binaryMessenger: controller.binaryMessenger)
let swiftTestChannel = SwiftTestChannel()
swiftTestChannel.setup(flutterViewController: controller)
testChannel.setStreamHandler(swiftTestChannel)
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
class SwiftTestChannel: NSObject, FlutterStreamHandler, CLLocationManagerDelegate {
var eventSink: FlutterEventSink?
private let channelName = "mychannel"
func setup(flutterViewController: FlutterViewController) {
let channel = FlutterEventChannel(name: channelName, binaryMessenger: flutterViewController as! FlutterBinaryMessenger)
channel.setStreamHandler(self)
}
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
eventSink = events
let timer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: true) { _ in
// self.eventSink?("My string from Swift")
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
if let location = locationManager.location?.coordinate {
let string = "\(location.latitude), \(location.longitude)"
self.eventSink?(string)
} else {
// Handle error
self.eventSink?("Error")
}
}
// getLocation()
return nil
}
func onCancel(withArguments arguments: Any?) -> FlutterError? {
return nil
}
}
2. Flutter Code
static const platform = EventChannel('com.example.testFlutter/test');
printMsgFromiOS() async {
try {
platform.receiveBroadcastStream().listen((data) {
print(data.toString());
});
} on PlatformException catch (e) {
print(e.message);
}
}
@override
void initState() {
// TODO: implement initState
super.initState();
printMsgFromiOS();
}
3. OUTPUT