diff --git a/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java b/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java index 4473abb..371b3d7 100644 --- a/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java +++ b/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java @@ -9,6 +9,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.location.Location; import android.os.Build; @@ -28,17 +29,21 @@ import java.util.Map; import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.embedding.engine.dart.DartExecutor; +import io.flutter.embedding.engine.dart.DartExecutor.DartCallback; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry.Registrar; +import io.flutter.view.FlutterCallbackInformation; import io.flutter.view.FlutterMain; +import io.flutter.view.FlutterNativeView; +import io.flutter.view.FlutterRunArguments; import io.radar.sdk.Radar; import io.radar.sdk.RadarReceiver; @@ -55,96 +60,38 @@ public class RadarFlutterPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware { + private static final String TAG = "RadarFlutterPlugin"; + private static final String CALLBACK_DISPATCHER_HANDLE_KEY = "callbackDispatcherHandle"; + + private static final Object lock = new Object(); private static FlutterEngine sBackgroundFlutterEngine; - private static EventChannel sEventsChannel; - private static EventChannel.EventSink sEventsSink; - private static EventChannel sLocationChannel; - private static EventChannel.EventSink sLocationSink; - private static EventChannel sClientLocationChannel; - private static EventChannel.EventSink sClientLocationSink; - private static EventChannel sErrorChannel; - private static EventChannel.EventSink sErrorSink; - private static EventChannel sLogChannel; - private static EventChannel.EventSink sLogSink; + private static MethodChannel sBackgroundChannel; private Activity mActivity; private Context mContext; private static void initializeBackgroundEngine(Context context) { - FlutterMain.startInitialization(context.getApplicationContext()); - FlutterMain.ensureInitializationComplete(context.getApplicationContext(), null); - - if (sBackgroundFlutterEngine == null) { - sBackgroundFlutterEngine = new FlutterEngine(context); - initializeEventChannels(sBackgroundFlutterEngine.getDartExecutor()); - } - } - - private static void initializeEventChannels(BinaryMessenger messenger) { - sEventsChannel = new EventChannel(messenger, "flutter_radar/events"); - sEventsChannel.setStreamHandler(new EventChannel.StreamHandler() { - @Override - public void onListen(Object listener, EventChannel.EventSink eventSink) { - sEventsSink = eventSink; - } - - @Override - public void onCancel(Object listener) { - sEventsSink = null; - } - }); - - sLocationChannel = new EventChannel(messenger, "flutter_radar/location"); - sLocationChannel.setStreamHandler(new EventChannel.StreamHandler() { - @Override - public void onListen(Object listener, EventChannel.EventSink eventSink) { - sLocationSink = eventSink; - } - - @Override - public void onCancel(Object listener) { - sLocationSink = null; - } - }); - - sClientLocationChannel = new EventChannel(messenger, "flutter_radar/clientLocation"); - sClientLocationChannel.setStreamHandler(new EventChannel.StreamHandler() { - @Override - public void onListen(Object listener, EventChannel.EventSink eventSink) { - sClientLocationSink = eventSink; - } - - @Override - public void onCancel(Object listener) { - sClientLocationSink = null; - } - }); - - sErrorChannel = new EventChannel(messenger, "flutter_radar/error"); - sErrorChannel.setStreamHandler(new EventChannel.StreamHandler() { - @Override - public void onListen(Object listener, EventChannel.EventSink eventSink) { - sErrorSink = eventSink; - } + synchronized(lock) { + if (sBackgroundFlutterEngine == null) { + FlutterMain.startInitialization(context.getApplicationContext()); + FlutterMain.ensureInitializationComplete(context.getApplicationContext(), null); + + SharedPreferences sharedPrefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); + long callbackDispatcherHandle = sharedPrefs.getLong(CALLBACK_DISPATCHER_HANDLE_KEY, 0); + if (callbackDispatcherHandle == 0) { + Log.e(TAG, "Error looking up callback dispatcher handle"); + return; + } - @Override - public void onCancel(Object listener) { - sErrorSink = null; - } - }); + FlutterCallbackInformation callbackInfo = FlutterCallbackInformation.lookupCallbackInformation(callbackDispatcherHandle); + sBackgroundFlutterEngine = new FlutterEngine(context.getApplicationContext()); - sLogChannel = new EventChannel(messenger, "flutter_radar/log"); - sLogChannel.setStreamHandler(new EventChannel.StreamHandler() { - @Override - public void onListen(Object listener, EventChannel.EventSink eventSink) { - sLogSink = eventSink; - } + DartCallback callback = new DartCallback(context.getAssets(), FlutterMain.findAppBundlePath(context), callbackInfo); + sBackgroundFlutterEngine.getDartExecutor().executeDartCallback(callback); - @Override - public void onCancel(Object listener) { - sLogSink = null; + sBackgroundChannel = new MethodChannel(sBackgroundFlutterEngine.getDartExecutor().getBinaryMessenger(), "flutter_radar_background"); } - }); + } } @Override @@ -152,7 +99,6 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { mContext = binding.getApplicationContext(); MethodChannel channel = new MethodChannel(binding.getFlutterEngine().getDartExecutor(), "flutter_radar"); channel.setMethodCallHandler(this); - initializeEventChannels(binding.getFlutterEngine().getDartExecutor()); } @Override @@ -187,11 +133,9 @@ public static void registerWith(Registrar registrar) { channel.setMethodCallHandler(plugin); plugin.mContext = registrar.context(); plugin.mActivity = registrar.activity(); - - initializeEventChannels(registrar.messenger()); } - private void runOnMainThread(final Runnable runnable) { + private static void runOnMainThread(final Runnable runnable) { Handler handler = new Handler(Looper.getMainLooper()); handler.post(runnable); } @@ -296,6 +240,18 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) case "stopForegroundService": stopForegroundService(call, result); break; + case "attachListeners": + attachListeners(call, result); + break; + case "detachListeners": + detachListeners(call, result); + break; + case "on": + on(call, result); + break; + case "off": + off(call, result); + break; default: result.notImplemented(); break; @@ -331,6 +287,11 @@ private void setLogLevel(MethodCall call, Result result) { private void getPermissionStatus(Result result) { + if (mActivity == null) { + result.success("UNKNOWN"); + return; + } + boolean foreground = ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; if (Build.VERSION.SDK_INT >= 29) { if (foreground) { @@ -345,6 +306,10 @@ private void getPermissionStatus(Result result) { } private void requestPermissions(MethodCall call, Result result) { + if (mActivity == null) { + return; + } + boolean background = call.argument("background"); if (mActivity != null) { if (Build.VERSION.SDK_INT >= 23) { @@ -414,7 +379,7 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { + } catch (Exception e) { result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } @@ -458,7 +423,7 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { + } catch (Exception e) { result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } @@ -577,7 +542,7 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { + } catch (Exception e) { result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } @@ -613,7 +578,7 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { + } catch (Exception e) { result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } @@ -659,7 +624,7 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { + } catch (Exception e) { result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } @@ -709,7 +674,7 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { + } catch (Exception e) { result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } @@ -736,7 +701,7 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { + } catch (Exception e) { result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } @@ -761,8 +726,8 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { - result.error("geocode", "An unexpected error happened during the reverse geocode callback logic: " + e.getMessage(), null); + } catch (Exception e) { + result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } }); @@ -795,7 +760,7 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { + } catch (Exception e) { result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } @@ -820,8 +785,8 @@ public void run() { HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); - } catch (JSONException e) { - result.error("geocode", "An unexpected error happened during the ip geocode callback logic: " + e.getMessage(), null); + } catch (Exception e) { + result.error(e.toString(), e.getMessage(), e.getStackTrace()); } } }); @@ -883,7 +848,7 @@ public void startForegroundService(MethodCall call, Result result) { } } - public void stopForegroundService(MethodCall call, Result result) throws JSONException { + public void stopForegroundService(MethodCall call, Result result) { if (mActivity == null) { return; } @@ -896,6 +861,35 @@ public void stopForegroundService(MethodCall call, Result result) throws JSONExc } } + public void attachListeners(MethodCall call, Result result) { + SharedPreferences sharedPrefs = mContext.getSharedPreferences(TAG, Context.MODE_PRIVATE); + long callbackDispatcherHandle = ((Number)call.argument("callbackDispatcherHandle")).longValue(); + sharedPrefs.edit().putLong(CALLBACK_DISPATCHER_HANDLE_KEY, callbackDispatcherHandle).commit(); + result.success(true); + } + + public void detachListeners(MethodCall call, Result result) { + SharedPreferences sharedPrefs = mContext.getSharedPreferences(TAG, Context.MODE_PRIVATE); + long callbackDispatcherHandle = call.argument("callbackDispatcherHandle"); + sharedPrefs.edit().putLong(CALLBACK_DISPATCHER_HANDLE_KEY, 0L).commit(); + result.success(true); + } + + public void on(MethodCall call, Result result) { + SharedPreferences sharedPrefs = mContext.getSharedPreferences(TAG, Context.MODE_PRIVATE); + String listener = call.argument("listener"); + long callbackHandle = ((Number)call.argument("callbackHandle")).longValue(); + sharedPrefs.edit().putLong(listener, callbackHandle).commit(); + result.success(true); + } + + public void off(MethodCall call, Result result) { + SharedPreferences sharedPrefs = mContext.getSharedPreferences(TAG, Context.MODE_PRIVATE); + String listener = call.argument("listener"); + sharedPrefs.edit().putLong(listener, 0L).commit(); + result.success(true); + } + private Location locationForMap(HashMap locationMap) { double latitude = (Double)locationMap.get("latitude"); double longitude = (Double)locationMap.get("longitude"); @@ -918,7 +912,7 @@ private JSONObject jsonForMap(HashMap map) throws JSONException { Object value = map.get(keyStr); obj.put(keyStr, value); } - } catch (JSONException e) { + } catch (Exception e) { Log.e("RadarFlutterPlugin", e.toString()); } return obj; @@ -928,88 +922,163 @@ public static class RadarFlutterReceiver extends RadarReceiver { @Override public void onEventsReceived(Context context, RadarEvent[] events, RadarUser user) { - RadarFlutterPlugin.initializeBackgroundEngine(context); - try { + SharedPreferences sharedPrefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); + long callbackHandle = sharedPrefs.getLong("events", 0L); + + if (callbackHandle == 0L) { + return; + } + + RadarFlutterPlugin.initializeBackgroundEngine(context); + JSONObject obj = new JSONObject(); obj.put("events", RadarEvent.toJson(events)); obj.put("user", user.toJson()); - HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); - if (sEventsSink != null) { - sEventsSink.success(map); + HashMap res = new Gson().fromJson(obj.toString(), HashMap.class); + synchronized(lock) { + final ArrayList args = new ArrayList(); + args.add(callbackHandle); + args.add(res); + runOnMainThread(new Runnable() { + @Override + public void run() { + sBackgroundChannel.invokeMethod("", args); + } + }); } - } catch (JSONException e) { + } catch (Exception e) { Log.e("RadarFlutterPlugin", e.toString()); } } @Override public void onLocationUpdated(Context context, Location location, RadarUser user) { - RadarFlutterPlugin.initializeBackgroundEngine(context); - try { + SharedPreferences sharedPrefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); + long callbackHandle = sharedPrefs.getLong("location", 0L); + + if (callbackHandle == 0L) { + return; + } + + RadarFlutterPlugin.initializeBackgroundEngine(context); + JSONObject obj = new JSONObject(); obj.put("location", Radar.jsonForLocation(location)); obj.put("user", user.toJson()); - HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); - if (sLocationSink != null) { - sLocationSink.success(map); + HashMap res = new Gson().fromJson(obj.toString(), HashMap.class); + synchronized(lock) { + final ArrayList args = new ArrayList(); + args.add(callbackHandle); + args.add(res); + runOnMainThread(new Runnable() { + @Override + public void run() { + sBackgroundChannel.invokeMethod("", args); + } + }); } - } catch (JSONException e) { + } catch (Exception e) { Log.e("RadarFlutterPlugin", e.toString()); } } public void onClientLocationUpdated(Context context, Location location, boolean stopped, Radar.RadarLocationSource source) { - RadarFlutterPlugin.initializeBackgroundEngine(context); - try { + SharedPreferences sharedPrefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); + long callbackHandle = sharedPrefs.getLong("clientLocation", 0L); + + if (callbackHandle == 0L) { + return; + } + + RadarFlutterPlugin.initializeBackgroundEngine(context); + JSONObject obj = new JSONObject(); obj.put("location", Radar.jsonForLocation(location)); obj.put("stopped", stopped); obj.put("source", source.toString()); - HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); - if (sClientLocationSink != null) { - sClientLocationSink.success(map); + HashMap res = new Gson().fromJson(obj.toString(), HashMap.class); + synchronized(lock) { + final ArrayList args = new ArrayList(); + args.add(callbackHandle); + args.add(res); + runOnMainThread(new Runnable() { + @Override + public void run() { + sBackgroundChannel.invokeMethod("", args); + } + }); } - } catch (JSONException e) { + } catch (Exception e) { Log.e("RadarFlutterPlugin", e.toString()); } } @Override public void onError(Context context, Radar.RadarStatus status) { - RadarFlutterPlugin.initializeBackgroundEngine(context); - try { + SharedPreferences sharedPrefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); + long callbackHandle = sharedPrefs.getLong("error", 0L); + + if (callbackHandle == 0L) { + return; + } + + RadarFlutterPlugin.initializeBackgroundEngine(context); + JSONObject obj = new JSONObject(); obj.put("status", status.toString()); - HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); - if (sErrorSink != null) { - sErrorSink.success(map); + HashMap res = new Gson().fromJson(obj.toString(), HashMap.class); + synchronized(lock) { + final ArrayList args = new ArrayList(); + args.add(callbackHandle); + args.add(res); + runOnMainThread(new Runnable() { + @Override + public void run() { + sBackgroundChannel.invokeMethod("", args); + } + }); } - } catch (JSONException e) { + } catch (Exception e) { Log.e("RadarFlutterPlugin", e.toString()); } } @Override public void onLog(Context context, String message) { - RadarFlutterPlugin.initializeBackgroundEngine(context); - try { + SharedPreferences sharedPrefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); + long callbackHandle = sharedPrefs.getLong("log", 0L); + + if (callbackHandle == 0L) { + return; + } + + RadarFlutterPlugin.initializeBackgroundEngine(context); + JSONObject obj = new JSONObject(); obj.put("message", message); - HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); - if (sLogSink != null) { - sLogSink.success(map); + HashMap res = new Gson().fromJson(obj.toString(), HashMap.class); + synchronized(lock) { + final ArrayList args = new ArrayList(); + args.add(callbackHandle); + args.add(res); + runOnMainThread(new Runnable() { + @Override + public void run() { + sBackgroundChannel.invokeMethod("", args); + } + }); } - } catch (JSONException e) { + } catch (Exception e) { Log.e("RadarFlutterPlugin", e.toString()); } } diff --git a/example/android/app/src/main/java/io/radar/example/MainApplication.java b/example/android/app/src/main/java/io/radar/example/MainApplication.java index 8e050de..7ca9591 100644 --- a/example/android/app/src/main/java/io/radar/example/MainApplication.java +++ b/example/android/app/src/main/java/io/radar/example/MainApplication.java @@ -9,7 +9,7 @@ public class MainApplication extends FlutterApplication { @Override public void onCreate() { super.onCreate(); - Radar.initialize(this, "prj_test_pk_0000000000000000000000000000000000000000"); + Radar.initialize(this, "org_test_pk_5857c63d9c1565175db8b00750808a66a002acb8"); FlutterMain.startInitialization(this); } diff --git a/example/ios/Runner/AppDelegate.m b/example/ios/Runner/AppDelegate.m index 594aa98..220d34f 100644 --- a/example/ios/Runner/AppDelegate.m +++ b/example/ios/Runner/AppDelegate.m @@ -1,6 +1,7 @@ +#import + #import "AppDelegate.h" #import "GeneratedPluginRegistrant.h" -#import @implementation AppDelegate diff --git a/example/lib/main.dart b/example/lib/main.dart index 0c42866..8fc7fea 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -2,7 +2,10 @@ import 'package:flutter/material.dart'; import 'dart:async'; import 'package:flutter_radar/flutter_radar.dart'; -void main() => runApp(MyApp()); +void main() { + WidgetsFlutterBinding.ensureInitialized(); + runApp(MyApp()); +} class MyApp extends StatefulWidget { @override @@ -16,27 +19,38 @@ class _MyAppState extends State { initRadar(); } + static void onEvents(Map res) { + print('📍 onEvents: $res'); + } + + static void onLocation(Map res) { + print('📍 onLocation: $res'); + } + + static void onClientLocation(Map res) { + print('📍 onClientLocation: $res'); + } + + static void onError(Map res) { + print('📍 onError: $res'); + } + + static void onLog(Map res) { + print('📍 onLog: $res'); + } + Future initRadar() async { Radar.setLogLevel('info'); Radar.setUserId('flutter'); Radar.setDescription('Flutter'); Radar.setMetadata({'foo': 'bar', 'bax': true, 'qux': 1}); - Radar.onEvents((result) { - print('onEvents: $result'); - }); - Radar.onLocation((result) { - print('onLocation: $result'); - }); - Radar.onClientLocation((result) { - print('onClientLocation: $result'); - }); - Radar.onError((result) { - print('onError: $result'); - }); - Radar.onLog((result) { - print('onLog: $result'); - }); + Radar.attachListeners(); + Radar.onEvents(onEvents); + Radar.onLocation(onLocation); + Radar.onClientLocation(onClientLocation); + Radar.onError(onError); + Radar.onLog(onLog); } @override diff --git a/lib/flutter_radar.dart b/lib/flutter_radar.dart index a82cee6..51ed9a7 100644 --- a/lib/flutter_radar.dart +++ b/lib/flutter_radar.dart @@ -1,26 +1,30 @@ import 'dart:async'; +import 'dart:ui'; +import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +void callbackDispatcher() { + const MethodChannel _backgroundChannel = + MethodChannel('flutter_radar_background'); + + WidgetsFlutterBinding.ensureInitialized(); + + _backgroundChannel.setMethodCallHandler((MethodCall call) async { + final args = call.arguments; + + final Function callback = PluginUtilities.getCallbackFromHandle( + CallbackHandle.fromRawHandle(args[0])); + assert(callback != null); + + final Map res = args[1].cast(); + + callback(res); + }); +} + class Radar { static const MethodChannel _channel = const MethodChannel('flutter_radar'); - static const EventChannel _eventsChannel = - const EventChannel('flutter_radar/events'); - static const EventChannel _locationChannel = - const EventChannel('flutter_radar/location'); - static const EventChannel _clientLocationChannel = - const EventChannel('flutter_radar/clientLocation'); - static const EventChannel _errorChannel = - const EventChannel('flutter_radar/error'); - static const EventChannel _logChannel = - const EventChannel('flutter_radar/log'); - - static Function(Map res) _eventsCallback; - static Function(Map res) _locationCallback; - static Function(Map res) _clientLocationCallback; - static Function(Map res) _errorCallback; - static Function(Map res) _logCallback; - static Future initialize(String publishableKey) async { try { await _channel.invokeMethod('initialize', { @@ -358,68 +362,122 @@ class Radar { } } - static onEvents(Function(Map result) callback) { - _eventsCallback = callback; - _eventsChannel.receiveBroadcastStream().listen((data) { - if (_eventsCallback != null) { - _eventsCallback(data); - } - }); + static attachListeners() async { + try { + await _channel.invokeMethod('attachListeners', { + 'callbackDispatcherHandle': + PluginUtilities.getCallbackHandle(callbackDispatcher).toRawHandle() + }); + } on PlatformException catch (e) { + print(e); + } } - static offEvents() { - _eventsCallback = null; + static Future detachListeners() async { + try { + await _channel.invokeMethod('detachListeners'); + } on PlatformException catch (e) { + print(e); + } } - static onLocation(Function(Map result) callback) { - _locationCallback = callback; - _locationChannel.receiveBroadcastStream().listen((data) { - if (_locationCallback != null) { - _locationCallback(data); - } - }); + static onEvents(Function(Map res) callback) async { + try { + await _channel.invokeMethod('on', { + 'listener': 'events', + 'callbackHandle': + PluginUtilities.getCallbackHandle(callback).toRawHandle() + }); + } on PlatformException catch (e) { + print(e); + } } - static offLocation() { - _locationCallback = null; + static offEvents() async { + try { + await _channel.invokeMethod('off', {'listener': 'events'}); + } on PlatformException catch (e) { + print(e); + } } - static onClientLocation(Function(Map result) callback) { - _clientLocationCallback = callback; - _clientLocationChannel.receiveBroadcastStream().listen((data) { - if (_clientLocationCallback != null) { - _clientLocationCallback(data); - } - }); + static onLocation(Function(Map res) callback) async { + try { + await _channel.invokeMethod('on', { + 'listener': 'location', + 'callbackHandle': + PluginUtilities.getCallbackHandle(callback).toRawHandle() + }); + } on PlatformException catch (e) { + print(e); + } } - static offClientLocation() { - _clientLocationCallback = null; + static offLocation() async { + try { + await _channel.invokeMethod('off', {'listener': 'location'}); + } on PlatformException catch (e) { + print(e); + } } - static onError(Function(Map result) callback) { - _errorCallback = callback; - _errorChannel.receiveBroadcastStream().listen((data) { - if (_errorCallback != null) { - _errorCallback(data); - } - }); + static onClientLocation(Function(Map res) callback) async { + try { + await _channel.invokeMethod('on', { + 'listener': 'clientLocation', + 'callbackHandle': + PluginUtilities.getCallbackHandle(callback).toRawHandle() + }); + } on PlatformException catch (e) { + print(e); + } } - static offError() { - _errorCallback = null; + static offClientLocation() async { + try { + await _channel.invokeMethod('off', {'listener': 'clientLocation'}); + } on PlatformException catch (e) { + print(e); + } } - static onLog(Function(Map result) callback) { - _logCallback = callback; - _logChannel.receiveBroadcastStream().listen((data) { - if (_logCallback != null) { - _logCallback(data); - } - }); + static onError(Function(Map res) callback) async { + try { + await _channel.invokeMethod('on', { + 'listener': 'error', + 'callbackHandle': + PluginUtilities.getCallbackHandle(callback).toRawHandle() + }); + } on PlatformException catch (e) { + print(e); + } } - static offLog() { - _logCallback = null; + static offError() async { + try { + await _channel.invokeMethod('off', {'listener': 'error'}); + } on PlatformException catch (e) { + print(e); + } + } + + static onLog(Function(Map res) callback) async { + try { + await _channel.invokeMethod('on', { + 'listener': 'log', + 'callbackHandle': + PluginUtilities.getCallbackHandle(callback).toRawHandle() + }); + } on PlatformException catch (e) { + print(e); + } + } + + static offLog() async { + try { + await _channel.invokeMethod('off', {'listener': 'log'}); + } on PlatformException catch (e) { + print(e); + } } }