diff --git a/CHANGELOG.md b/CHANGELOG.md index c81afbe..c3a6f19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 3.10.0 + +- Bump iOS version from 3.9.14 to 3.15.0 +- Bump Android version from 3.9.8 to 3.15.0 + # 3.9.1 - Bump iOS version from 3.9.7 to 3.9.14 diff --git a/android/build.gradle b/android/build.gradle index 11eef99..77e9a78 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -34,7 +34,7 @@ android { } dependencies { - implementation 'io.radar:sdk:3.9.8' + implementation 'io.radar:sdk:3.15.0' implementation 'com.google.android.gms:play-services-location:21.0.1' implementation 'com.google.code.gson:gson:2.8.6' } diff --git a/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java b/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java index 0ab9c9f..931be70 100644 --- a/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java +++ b/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java @@ -58,6 +58,7 @@ import io.radar.sdk.model.RadarTrip; import io.radar.sdk.model.RadarRouteMatrix; import io.radar.sdk.RadarTrackingOptions.RadarTrackingOptionsForegroundService; +import io.radar.sdk.model.RadarVerifiedLocationToken; import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.dart.DartExecutor.DartCallback; @@ -66,51 +67,27 @@ import io.flutter.view.FlutterRunArguments; import io.flutter.view.FlutterCallbackInformation; -public class RadarFlutterPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware, RequestPermissionsResultListener { +public class RadarFlutterPlugin implements FlutterPlugin, ActivityAware, RequestPermissionsResultListener { - private static FlutterEngine sBackgroundFlutterEngine; - - private Activity mActivity; - private Context mContext; + private static Activity mActivity; + private static Context mContext; private static final String TAG = "RadarFlutterPlugin"; private static final String CALLBACK_DISPATCHER_HANDLE_KEY = "callbackDispatcherHandle"; - private static MethodChannel sBackgroundChannel; + private static MethodChannel channel; + private static RadarMethodCallHandler callHandler; private static final Object lock = new Object(); private static final int PERMISSIONS_REQUEST_CODE = 20160525; - private Result mPermissionsRequestResult; - - private static void initializeBackgroundEngine(Context context) { - 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; - } - - FlutterCallbackInformation callbackInfo = FlutterCallbackInformation.lookupCallbackInformation(callbackDispatcherHandle); - sBackgroundFlutterEngine = new FlutterEngine(context.getApplicationContext()); - - DartCallback callback = new DartCallback(context.getAssets(), FlutterMain.findAppBundlePath(context), callbackInfo); - sBackgroundFlutterEngine.getDartExecutor().executeDartCallback(callback); - sBackgroundChannel = new MethodChannel(sBackgroundFlutterEngine.getDartExecutor().getBinaryMessenger(), "flutter_radar_background"); - } - } - } + private static Result mPermissionsRequestResult; @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - Radar.setReceiver(new RadarFlutterReceiver()); mContext = binding.getApplicationContext(); - MethodChannel channel = new MethodChannel(binding.getFlutterEngine().getDartExecutor(), "flutter_radar"); - channel.setMethodCallHandler(this); + channel = new MethodChannel(binding.getBinaryMessenger(), "flutter_radar"); + callHandler = new RadarMethodCallHandler(); + channel.setMethodCallHandler(callHandler); } @Override @@ -141,12 +118,12 @@ public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding } public static void registerWith(Registrar registrar) { - RadarFlutterPlugin plugin = new RadarFlutterPlugin(); - - MethodChannel channel = new MethodChannel(registrar.messenger(), "radar_flutter_plugin"); - channel.setMethodCallHandler(plugin); - plugin.mContext = registrar.context(); - plugin.mActivity = registrar.activity(); + mContext = registrar.context(); + mActivity = registrar.activity(); + + channel = new MethodChannel(registrar.messenger(), "flutter_radar"); + callHandler = new RadarMethodCallHandler(); + channel.setMethodCallHandler(callHandler); } private static void runOnMainThread(final Runnable runnable) { @@ -163,174 +140,166 @@ public boolean onRequestPermissionsResult(int requestCode, String[] permissions, return true; } - @Override - public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) { - try { - switch (call.method) { - case "initialize": - initialize(call, result); - break; - case "setLogLevel": - setLogLevel(call, result); - break; - case "getPermissionsStatus": - getPermissionStatus(result); - break; - case "requestPermissions": - requestPermissions(call, result); - break; - case "setUserId": - setUserId(call, result); - break; - case "getUserId": - getUserId(result); - break; - case "setDescription": - setDescription(call, result); - break; - case "getDescription": - getDescription(result); - break; - case "setMetadata": - setMetadata(call, result); - break; - case "getMetadata": - getMetadata(result); - break; - case "setAnonymousTrackingEnabled": - setAnonymousTrackingEnabled(call, result); - break; - case "getLocation": - getLocation(call, result); - break; - case "trackOnce": - trackOnce(call, result); - break; - case "startTracking": - startTracking(call, result); - break; - case "startTrackingCustom": - startTrackingCustom(call, result); - break; - case "startTrackingVerified": - startTrackingVerified(call, result); - break; - case "stopTracking": - stopTracking(result); - break; - case "isTracking": - isTracking(result); - break; - case "isUsingRemoteTrackingOptions": - isUsingRemoteTrackingOptions(result); - break; - case "getTrackingOptions": - getTrackingOptions(result); - break; - case "mockTracking": - mockTracking(call, result); - break; - case "startTrip": - startTrip(call, result); - break; - case "updateTrip": - updateTrip(call, result); - break; - case "getTripOptions": - getTripOptions(result); - break; - case "completeTrip": - completeTrip(result); - break; - case "cancelTrip": - cancelTrip(result); - break; - case "getContext": - getContext(call, result); - break; - case "searchGeofences": - searchGeofences(call, result); - break; - case "searchPlaces": - searchPlaces(call, result); - break; - case "autocomplete": - autocomplete(call, result); - break; - case "forwardGeocode": - geocode(call, result); - break; - case "reverseGeocode": - reverseGeocode(call, result); - break; - case "ipGeocode": - ipGeocode(call, result); - break; - case "getDistance": - getDistance(call, result); - break; - case "logConversion": - logConversion(call, result); - break; - case "logTermination": - // do nothing - break; - case "logBackgrounding": - logBackgrounding(result); - break; - case "logResigningActive": - logResigningActive(result); - break; - case "getMatrix": - getMatrix(call, result); - break; - case "setNotificationOptions": - setNotificationOptions(call, result); - break; - case "setForegroundServiceOptions": - setForegroundServiceOptions(call, result); - break; - case "trackVerified": - trackVerified(call, result); - break; - case "trackVerifiedToken": - trackVerifiedToken(call, result); - break; - case "validateAddress": - validateAddress(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; + public static class RadarMethodCallHandler implements MethodCallHandler { + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) { + try { + switch (call.method) { + case "initialize": + initialize(call, result); + break; + case "setLogLevel": + setLogLevel(call, result); + break; + case "getPermissionsStatus": + getPermissionStatus(result); + break; + case "requestPermissions": + requestPermissions(call, result); + break; + case "setUserId": + setUserId(call, result); + break; + case "getUserId": + getUserId(result); + break; + case "setDescription": + setDescription(call, result); + break; + case "getDescription": + getDescription(result); + break; + case "setMetadata": + setMetadata(call, result); + break; + case "getMetadata": + getMetadata(result); + break; + case "setAnonymousTrackingEnabled": + setAnonymousTrackingEnabled(call, result); + break; + case "getLocation": + getLocation(call, result); + break; + case "trackOnce": + trackOnce(call, result); + break; + case "startTracking": + startTracking(call, result); + break; + case "startTrackingCustom": + startTrackingCustom(call, result); + break; + case "startTrackingVerified": + startTrackingVerified(call, result); + break; + case "stopTrackingVerified": + stopTrackingVerified(call, result); + break; + case "stopTracking": + stopTracking(result); + break; + case "isTracking": + isTracking(result); + break; + case "isUsingRemoteTrackingOptions": + isUsingRemoteTrackingOptions(result); + break; + case "getTrackingOptions": + getTrackingOptions(result); + break; + case "mockTracking": + mockTracking(call, result); + break; + case "startTrip": + startTrip(call, result); + break; + case "updateTrip": + updateTrip(call, result); + break; + case "getTripOptions": + getTripOptions(result); + break; + case "completeTrip": + completeTrip(result); + break; + case "cancelTrip": + cancelTrip(result); + break; + case "getContext": + getContext(call, result); + break; + case "searchGeofences": + searchGeofences(call, result); + break; + case "searchPlaces": + searchPlaces(call, result); + break; + case "autocomplete": + autocomplete(call, result); + break; + case "forwardGeocode": + geocode(call, result); + break; + case "reverseGeocode": + reverseGeocode(call, result); + break; + case "ipGeocode": + ipGeocode(call, result); + break; + case "getDistance": + getDistance(call, result); + break; + case "logConversion": + logConversion(call, result); + break; + case "logTermination": + // do nothing + break; + case "logBackgrounding": + logBackgrounding(result); + break; + case "logResigningActive": + logResigningActive(result); + break; + case "getMatrix": + getMatrix(call, result); + break; + case "setNotificationOptions": + setNotificationOptions(call, result); + break; + case "setForegroundServiceOptions": + setForegroundServiceOptions(call, result); + break; + case "trackVerified": + trackVerified(call, result); + break; + case "validateAddress": + validateAddress(call, result); + break; + default: + result.notImplemented(); + break; + } + } catch (Error | Exception e) { + result.error(e.toString(), e.getMessage(), e.getMessage()); } - } catch (Error | Exception e) { - result.error(e.toString(), e.getMessage(), e.getMessage()); } } - private void initialize(MethodCall call, Result result) { + private static void initialize(MethodCall call, Result result) { String publishableKey = call.argument("publishableKey"); SharedPreferences.Editor editor = mContext.getSharedPreferences("RadarSDK", Context.MODE_PRIVATE).edit(); editor.putString("x_platform_sdk_type", "Flutter"); - editor.putString("x_platform_sdk_version", "3.9.1"); + editor.putString("x_platform_sdk_version", "3.10.0"); editor.apply(); Radar.initialize(mContext, publishableKey); + Radar.setReceiver(new RadarFlutterReceiver(channel)); + Radar.setVerifiedReceiver(new RadarFlutterVerifiedReceiver(channel)); result.success(true); } - private void setNotificationOptions(MethodCall call, Result result) { + private static void setNotificationOptions(MethodCall call, Result result) { HashMap notificationOptionsMap = (HashMap)call.arguments; JSONObject notificationOptionsJson = new JSONObject(notificationOptionsMap); RadarNotificationOptions options = RadarNotificationOptions.fromJson(notificationOptionsJson); @@ -338,7 +307,7 @@ private void setNotificationOptions(MethodCall call, Result result) { result.success(true); } - private void setForegroundServiceOptions(MethodCall call, Result result) { + private static void setForegroundServiceOptions(MethodCall call, Result result) { HashMap foregroundServiceOptionsMap = (HashMap)call.arguments; JSONObject foregroundServiceOptionsJson = new JSONObject(foregroundServiceOptionsMap); RadarTrackingOptionsForegroundService options = RadarTrackingOptionsForegroundService.fromJson(foregroundServiceOptionsJson); @@ -346,7 +315,7 @@ private void setForegroundServiceOptions(MethodCall call, Result result) { result.success(true); } - private void setLogLevel(MethodCall call, Result result) { + private static void setLogLevel(MethodCall call, Result result) { String logLevel = call.argument("logLevel"); if (logLevel == null) { Radar.setLogLevel(Radar.RadarLogLevel.NONE); @@ -365,7 +334,7 @@ private void setLogLevel(MethodCall call, Result result) { } - private void getPermissionStatus(Result result) { + private static void getPermissionStatus(Result result) { String status = "NOT_DETERMINED"; if (mActivity == null || result == null) { @@ -389,7 +358,7 @@ private void getPermissionStatus(Result result) { result.success(status); } - private void requestPermissions(MethodCall call, Result result) { + private static void requestPermissions(MethodCall call, Result result) { boolean background = call.argument("background"); mPermissionsRequestResult = result; if (mActivity != null) { @@ -403,36 +372,36 @@ private void requestPermissions(MethodCall call, Result result) { } } - private void setUserId(MethodCall call, Result result) { + private static void setUserId(MethodCall call, Result result) { String userId = call.argument("userId"); Radar.setUserId(userId); result.success(true); } - private void getUserId(Result result) { + private static void getUserId(Result result) { String userId = Radar.getUserId(); result.success(userId); } - private void setDescription(MethodCall call, Result result) { + private static void setDescription(MethodCall call, Result result) { String description = call.argument("description"); Radar.setDescription(description); result.success(true); } - private void getDescription(Result result) { + private static void getDescription(Result result) { String description = Radar.getDescription(); result.success(description); } - private void setMetadata(MethodCall call, Result result) { + private static void setMetadata(MethodCall call, Result result) { HashMap metadataMap = (HashMap)call.arguments; JSONObject metadata = new JSONObject(metadataMap); Radar.setMetadata(metadata); result.success(true); } - private void getMetadata(Result result) { + private static void getMetadata(Result result) { JSONObject metadata = Radar.getMetadata(); HashMap metadataMap = null; if (metadata != null) { @@ -441,13 +410,13 @@ private void getMetadata(Result result) { result.success(metadataMap); } - private void setAnonymousTrackingEnabled(MethodCall call, Result result) { + private static void setAnonymousTrackingEnabled(MethodCall call, Result result) { boolean enabled = call.argument("enabled"); Radar.setAnonymousTrackingEnabled(enabled); result.success(true); } - private void getLocation(MethodCall call, final Result result) { + private static void getLocation(MethodCall call, final Result result) { Radar.RadarLocationCallback callback = new Radar.RadarLocationCallback() { @Override public void onComplete(final Radar.RadarStatus status, final Location location, final boolean stopped) { @@ -486,7 +455,7 @@ public void run() { } } - private void trackOnce(MethodCall call, final Result result) { + private static void trackOnce(MethodCall call, final Result result) { Radar.RadarTrackCallback callback = new Radar.RadarTrackCallback() { @Override public void onComplete(final Radar.RadarStatus status, final Location location, final RadarEvent[] events, final RadarUser user) { @@ -544,7 +513,7 @@ public void run() { } } - private void startTracking(MethodCall call, Result result) { + private static void startTracking(MethodCall call, Result result) { String preset = call.argument("preset"); if (preset == null) { Radar.startTracking(RadarTrackingOptions.RESPONSIVE); @@ -560,7 +529,7 @@ private void startTracking(MethodCall call, Result result) { result.success(true); } - private void startTrackingCustom(MethodCall call, Result result) { + private static void startTrackingCustom(MethodCall call, Result result) { HashMap optionsMap = (HashMap)call.arguments; JSONObject optionsJson = new JSONObject(optionsMap); RadarTrackingOptions options = RadarTrackingOptions.fromJson(optionsJson); @@ -568,15 +537,19 @@ private void startTrackingCustom(MethodCall call, Result result) { result.success(true); } - private void startTrackingVerified(MethodCall call, Result result) { - Boolean token = call.hasArgument("token") ? call.argument("token") : false; + private static void startTrackingVerified(MethodCall call, Result result) { int interval = call.hasArgument("interval") && call.argument("interval") != null ? (int)call.argument("interval") : 1; Boolean beacons = call.hasArgument("beacons") ? call.argument("beacons") : false; - Radar.startTrackingVerified(token, interval, beacons); + Radar.startTrackingVerified(interval, beacons); result.success(true); } - public void mockTracking(MethodCall call, final Result result) { + private static void stopTrackingVerified(MethodCall call, Result result) { + Radar.stopTrackingVerified(); + result.success(true); + } + + public static void mockTracking(MethodCall call, final Result result) { HashMap originMap = (HashMap)call.argument("origin"); Location origin = locationForMap(originMap); HashMap destinationMap = (HashMap)call.argument("destination"); @@ -601,17 +574,17 @@ public void onComplete(Radar.RadarStatus status, Location location, RadarEvent[] }); } - private void stopTracking(Result result) { + private static void stopTracking(Result result) { Radar.stopTracking(); result.success(true); } - private void isTracking(Result result) { + private static void isTracking(Result result) { Boolean isTracking = Radar.isTracking(); result.success(isTracking); } - private void getTrackingOptions(Result result) throws JSONException { + private static void getTrackingOptions(Result result) throws JSONException { RadarTrackingOptions options = Radar.getTrackingOptions(); JSONObject optionsJson = options.toJson(); HashMap optionsMap = null; @@ -621,7 +594,7 @@ private void getTrackingOptions(Result result) throws JSONException { result.success(optionsMap); } - public void startTrip(MethodCall call, Result result) throws JSONException { + public static void startTrip(MethodCall call, Result result) throws JSONException { HashMap tripOptionsMap = (HashMap)call.argument("tripOptions"); JSONObject tripOptionsJson = jsonForMap(tripOptionsMap); RadarTripOptions tripOptions = RadarTripOptions.fromJson(tripOptionsJson); @@ -660,7 +633,7 @@ public void run() { }); } - public void updateTrip(MethodCall call, Result result) throws JSONException { + public static void updateTrip(MethodCall call, Result result) throws JSONException { HashMap tripOptionsMap = (HashMap)call.argument("tripOptions"); JSONObject tripOptionsJson = jsonForMap(tripOptionsMap); RadarTripOptions tripOptions = RadarTripOptions.fromJson(tripOptionsJson); @@ -708,13 +681,13 @@ public void run() { }); } - public void getTripOptions(Result result) { + public static void getTripOptions(Result result) { RadarTripOptions tripOptions = Radar.getTripOptions(); HashMap map = new Gson().fromJson(tripOptions.toJson().toString(), HashMap.class); result.success(map); } - public void completeTrip(Result result) { + public static void completeTrip(Result result) { Radar.completeTrip(new Radar.RadarTripCallback() { @Override public void onComplete(@NonNull Radar.RadarStatus status, @@ -744,7 +717,7 @@ public void run() { }); } - public void cancelTrip(Result result) { + public static void cancelTrip(Result result) { Radar.cancelTrip(new Radar.RadarTripCallback() { @Override public void onComplete(@NonNull Radar.RadarStatus status, @@ -774,7 +747,7 @@ public void run() { }); } - public void getContext(MethodCall call, final Result result) { + public static void getContext(MethodCall call, final Result result) { Radar.RadarContextCallback callback = new Radar.RadarContextCallback() { @Override public void onComplete(final Radar.RadarStatus status, final Location location, final RadarContext context) { @@ -810,7 +783,7 @@ public void run() { } } - private void searchGeofences(MethodCall call, final Result result) throws JSONException { + private static void searchGeofences(MethodCall call, final Result result) throws JSONException { Radar.RadarSearchGeofencesCallback callback = new Radar.RadarSearchGeofencesCallback() { @Override public void onComplete(final Radar.RadarStatus status, final Location location, final RadarGeofence[] geofences) { @@ -848,15 +821,16 @@ public void run() { HashMap metadataMap = (HashMap)call.argument("metadata"); JSONObject metadata = jsonForMap(metadataMap); int limit = call.hasArgument("limit") ? (int)call.argument("limit") : 10; + boolean includeGeometry = call.hasArgument("includeGeometry") ? call.argument("includeGeometry") : false; if (near != null) { - Radar.searchGeofences(near, radius, tags, metadata, limit, callback); + Radar.searchGeofences(near, radius, tags, metadata, limit, includeGeometry, callback); } else { - Radar.searchGeofences(radius, tags, metadata, limit, callback); + Radar.searchGeofences(radius, tags, metadata, limit, includeGeometry, callback); } } - public void searchPlaces(MethodCall call, final Result result) { + public static void searchPlaces(MethodCall call, final Result result) { Radar.RadarSearchPlacesCallback callback = new Radar.RadarSearchPlacesCallback() { @Override public void onComplete(final Radar.RadarStatus status, final Location location, final RadarPlace[] places) { @@ -905,7 +879,7 @@ public void run() { } } - public void autocomplete(MethodCall call, final Result result) { + public static void autocomplete(MethodCall call, final Result result) { String query = call.argument("query"); HashMap nearMap = (HashMap)call.argument("near"); Location near = locationForMap(nearMap); @@ -939,10 +913,10 @@ public void run() { }); } - public void geocode(MethodCall call, final Result result) { + public static void geocode(MethodCall call, final Result result) { String query = call.argument("query"); - Radar.geocode(query, new Radar.RadarGeocodeCallback() { + Radar.geocode(query, null, null, new Radar.RadarGeocodeCallback() { @Override public void onComplete(final Radar.RadarStatus status, final RadarAddress[] addresses) { runOnMainThread(new Runnable() { @@ -966,7 +940,7 @@ public void run() { }); } - public void reverseGeocode(MethodCall call, final Result result) { + public static void reverseGeocode(MethodCall call, final Result result) { Radar.RadarGeocodeCallback callback = new Radar.RadarGeocodeCallback() { @Override public void onComplete(final Radar.RadarStatus status, final RadarAddress[] addresses) { @@ -990,16 +964,18 @@ public void run() { } }; - if (call.hasArgument("location")) { - HashMap locationMap = (HashMap)call.argument("location"); + String[] layers = call.hasArgument("layers") && call.argument("layers") != null ? call.argument("layers") + : null; + if (call.hasArgument("location") && call.argument("location") != null) { + HashMap locationMap = (HashMap) call.argument("location"); Location location = locationForMap(locationMap); - Radar.reverseGeocode(location, callback); + Radar.reverseGeocode(location, layers, callback); } else { - Radar.reverseGeocode(callback); + Radar.reverseGeocode(layers, callback); } } - public void ipGeocode(MethodCall call, final Result result) { + public static void ipGeocode(MethodCall call, final Result result) { Radar.ipGeocode(new Radar.RadarIpGeocodeCallback() { @Override public void onComplete(final Radar.RadarStatus status, final RadarAddress address, final boolean proxy) { @@ -1025,7 +1001,7 @@ public void run() { }); } - public void getDistance(MethodCall call, final Result result) throws JSONException { + public static void getDistance(MethodCall call, final Result result) throws JSONException { Radar.RadarRouteCallback callback = new Radar.RadarRouteCallback() { @Override public void onComplete(final Radar.RadarStatus status, final RadarRoutes routes) { @@ -1080,7 +1056,7 @@ public void run() { } } - public void logConversion(MethodCall call, final Result result) throws JSONException { + public static void logConversion(MethodCall call, final Result result) throws JSONException { Radar.RadarLogConversionCallback callback = new Radar.RadarLogConversionCallback() { @Override public void onComplete(@NonNull Radar.RadarStatus status, @Nullable RadarEvent event) { @@ -1115,17 +1091,17 @@ public void run() { } } - public void logBackgrounding(Result result) { + public static void logBackgrounding(Result result) { Radar.logBackgrounding(); result.success(true); } - public void logResigningActive(Result result) { + public static void logResigningActive(Result result) { Radar.logResigningActive(); result.success(true); } - public void getMatrix(MethodCall call, final Result result) throws JSONException { + public static void getMatrix(MethodCall call, final Result result) throws JSONException { ArrayList originsArr = call.argument("origins"); Location[] origins = new Location[originsArr.size()]; for (int i = 0; i < originsArr.size(); i++) { @@ -1179,25 +1155,19 @@ public void run() { }); } - public void trackVerified(MethodCall call, final Result result) { + public static void trackVerified(MethodCall call, final Result result) { Boolean beacons = call.hasArgument("beacons") ? call.argument("beacons") : false; - Radar.RadarTrackCallback callback = new Radar.RadarTrackCallback() { + Radar.RadarTrackVerifiedCallback callback = new Radar.RadarTrackVerifiedCallback() { @Override - public void onComplete(final Radar.RadarStatus status, final Location location, final RadarEvent[] events, final RadarUser user) { + public void onComplete(final Radar.RadarStatus status, final RadarVerifiedLocationToken token) { runOnMainThread(new Runnable() { @Override public void run() { try { JSONObject obj = new JSONObject(); obj.put("status", status.toString()); - if (location != null) { - obj.put("location", Radar.jsonForLocation(location)); - } - obj.put("events", RadarEvent.toJson(events)); - if ( user != null) { - obj.put("user", user.toJson()); - } + obj.put("token", token.toJson()); HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); @@ -1212,39 +1182,12 @@ public void run() { Radar.trackVerified(beacons, callback); } - public void trackVerifiedToken(MethodCall call, final Result result) { - Boolean beacons = call.hasArgument("beacons") ? call.argument("beacons") : false; - - Radar.RadarTrackTokenCallback callback = new Radar.RadarTrackTokenCallback() { - @Override - public void onComplete(final Radar.RadarStatus status, final String token) { - runOnMainThread(new Runnable() { - @Override - public void run() { - try { - JSONObject obj = new JSONObject(); - obj.put("status", status.toString()); - obj.put("token", token); - - HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); - result.success(map); - } catch (Exception e) { - result.error(e.toString(), e.getMessage(), e.getMessage()); - } - } - }); - } - }; - - Radar.trackVerifiedToken(beacons, callback); - } - - private void isUsingRemoteTrackingOptions(Result result) { + private static void isUsingRemoteTrackingOptions(Result result) { Boolean isRemoteTracking = Radar.isUsingRemoteTrackingOptions(); result.success(isRemoteTracking); } - public void validateAddress(MethodCall call, final Result result) throws JSONException { + public static void validateAddress(MethodCall call, final Result result) throws JSONException { Radar.RadarValidateAddressCallback callback = new Radar.RadarValidateAddressCallback() { @Override public void onComplete(final Radar.RadarStatus status, final RadarAddress address, final Radar.RadarAddressVerificationStatus verificationStatus) { @@ -1277,7 +1220,7 @@ public void run() { Radar.validateAddress(address, callback); } - private Location locationForMap(HashMap locationMap) { + private static Location locationForMap(HashMap locationMap) { double latitude = (Double)locationMap.get("latitude"); double longitude = (Double)locationMap.get("longitude"); Location location = new Location("RadarSDK"); @@ -1291,7 +1234,7 @@ private Location locationForMap(HashMap locationMap) { return location; } - private JSONObject jsonForMap(HashMap map) throws JSONException { + private static JSONObject jsonForMap(HashMap map) throws JSONException { JSONObject obj = new JSONObject(); try { for (Object key : map.keySet()) { @@ -1307,31 +1250,28 @@ private JSONObject jsonForMap(HashMap map) throws JSONException { public static class RadarFlutterReceiver extends RadarReceiver { + private MethodChannel channel; + + RadarFlutterReceiver(MethodChannel channel) { + this.channel = channel; + } + @Override public void onEventsReceived(Context context, RadarEvent[] events, RadarUser user) { 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 res = new Gson().fromJson(obj.toString(), HashMap.class); + final ArrayList eventsArgs = new ArrayList(); + eventsArgs.add(0); + eventsArgs.add(res); synchronized(lock) { - final ArrayList args = new ArrayList(); - args.add(callbackHandle); - args.add(res); runOnMainThread(new Runnable() { @Override public void run() { - sBackgroundChannel.invokeMethod("", args); + channel.invokeMethod("events", eventsArgs); } }); } @@ -1339,33 +1279,24 @@ public void run() { Log.e(TAG, e.toString()); } } - + @Override public void onLocationUpdated(Context context, Location location, RadarUser user) { try { - SharedPreferences sharedPrefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); - long callbackHandle = sharedPrefs.getLong("location", 0L); - - if (callbackHandle == 0L) { - Log.e(TAG, "callback handle is empty"); - return; - } - - RadarFlutterPlugin.initializeBackgroundEngine(context); - JSONObject obj = new JSONObject(); obj.put("location", Radar.jsonForLocation(location)); obj.put("user", user.toJson()); HashMap res = new Gson().fromJson(obj.toString(), HashMap.class); + + final ArrayList locationArgs = new ArrayList(); + locationArgs.add(0); + locationArgs.add(res); synchronized(lock) { - final ArrayList args = new ArrayList(); - args.add(callbackHandle); - args.add(res); runOnMainThread(new Runnable() { @Override public void run() { - sBackgroundChannel.invokeMethod("", args); + channel.invokeMethod("location", locationArgs); } }); } @@ -1373,32 +1304,25 @@ public void run() { Log.e(TAG, e.toString()); } } + public void onClientLocationUpdated(Context context, Location location, boolean stopped, Radar.RadarLocationSource source) { 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 res = new Gson().fromJson(obj.toString(), HashMap.class); - synchronized(lock) { - final ArrayList args = new ArrayList(); - args.add(callbackHandle); - args.add(res); + + final ArrayList clientLocationArgs = new ArrayList(); + clientLocationArgs.add(0); + clientLocationArgs.add(res); + synchronized(lock){ runOnMainThread(new Runnable() { @Override public void run() { - sBackgroundChannel.invokeMethod("", args); + channel.invokeMethod("clientLocation", clientLocationArgs); } }); } @@ -1410,27 +1334,18 @@ public void run() { @Override public void onError(Context context, Radar.RadarStatus status) { 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 res = new Gson().fromJson(obj.toString(), HashMap.class); - synchronized(lock) { - final ArrayList args = new ArrayList(); - args.add(callbackHandle); - args.add(res); + final ArrayList errorArgs = new ArrayList(); + errorArgs.add(0); + errorArgs.add(res); + synchronized(lock){ runOnMainThread(new Runnable() { @Override public void run() { - sBackgroundChannel.invokeMethod("", args); + channel.invokeMethod("error", errorArgs); } }); } @@ -1442,27 +1357,18 @@ public void run() { @Override public void onLog(Context context, String message) { 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 res = new Gson().fromJson(obj.toString(), HashMap.class); + final ArrayList logArgs = new ArrayList(); + logArgs.add(0); + logArgs.add(res); synchronized(lock) { - final ArrayList args = new ArrayList(); - args.add(callbackHandle); - args.add(res); runOnMainThread(new Runnable() { @Override public void run() { - sBackgroundChannel.invokeMethod("", args); + channel.invokeMethod("log", logArgs); } }); } @@ -1470,38 +1376,36 @@ public void run() { Log.e(TAG, e.toString()); } } - } - + public static class RadarFlutterVerifiedReceiver extends RadarVerifiedReceiver { - @Override - public void onTokenUpdated(Context context, String token) { - try { - SharedPreferences sharedPrefs = context.getSharedPreferences(TAG, Context.MODE_PRIVATE); - long callbackHandle = sharedPrefs.getLong("token", 0L); + private MethodChannel channel; - if (callbackHandle == 0L) { - return; - } + RadarFlutterVerifiedReceiver(MethodChannel channel) { + this.channel = channel; + } - RadarFlutterPlugin.initializeBackgroundEngine(context); + @Override + public void onTokenUpdated(Context context, RadarVerifiedLocationToken token) { + try { JSONObject obj = new JSONObject(); - obj.put("token", token); + obj.put("token", token.toJson()); HashMap res = new Gson().fromJson(obj.toString(), HashMap.class); + final ArrayList tokenArgs = new ArrayList(); + tokenArgs.add(0); + tokenArgs.add(res); synchronized(lock) { - final ArrayList args = new ArrayList(); - args.add(callbackHandle); - args.add(res); runOnMainThread(new Runnable() { @Override public void run() { - sBackgroundChannel.invokeMethod("", args); + channel.invokeMethod("token", tokenArgs); } }); } + } catch (Exception e) { Log.e(TAG, e.toString()); } @@ -1509,33 +1413,4 @@ public void run() { } - 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); - } - }; diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index fb4140f..aa55010 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -34,7 +34,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "io.radar.example" - minSdkVersion 16 + minSdkVersion flutter.minSdkVersion targetSdkVersion 29 versionCode flutterVersionCode.toInteger() versionName flutterVersionName @@ -49,7 +49,7 @@ android { } dependencies { - implementation 'io.radar:sdk:3.9.8' + implementation 'io.radar:sdk:3.15.0' implementation "com.google.android.play:integrity:1.2.0" } } diff --git a/example/android/build.gradle b/example/android/build.gradle index 21d7749..9881192 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -24,6 +24,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 4f8d4d2..8c6e561 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index bfd60c4..b331c7b 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '11.0' +platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 3c16ff9..9e54d3c 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -149,6 +149,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 717FBB0054865DEA34CA9827 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -165,7 +166,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -208,10 +209,12 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -220,6 +223,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; }; + 717FBB0054865DEA34CA9827 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 8AED107CD2EAE06C6755A899 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -244,6 +264,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 3db53b6..e67b280 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + UIApplicationSupportsIndirectInputEvents + diff --git a/example/lib/main.dart b/example/lib/main.dart index 4cbeaaa..b56d490 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -75,8 +75,6 @@ class _MyAppState extends State with WidgetsBindingObserver { Radar.setLogLevel('info'); Radar.setAnonymousTrackingEnabled(false); - Radar.attachListeners(); - Radar.onLocation(onLocation); Radar.onClientLocation(onClientLocation); Radar.onError(onError); @@ -85,7 +83,7 @@ class _MyAppState extends State with WidgetsBindingObserver { Radar.onToken(onToken); await Radar.requestPermissions(false); - + await Radar.requestPermissions(true); var permissionStatus = await Radar.getPermissionsStatus(); if (permissionStatus != "DENIED") { @@ -249,7 +247,43 @@ class _MyAppState extends State with WidgetsBindingObserver { ); print("searchPlaces: $resp"); }, - child: Text('searchPlaces'), + child: Text('searchPlaces()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.searchGeofences( + near: { + 'latitude': 40.783826, + 'longitude': -73.975363, + }, + radius: 1000, + limit: 10, + includeGeometry: true, + tags: List.empty(), + metadata: {}, + ); + print("searchGeofences: $resp"); + }, + child: Text('searchGeofences()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.geocode( + '20 jay st brooklyn', + ); + print("geocode: $resp"); + }, + child: Text('geocode()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.reverseGeocode(); + print("reverseGeocode: $resp"); + }, + child: Text('reverseGeocode()'), ), ElevatedButton( style: raisedButtonStyle, @@ -339,9 +373,16 @@ class _MyAppState extends State with WidgetsBindingObserver { ElevatedButton( style: raisedButtonStyle, onPressed: () { - Radar.startTrackingVerified(token: true); + Radar.startTrackingVerified(30, false); }, - child: Text('startTrackingVerified(token: true)'), + child: Text('startTrackingVerified()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () { + Radar.stopTrackingVerified(); + }, + child: Text('stopTrackingVerified()'), ), ElevatedButton( style: raisedButtonStyle, @@ -376,16 +417,9 @@ class _MyAppState extends State with WidgetsBindingObserver { Map? resp = await Radar.trackVerified(); print("trackVerified: $resp"); }, - child: Text('trackVerified'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - Map? resp = await Radar.trackVerifiedToken(); - print("trackVerifiedToken: $resp"); - }, - child: Text('trackVerifiedToken'), + child: Text('trackVerified()'), ), + ElevatedButton( style: raisedButtonStyle, onPressed: () async { diff --git a/ios/Classes/RadarFlutterPlugin.m b/ios/Classes/RadarFlutterPlugin.m index 487b8fe..28941e8 100644 --- a/ios/Classes/RadarFlutterPlugin.m +++ b/ios/Classes/RadarFlutterPlugin.m @@ -74,6 +74,8 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { [self startTrackingCustom:call withResult:result]; } else if ([@"startTrackingVerified" isEqualToString:call.method]) { [self startTrackingVerified:call withResult:result]; + } else if ([@"stopTrackingVerified" isEqualToString:call.method]) { + [self stopTrackingVerified:call withResult:result]; } else if ([@"stopTracking" isEqualToString:call.method]) { [self stopTracking:call withResult:result]; } else if ([@"isTracking" isEqualToString:call.method]) { @@ -124,20 +126,10 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { // do nothing } else if ([@"trackVerified" isEqualToString:call.method]) { [self trackVerified:call withResult:result]; - } else if ([@"trackVerifiedToken" isEqualToString:call.method]) { - [self trackVerifiedToken:call withResult:result]; } else if ([@"isUsingRemoteTrackingOptions" isEqualToString:call.method]) { [self isUsingRemoteTrackingOptions:call withResult:result]; } else if ([@"validateAddress" isEqualToString:call.method]) { [self validateAddress:call withResult:result]; - } else if ([@"attachListeners" isEqualToString:call.method]) { - [self attachListeners:call withResult:result]; - } else if ([@"detachListeners" isEqualToString:call.method]) { - [self detachListeners:call withResult:result]; - } else if ([@"on" isEqualToString:call.method]) { - [self on:call withResult:result]; - } else if ([@"off" isEqualToString:call.method]) { - [self off:call withResult:result]; } else { result(FlutterMethodNotImplemented); } @@ -148,7 +140,7 @@ - (void)initialize:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSString *publishableKey = argsDict[@"publishableKey"]; [[NSUserDefaults standardUserDefaults] setObject:@"Flutter" forKey:@"radar-xPlatformSDKType"]; - [[NSUserDefaults standardUserDefaults] setObject:@"3.9.1" forKey:@"radar-xPlatformSDKVersion"]; + [[NSUserDefaults standardUserDefaults] setObject:@"3.10.0" forKey:@"radar-xPlatformSDKVersion"]; [Radar initializeWithPublishableKey:publishableKey]; result(nil); } @@ -379,12 +371,6 @@ - (void)startTrackingCustom:(FlutterMethodCall *)call withResult:(FlutterResult) - (void)startTrackingVerified:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - BOOL token = NO; - NSNumber *tokenNumber = argsDict[@"token"]; - if (tokenNumber != nil && [tokenNumber isKindOfClass:[NSNumber class]]) { - token = [tokenNumber boolValue]; - } - BOOL beacons = NO; NSNumber *beaconsNumber = argsDict[@"beacons"]; if (beaconsNumber != nil && [beaconsNumber isKindOfClass:[NSNumber class]]) { @@ -397,7 +383,12 @@ - (void)startTrackingVerified:(FlutterMethodCall *)call withResult:(FlutterResul interval = [intervalNumber doubleValue]; } - [Radar startTrackingVerified:token interval:interval beacons:beacons]; + [Radar startTrackingVerifiedWithInterval:interval beacons:beacons]; + result(nil); +} + +- (void)stopTrackingVerified:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Radar stopTrackingVerified]; result(nil); } @@ -639,11 +630,17 @@ - (void)searchGeofences:(FlutterMethodCall *)call withResult:(FlutterResult)resu } else { limit = 10; } + BOOL includeGeometry = NO; + NSNumber *includeGeometryNumber = argsDict[@"includeGeometry"]; + if (includeGeometryNumber != nil && [includeGeometryNumber isKindOfClass:[NSNumber class]]) { + includeGeometry = [includeGeometryNumber boolValue]; + } + if (near != nil) { - [Radar searchGeofencesNear:near radius:radius tags:tags metadata:metadata limit:limit completionHandler:completionHandler]; + [Radar searchGeofencesNear:near radius:radius tags:tags metadata:metadata limit:limit includeGeometry:includeGeometry completionHandler:completionHandler]; } else { - [Radar searchGeofencesWithRadius:radius tags:tags metadata:metadata limit:limit completionHandler:completionHandler]; + [Radar searchGeofences:completionHandler]; } } @@ -765,9 +762,30 @@ - (void)reverseGeocode:(FlutterMethodCall *)call withResult:(FlutterResult)resul result(dict); }; - NSDictionary *argsDict = call.arguments; + NSDictionary *argsDict = call.arguments; - NSDictionary *locationDict = argsDict[@"location"]; + NSArray *layers = nil; + id layersValue = argsDict[@"layers"]; + if (layersValue != nil && [layersValue isKindOfClass:[NSArray class]]) { + NSArray *tempLayers = (NSArray *)layersValue; + // Further check if the array contains only NSString objects + BOOL allStrings = YES; + for (id item in tempLayers) { + if (![item isKindOfClass:[NSString class]]) { + allStrings = NO; + break; + } + } + if (allStrings) { + layers = tempLayers; + } + } + + NSDictionary *locationDict = nil; + id locationDictValue = argsDict[@"location"]; + if (locationDictValue != nil && [locationDictValue isKindOfClass:[NSDictionary class]]) { + locationDict = (NSDictionary *)locationDictValue; + } if (locationDict) { NSNumber *latitudeNumber = locationDict[@"latitude"]; NSNumber *longitudeNumber = locationDict[@"longitude"]; @@ -775,9 +793,9 @@ - (void)reverseGeocode:(FlutterMethodCall *)call withResult:(FlutterResult)resul double longitude = [longitudeNumber doubleValue]; CLLocation *location = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) altitude:-1 horizontalAccuracy:5 verticalAccuracy:-1 timestamp:[NSDate date]]; - [Radar reverseGeocodeLocation:location completionHandler:completionHandler]; + [Radar reverseGeocodeLocation:location layers:layers completionHandler:completionHandler]; } else { - [Radar reverseGeocodeWithCompletionHandler:completionHandler]; + [Radar reverseGeocodeWithLayers:layers completionHandler:completionHandler]; } } @@ -956,19 +974,11 @@ - (void)trackVerified:(FlutterMethodCall *)call withResult:(FlutterResult)result beacons = [beaconsNumber boolValue]; } - RadarTrackCompletionHandler completionHandler = ^(RadarStatus status, CLLocation *location, NSArray *events, RadarUser *user) { + RadarTrackVerifiedCompletionHandler completionHandler = ^(RadarStatus status, RadarVerifiedLocationToken* token) { if (status == RadarStatusSuccess) { NSMutableDictionary *dict = [NSMutableDictionary new]; [dict setObject:[Radar stringForStatus:status] forKey:@"status"]; - if (location) { - [dict setObject:[Radar dictionaryForLocation:location] forKey:@"location"]; - } - if (events) { - [dict setObject:[RadarEvent arrayForEvents:events] forKey:@"events"]; - } - if (user) { - [dict setObject:[user dictionaryValue] forKey:@"user"]; - } + [dict setObject:[token dictionaryValue] forKey:@"token"]; result(dict); } }; @@ -976,27 +986,6 @@ - (void)trackVerified:(FlutterMethodCall *)call withResult:(FlutterResult)result [Radar trackVerifiedWithBeacons:beacons completionHandler:completionHandler]; } -- (void)trackVerifiedToken:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSDictionary *argsDict = call.arguments; - - BOOL beacons = NO; - NSNumber *beaconsNumber = argsDict[@"beacons"]; - if (beaconsNumber != nil && [beaconsNumber isKindOfClass:[NSNumber class]]) { - beacons = [beaconsNumber boolValue]; - } - - RadarTrackTokenCompletionHandler completionHandler = ^(RadarStatus status, NSString* token) { - if (status == RadarStatusSuccess) { - NSMutableDictionary *dict = [NSMutableDictionary new]; - [dict setObject:[Radar stringForStatus:status] forKey:@"status"]; - [dict setObject:token forKey:@"token"]; - result(dict); - } - }; - - [Radar trackVerifiedTokenWithBeacons:beacons completionHandler:completionHandler]; -} - - (void)validateAddress:(FlutterMethodCall *)call withResult:(FlutterResult)result { RadarValidateAddressCompletionHandler completionHandler = ^(RadarStatus status, RadarAddress * _Nullable address, RadarAddressVerificationStatus verificationStatus) { NSMutableDictionary *dict = [NSMutableDictionary new]; @@ -1015,111 +1004,52 @@ - (void)validateAddress:(FlutterMethodCall *)call withResult:(FlutterResult)resu [Radar validateAddress:address completionHandler:completionHandler]; } --(void)attachListeners:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSNumber* callbackDispatcherHandle = call.arguments[@"callbackDispatcherHandle"]; - - // Retrieve the callback information - FlutterCallbackInformation *callbackInfo = [FlutterCallbackCache lookupCallbackInformation:[callbackDispatcherHandle longValue]]; - - // Create the background Flutter engine - FlutterEngine *sBackgroundFlutterEngine; - sBackgroundFlutterEngine = [[FlutterEngine alloc] init]; - self.sBackgroundFlutterEngine = sBackgroundFlutterEngine; - - FlutterMethodChannel *backgroundChannel = [FlutterMethodChannel methodChannelWithName:@"flutter_radar_background" binaryMessenger:[sBackgroundFlutterEngine binaryMessenger]]; - self.backgroundChannel = backgroundChannel; - - [self.sBackgroundFlutterEngine runWithEntrypoint:callbackInfo.callbackName libraryURI: callbackInfo.callbackLibraryPath] ; - result(nil); -} - --(void)detachListeners:(FlutterMethodCall *)call withResult:(FlutterResult)result { - self.backgroundChannel = nil; - result(nil); -} - --(void)on:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSDictionary *argsDict = call.arguments; - NSString* listener = argsDict[@"listener"]; - NSNumber *callbackHandleNumber = argsDict[@"callbackHandle"]; - long callbackHandle = [callbackHandleNumber longValue]; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:callbackHandleNumber forKey:listener]; - result(nil); -} - --(void)off:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSDictionary *argsDict = call.arguments; - NSString* listener = argsDict[@"listener"]; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:nil forKey:listener]; - result(nil); -} - - (void)didReceiveEvents:(NSArray *)events user:(RadarUser *)user { NSDictionary *dict = @{@"events": [RadarEvent arrayForEvents:events], @"user": user ? [user dictionaryValue] : @""}; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - NSInteger callbackHandle = [userDefaults integerForKey:@"events"]; - if (callbackHandle == 0) { - return; + NSArray* args = @[@0, dict]; + if (self.channel != nil) { + [self.channel invokeMethod:@"events" arguments:args]; } - NSArray* args = @[[NSNumber numberWithInteger:callbackHandle], dict]; - [self.backgroundChannel invokeMethod:@"" arguments:args]; } - (void)didUpdateLocation:(CLLocation *)location user:(RadarUser *)user { NSDictionary *dict = @{@"location": [Radar dictionaryForLocation:location], @"user": [user dictionaryValue]}; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - NSInteger callbackHandle = [userDefaults integerForKey:@"location"]; - if (callbackHandle == 0) { - return; + NSArray* args = @[@0, dict]; + if (self.channel != nil) { + [self.channel invokeMethod:@"location" arguments:args]; } - NSArray* args = @[[NSNumber numberWithInteger:callbackHandle], dict]; - [self.backgroundChannel invokeMethod:@"" arguments:args]; } - (void)didUpdateClientLocation:(CLLocation *)location stopped:(BOOL)stopped source:(RadarLocationSource)source { NSDictionary *dict = @{@"location": [Radar dictionaryForLocation:location], @"stopped": @(stopped), @"source": [Radar stringForLocationSource:source]}; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - NSInteger callbackHandle = [userDefaults integerForKey:@"clientLocation"]; - if (callbackHandle == 0) { - return; + NSArray* args = @[@0, dict]; + if (self.channel != nil) { + [self.channel invokeMethod:@"clientLocation" arguments:args]; } - NSArray* args = @[[NSNumber numberWithInteger:callbackHandle], dict]; - [self.backgroundChannel invokeMethod:@"" arguments:args]; } - (void)didFailWithStatus:(RadarStatus)status { NSDictionary *dict = @{@"status": [Radar stringForStatus:status]}; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - NSInteger callbackHandle = [userDefaults integerForKey:@"error"]; - if (callbackHandle == 0) { - return; + NSArray* args = @[@0, dict]; + if (self.channel != nil) { + [self.channel invokeMethod:@"error" arguments:args]; } - NSArray* args = @[[NSNumber numberWithInteger:callbackHandle], dict]; - [self.backgroundChannel invokeMethod:@"" arguments:args]; } - (void)didLogMessage:(NSString *)message { NSDictionary *dict = @{@"message": message}; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - NSNumber* callbackHandle = [userDefaults objectForKey:@"log"]; - if (callbackHandle == 0) { - return; + NSArray* args = @[@0, dict]; + if (self.channel != nil) { + [self.channel invokeMethod:@"log" arguments:args]; } - NSArray* args = @[callbackHandle, dict]; - [self.backgroundChannel invokeMethod:@"" arguments:args]; } - (void)didUpdateToken:(NSString *)token { NSDictionary *dict = @{@"token": token}; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - NSNumber* callbackHandle = [userDefaults objectForKey:@"token"]; - if (callbackHandle == 0) { - return; + NSArray* args = @[@0, dict]; + if (self.channel != nil) { + [self.channel invokeMethod:@"token" arguments:args]; } - NSArray* args = @[callbackHandle, dict]; - [self.backgroundChannel invokeMethod:@"" arguments:args]; } @end diff --git a/ios/flutter_radar.podspec b/ios/flutter_radar.podspec index 63f63da..9749451 100644 --- a/ios/flutter_radar.podspec +++ b/ios/flutter_radar.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'flutter_radar' - s.version = '3.9.1' + s.version = '3.10.0' s.summary = 'Flutter package for Radar, the leading geofencing and location tracking platform' s.description = 'Flutter package for Radar, the leading geofencing and location tracking platform' s.homepage = 'http://example.com' @@ -10,7 +10,7 @@ Pod::Spec.new do |s| s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - s.dependency 'RadarSDK', '3.9.14' + s.dependency 'RadarSDK', '3.15.0' s.platform = :ios, '10.0' s.static_framework = true diff --git a/lib/flutter_radar.dart b/lib/flutter_radar.dart index c344a86..2477bd0 100644 --- a/lib/flutter_radar.dart +++ b/lib/flutter_radar.dart @@ -20,35 +20,59 @@ void callbackDispatcher() { }); } +typedef LocationCallback = void Function(Map locationEvent); +typedef ClientLocationCallback = void Function( + Map locationEvent, +); +typedef ErrorCallback = void Function(Map errorEvent); +typedef LogCallback = void Function(Map logEvent); +typedef EventsCallback = void Function(Map eventsEvent); +typedef TokenCallback = void Function(Map tokenEvent); + class Radar { static const MethodChannel _channel = const MethodChannel('flutter_radar'); + static LocationCallback? foregroundLocationCallback; + static ClientLocationCallback? foregroundClientLocationCallback; + static ErrorCallback? foregroundErrorCallback; + static LogCallback? foregroundLogCallback; + static EventsCallback? foregroundEventsCallback; + static TokenCallback? foregroundTokenCallback; + static Future initialize(String publishableKey) async { try { await _channel.invokeMethod('initialize', { 'publishableKey': publishableKey, }); + _channel.setMethodCallHandler(_handleMethodCall); } on PlatformException catch (e) { print(e); } } - static attachListeners() async { - try { - await _channel.invokeMethod('attachListeners', { - 'callbackDispatcherHandle': - PluginUtilities.getCallbackHandle(callbackDispatcher)?.toRawHandle() - }); - } on PlatformException catch (e) { - print(e); - } - } - - static Future detachListeners() async { - try { - await _channel.invokeMethod('detachListeners'); - } on PlatformException catch (e) { - print(e); + static Future _handleMethodCall(MethodCall call) async { + final args = call.arguments; + switch (call.method) { + case 'location': + foregroundLocationCallback?.call(args[1] as Map); + break; + case 'clientLocation': + foregroundClientLocationCallback?.call( + args[1] as Map, + ); + break; + case 'error': + foregroundErrorCallback?.call(args[1] as Map); + break; + case 'log': + foregroundLogCallback?.call(args[1] as Map); + break; + case 'events': + foregroundEventsCallback?.call(args[1] as Map); + break; + case 'token': + foregroundTokenCallback?.call(args[1] as Map); + break; } } @@ -162,11 +186,10 @@ class Radar { } } - static Future startTrackingVerified( - {bool? token, int? interval, bool? beacons}) async { + static Future startTrackingVerified(int interval, bool beacons) async { try { - await _channel.invokeMethod('startTrackingVerified', - {'token': token, 'interval': interval, 'beacons': beacons}); + await _channel.invokeMethod( + 'startTrackingVerified', {'interval': interval, 'beacons': beacons}); } on PlatformException catch (e) { print(e); } @@ -180,6 +203,14 @@ class Radar { } } + static Future stopTrackingVerified() async { + try { + await _channel.invokeMethod('stopTrackingVerified'); + } on PlatformException catch (e) { + print(e); + } + } + static Future isTracking() async { return await _channel.invokeMethod('isTracking'); } @@ -272,14 +303,16 @@ class Radar { int? radius, List? tags, Map? metadata, - int? limit}) async { + int? limit, + bool? includeGeometry}) async { try { return await _channel.invokeMethod('searchGeofences', { 'near': near, 'radius': radius, 'limit': limit, 'tags': tags, - 'metadata': metadata + 'metadata': metadata, + 'includeGeometry': includeGeometry }); } on PlatformException catch (e) { print(e); @@ -344,10 +377,14 @@ class Radar { } } - static Future reverseGeocode(Map location) async { + static Future reverseGeocode( + {Map? location, List? layers}) async { try { - return await _channel - .invokeMethod('reverseGeocode', {'location': location}); + final Map arguments = { + 'location': location != null ? location : null, + 'layers': layers != null ? layers : null + }; + return await _channel.invokeMethod('reverseGeocode', arguments); } on PlatformException catch (e) { print(e); return {'error': e.code}; @@ -460,17 +497,8 @@ class Radar { static Future trackVerified({bool? beacons}) async { try { - return await _channel.invokeMethod('trackVerified', {'beacons': beacons}); - } on PlatformException catch (e) { - print(e); - return {'error': e.code}; - } - } - - static Future trackVerifiedToken({bool? beacons}) async { - try { - return await _channel - .invokeMethod('trackVerifiedToken', {'beacons': beacons}); + return await _channel.invokeMethod( + 'trackVerified', {'beacons': beacons != null ? beacons : false}); } on PlatformException catch (e) { print(e); return {'error': e.code}; @@ -491,166 +519,116 @@ class Radar { } } - static onLocation(Function(Map res) callback) async { - try { - final CallbackHandle handle = - PluginUtilities.getCallbackHandle(callback)!; - await _channel.invokeMethod('on', - {'listener': 'location', 'callbackHandle': handle.toRawHandle()}); - } on PlatformException catch (e) { - print(e); + static onLocation(LocationCallback callback) { + if (foregroundLocationCallback != null) { + throw RadarExistingCallbackException(); } + foregroundLocationCallback = callback; } - static offLocation() async { - try { - await _channel.invokeMethod('off', {'listener': 'location'}); - } on PlatformException catch (e) { - print(e); - } + static offLocation() { + foregroundLocationCallback = null; } - static onClientLocation(Function(Map res) callback) async { - try { - final CallbackHandle handle = - PluginUtilities.getCallbackHandle(callback)!; - await _channel.invokeMethod('on', { - 'listener': 'clientLocation', - 'callbackHandle': handle.toRawHandle() - }); - } on PlatformException catch (e) { - print(e); + static void onClientLocation(ClientLocationCallback callback) { + if (foregroundClientLocationCallback != null) { + throw RadarExistingCallbackException(); } + foregroundClientLocationCallback = callback; } - static offClientLocation() async { - try { - await _channel.invokeMethod('off', {'listener': 'clientLocation'}); - } on PlatformException catch (e) { - print(e); - } + static offClientLocation() { + foregroundClientLocationCallback = null; } - static onError(Function(Map res) callback) async { - try { - final CallbackHandle handle = - PluginUtilities.getCallbackHandle(callback)!; - await _channel.invokeMethod( - 'on', {'listener': 'error', 'callbackHandle': handle.toRawHandle()}); - } on PlatformException catch (e) { - print(e); + static onError(ErrorCallback callback) { + if (foregroundErrorCallback != null) { + throw RadarExistingCallbackException(); } + foregroundErrorCallback = callback; } - static offError() async { - try { - await _channel.invokeMethod('off', {'listener': 'error'}); - } on PlatformException catch (e) { - print(e); - } + static offError() { + foregroundErrorCallback = null; } - static onLog(Function(Map res) callback) async { - try { - final CallbackHandle handle = - PluginUtilities.getCallbackHandle(callback)!; - await _channel.invokeMethod( - 'on', {'listener': 'log', 'callbackHandle': handle.toRawHandle()}); - } on PlatformException catch (e) { - print(e); + static onLog(LogCallback callback) { + if (foregroundLogCallback != null) { + throw RadarExistingCallbackException(); } + foregroundLogCallback = callback; } - static offLog() async { - try { - await _channel.invokeMethod('off', {'listener': 'log'}); - } on PlatformException catch (e) { - print(e); - } + static offLog() { + foregroundLogCallback = null; } - - static onEvents(Function(Map res) callback) async { - try { - final CallbackHandle handle = - PluginUtilities.getCallbackHandle(callback)!; - await _channel.invokeMethod( - 'on', {'listener': 'events', 'callbackHandle': handle.toRawHandle()}); - } on PlatformException catch (e) { - print(e); + + static onEvents(EventsCallback callback) { + if (foregroundEventsCallback != null) { + throw RadarExistingCallbackException(); } + foregroundEventsCallback = callback; } - static offEvents() async { - try { - await _channel.invokeMethod('off', {'listener': 'events'}); - } on PlatformException catch (e) { - print(e); - } + static offEvents() { + foregroundEventsCallback = null; } - static onToken(Function(Map res) callback) async { - try { - final CallbackHandle handle = - PluginUtilities.getCallbackHandle(callback)!; - await _channel.invokeMethod( - 'on', {'listener': 'token', 'callbackHandle': handle.toRawHandle()}); - } on PlatformException catch (e) { - print(e); + static onToken(TokenCallback callback) { + if (foregroundTokenCallback != null) { + throw RadarExistingCallbackException(); } + foregroundTokenCallback = callback; } - static offToken() async { - try { - await _channel.invokeMethod('off', {'listener': 'token'}); - } on PlatformException catch (e) { - print(e); - } + static offToken() { + foregroundTokenCallback = null; } static Map presetContinuousIOS = { - "desiredStoppedUpdateInterval": 30, - "desiredMovingUpdateInterval": 30, - "desiredSyncInterval": 20, - "desiredAccuracy":'high', - "stopDuration": 140, - "stopDistance": 70, - "replay": 'none', - "useStoppedGeofence": false, - "showBlueBar": true, - "startTrackingAfter": null, - "stopTrackingAfter": null, - "stoppedGeofenceRadius": 0, - "useMovingGeofence": false, - "movingGeofenceRadius": 0, - "syncGeofences": true, - "useVisits": false, - "useSignificantLocationChanges": false, - "beacons": false, - "sync": 'all', -}; - - static Map presetContinuousAndroid = { - "desiredStoppedUpdateInterval": 30, - "fastestStoppedUpdateInterval": 30, - "desiredMovingUpdateInterval": 30, - "fastestMovingUpdateInterval": 30, - "desiredSyncInterval": 20, - "desiredAccuracy": 'high', - "stopDuration": 140, - "stopDistance": 70, - "replay": 'none', - "sync": 'all', - "useStoppedGeofence": false, - "stoppedGeofenceRadius": 0, - "useMovingGeofence": false, - "movingGeofenceRadius": 0, - "syncGeofences": true, - "syncGeofencesLimit": 0, - "foregroundServiceEnabled": true, - "beacons": false, - "startTrackingAfter": null, - "stopTrackingAfter": null, -}; + "desiredStoppedUpdateInterval": 30, + "desiredMovingUpdateInterval": 30, + "desiredSyncInterval": 20, + "desiredAccuracy": 'high', + "stopDuration": 140, + "stopDistance": 70, + "replay": 'none', + "useStoppedGeofence": false, + "showBlueBar": true, + "startTrackingAfter": null, + "stopTrackingAfter": null, + "stoppedGeofenceRadius": 0, + "useMovingGeofence": false, + "movingGeofenceRadius": 0, + "syncGeofences": true, + "useVisits": false, + "useSignificantLocationChanges": false, + "beacons": false, + "sync": 'all', + }; + + static Map presetContinuousAndroid = { + "desiredStoppedUpdateInterval": 30, + "fastestStoppedUpdateInterval": 30, + "desiredMovingUpdateInterval": 30, + "fastestMovingUpdateInterval": 30, + "desiredSyncInterval": 20, + "desiredAccuracy": 'high', + "stopDuration": 140, + "stopDistance": 70, + "replay": 'none', + "sync": 'all', + "useStoppedGeofence": false, + "stoppedGeofenceRadius": 0, + "useMovingGeofence": false, + "movingGeofenceRadius": 0, + "syncGeofences": true, + "syncGeofencesLimit": 0, + "foregroundServiceEnabled": true, + "beacons": false, + "startTrackingAfter": null, + "stopTrackingAfter": null, + }; static Map presetResponsiveIOS = { "desiredStoppedUpdateInterval": 0, @@ -698,54 +676,61 @@ class Radar { }; static Map presetEfficientIOS = { - "desiredStoppedUpdateInterval": 0, - "desiredMovingUpdateInterval": 0, - "desiredSyncInterval": 0, - "desiredAccuracy": "medium", - "stopDuration": 0, - "stopDistance": 0, - "replay": 'stops', - "useStoppedGeofence": false, - "showBlueBar": false, - "startTrackingAfter": null, - "stopTrackingAfter": null, - "stoppedGeofenceRadius": 0, - "useMovingGeofence": false, - "movingGeofenceRadius": 0, - "syncGeofences": true, - "useVisits": true, - "useSignificantLocationChanges": false, - "beacons": false, - "sync": 'all', -}; - - static Map presetEfficientAndroid ={ - "desiredStoppedUpdateInterval": 3600, - "fastestStoppedUpdateInterval": 1200, - "desiredMovingUpdateInterval": 1200, - "fastestMovingUpdateInterval": 360, - "desiredSyncInterval": 140, - "desiredAccuracy": 'medium', - "stopDuration": 140, - "stopDistance": 70, - "replay": 'stops', - "sync": 'all', - "useStoppedGeofence": false, - "stoppedGeofenceRadius": 0, - "useMovingGeofence": false, - "movingGeofenceRadius": 0, - "syncGeofences": true, - "syncGeofencesLimit": 10, - "foregroundServiceEnabled": false, - "beacons": false, - "startTrackingAfter": null, - "stopTrackingAfter": null, -}; + "desiredStoppedUpdateInterval": 0, + "desiredMovingUpdateInterval": 0, + "desiredSyncInterval": 0, + "desiredAccuracy": "medium", + "stopDuration": 0, + "stopDistance": 0, + "replay": 'stops', + "useStoppedGeofence": false, + "showBlueBar": false, + "startTrackingAfter": null, + "stopTrackingAfter": null, + "stoppedGeofenceRadius": 0, + "useMovingGeofence": false, + "movingGeofenceRadius": 0, + "syncGeofences": true, + "useVisits": true, + "useSignificantLocationChanges": false, + "beacons": false, + "sync": 'all', + }; + + static Map presetEfficientAndroid = { + "desiredStoppedUpdateInterval": 3600, + "fastestStoppedUpdateInterval": 1200, + "desiredMovingUpdateInterval": 1200, + "fastestMovingUpdateInterval": 360, + "desiredSyncInterval": 140, + "desiredAccuracy": 'medium', + "stopDuration": 140, + "stopDistance": 70, + "replay": 'stops', + "sync": 'all', + "useStoppedGeofence": false, + "stoppedGeofenceRadius": 0, + "useMovingGeofence": false, + "movingGeofenceRadius": 0, + "syncGeofences": true, + "syncGeofencesLimit": 10, + "foregroundServiceEnabled": false, + "beacons": false, + "startTrackingAfter": null, + "stopTrackingAfter": null, + }; static Map presetResponsive = Platform.isIOS ? presetResponsiveIOS : presetResponsiveAndroid; static Map presetContinuous = Platform.isIOS ? presetContinuousIOS : presetContinuousAndroid; - static Map presetEfficient= + static Map presetEfficient = Platform.isIOS ? presetEfficientIOS : presetEfficientAndroid; } + +class RadarExistingCallbackException implements Exception { + @override + String toString() { + return 'Existing callback already exists for this event. Please call the corresponding `off` method first.'; + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 482f01e..2b48bb1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_radar description: Flutter package for Radar, the leading geofencing and location tracking platform -version: 3.9.1 +version: 3.10.0 homepage: https://github.com/radarlabs/flutter-radar environment: