diff --git a/CHANGELOG.md b/CHANGELOG.md index c81afbe..92c9114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 3.10.0-beta.1 + +- 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..93a28f8 100644 --- a/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java +++ b/android/src/main/java/io/radar/flutter/RadarFlutterPlugin.java @@ -21,6 +21,7 @@ import org.json.JSONObject; import org.jetbrains.annotations.Nullable; +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; @@ -58,6 +59,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,7 +68,8 @@ import io.flutter.view.FlutterRunArguments; import io.flutter.view.FlutterCallbackInformation; -public class RadarFlutterPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware, RequestPermissionsResultListener { +public class RadarFlutterPlugin + implements FlutterPlugin, MethodCallHandler, ActivityAware, RequestPermissionsResultListener { private static FlutterEngine sBackgroundFlutterEngine; @@ -76,40 +79,19 @@ public class RadarFlutterPlugin implements FlutterPlugin, MethodCallHandler, Act private static final String TAG = "RadarFlutterPlugin"; private static final String CALLBACK_DISPATCHER_HANDLE_KEY = "callbackDispatcherHandle"; private static MethodChannel sBackgroundChannel; + private MethodChannel channel; 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"); - } - } - } - @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - Radar.setReceiver(new RadarFlutterReceiver()); mContext = binding.getApplicationContext(); - MethodChannel channel = new MethodChannel(binding.getFlutterEngine().getDartExecutor(), "flutter_radar"); + channel = new MethodChannel(binding.getFlutterEngine().getDartExecutor(), "flutter_radar"); + Radar.setReceiver(new RadarFlutterReceiver(channel)); + Radar.setVerifiedReceiver(new RadarFlutterVerifiedReceiver(channel)); channel.setMethodCallHandler(this); } @@ -215,6 +197,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) case "startTrackingVerified": startTrackingVerified(call, result); break; + case "stopTrackingVerified": + stopTrackingVerified(call, result); + break; case "stopTracking": stopTracking(result); break; @@ -245,6 +230,12 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) case "cancelTrip": cancelTrip(result); break; + case "acceptEvent": + acceptEvent(call, result); + break; + case "rejectEvent": + rejectEvent(call, result); + break; case "getContext": getContext(call, result); break; @@ -256,7 +247,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) break; case "autocomplete": autocomplete(call, result); - break; + break; case "forwardGeocode": geocode(call, result); break; @@ -293,24 +284,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) 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; @@ -320,18 +296,104 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) } } + private String getStringFromMethodCall(MethodCall call, String key) { + try { + final Map arguments = call.arguments(); + if (arguments.containsKey(key)) { + Object value = arguments.get(key); + if (value instanceof String) { + return (String) value; // Return the string value if it exists and is a string + } + } + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + return null; // Return null if the key does not exist or is not a string + } + + private boolean getBooleanFromMethodCall(MethodCall call, String key, boolean defaultValue) { + try { + final Map arguments = call.arguments(); + if (arguments.containsKey(key)) { + Object value = arguments.get(key); + if (value instanceof Boolean) { + return (Boolean) value; + } + } + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + return defaultValue; + } + + private HashMap getHashMapFromMethodCall(MethodCall call, String key) { + try { + final Map arguments = call.arguments(); + if (arguments.containsKey(key)) { + Object value = arguments.get(key); + if (value instanceof HashMap) { + return (HashMap) value; + } + } + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + return null; + } + + private int getIntFromMethodCall(MethodCall call, String key, int defaultValue) { + try { + final Map arguments = call.arguments(); + if (arguments.containsKey(key)) { + Object value = arguments.get(key); + if (value instanceof Integer) { + return (Integer) value; + } + } + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + return defaultValue; + } + + private ArrayList getArrayListFromMethodCall(MethodCall call, String key) { + try { + final Map arguments = call.arguments(); + if (arguments.containsKey(key)) { + Object value = arguments.get(key); + if (value instanceof ArrayList) { + return (ArrayList) value; + } + } + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + return null; + } + + private String[] getStringArrayFromMethodCall(MethodCall call, String key) { + ArrayList list = getArrayListFromMethodCall(call, key); + if (list != null) { + return list.toArray(new String[0]); + } + return null; + } + private void initialize(MethodCall call, Result result) { - String publishableKey = call.argument("publishableKey"); + String publishableKey = getStringFromMethodCall(call, "publishableKey"); + boolean fraud = getBooleanFromMethodCall(call, "fraud", false); 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-beta.1"); editor.apply(); - Radar.initialize(mContext, publishableKey); + Radar.initialize(mContext, publishableKey, null, Radar.RadarLocationServicesProvider.GOOGLE, fraud); + Radar.setReceiver(new RadarFlutterReceiver(channel)); + Radar.setVerifiedReceiver(new RadarFlutterVerifiedReceiver(channel)); result.success(true); } private void setNotificationOptions(MethodCall call, Result result) { - HashMap notificationOptionsMap = (HashMap)call.arguments; + HashMap notificationOptionsMap = (HashMap) call.arguments; JSONObject notificationOptionsJson = new JSONObject(notificationOptionsMap); RadarNotificationOptions options = RadarNotificationOptions.fromJson(notificationOptionsJson); Radar.setNotificationOptions(options); @@ -339,15 +401,16 @@ private void setNotificationOptions(MethodCall call, Result result) { } private void setForegroundServiceOptions(MethodCall call, Result result) { - HashMap foregroundServiceOptionsMap = (HashMap)call.arguments; + HashMap foregroundServiceOptionsMap = (HashMap) call.arguments; JSONObject foregroundServiceOptionsJson = new JSONObject(foregroundServiceOptionsMap); - RadarTrackingOptionsForegroundService options = RadarTrackingOptionsForegroundService.fromJson(foregroundServiceOptionsJson); + RadarTrackingOptionsForegroundService options = RadarTrackingOptionsForegroundService + .fromJson(foregroundServiceOptionsJson); Radar.setForegroundServiceOptions(options); result.success(true); } private void setLogLevel(MethodCall call, Result result) { - String logLevel = call.argument("logLevel"); + String logLevel = getStringFromMethodCall(call, "logLevel"); if (logLevel == null) { Radar.setLogLevel(Radar.RadarLogLevel.NONE); } else if (logLevel.equals("debug")) { @@ -364,20 +427,21 @@ private void setLogLevel(MethodCall call, Result result) { result.success(true); } - private void getPermissionStatus(Result result) { String status = "NOT_DETERMINED"; - + if (mActivity == null || result == null) { result.success(status); return; } - boolean foreground = ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; + boolean foreground = ActivityCompat.checkSelfPermission(mActivity, + Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; if (Build.VERSION.SDK_INT >= 29) { if (foreground) { - boolean background = ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED; + boolean background = ActivityCompat.checkSelfPermission(mActivity, + Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED; status = background ? "GRANTED_BACKGROUND" : "GRANTED_FOREGROUND"; } else { status = "DENIED"; @@ -390,21 +454,27 @@ private void getPermissionStatus(Result result) { } private void requestPermissions(MethodCall call, Result result) { - boolean background = call.argument("background"); + boolean background = getBooleanFromMethodCall(call, "background", false); mPermissionsRequestResult = result; if (mActivity != null) { if (Build.VERSION.SDK_INT >= 23) { if (background && Build.VERSION.SDK_INT >= 29) { - ActivityCompat.requestPermissions(mActivity, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION }, PERMISSIONS_REQUEST_CODE); + ActivityCompat.requestPermissions(mActivity, + new String[] { Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_BACKGROUND_LOCATION }, + PERMISSIONS_REQUEST_CODE); } else { - ActivityCompat.requestPermissions(mActivity, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }, PERMISSIONS_REQUEST_CODE); + ActivityCompat.requestPermissions(mActivity, new String[] { + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }, + PERMISSIONS_REQUEST_CODE); } } } } private void setUserId(MethodCall call, Result result) { - String userId = call.argument("userId"); + String userId = getStringFromMethodCall(call, "userId"); Radar.setUserId(userId); result.success(true); } @@ -415,7 +485,7 @@ private void getUserId(Result result) { } private void setDescription(MethodCall call, Result result) { - String description = call.argument("description"); + String description = getStringFromMethodCall(call, "description"); Radar.setDescription(description); result.success(true); } @@ -426,7 +496,7 @@ private void getDescription(Result result) { } private void setMetadata(MethodCall call, Result result) { - HashMap metadataMap = (HashMap)call.arguments; + HashMap metadataMap = (HashMap) call.arguments; JSONObject metadata = new JSONObject(metadataMap); Radar.setMetadata(metadata); result.success(true); @@ -436,13 +506,13 @@ private void getMetadata(Result result) { JSONObject metadata = Radar.getMetadata(); HashMap metadataMap = null; if (metadata != null) { - metadataMap = new Gson().fromJson(metadata.toString(), HashMap.class); + metadataMap = new Gson().fromJson(metadata.toString(), HashMap.class); } result.success(metadataMap); } private void setAnonymousTrackingEnabled(MethodCall call, Result result) { - boolean enabled = call.argument("enabled"); + boolean enabled = getBooleanFromMethodCall(call, "enabled", false); Radar.setAnonymousTrackingEnabled(enabled); result.success(true); } @@ -472,7 +542,7 @@ public void run() { } }; - String accuracy = call.argument("accuracy"); + String accuracy = getStringFromMethodCall(call, "accuracy"); if (accuracy == null) { Radar.getLocation(callback); } else if (accuracy.equals("high")) { @@ -489,7 +559,8 @@ public void run() { private 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) { + public void onComplete(final Radar.RadarStatus status, final Location location, final RadarEvent[] events, + final RadarUser user) { runOnMainThread(new Runnable() { @Override public void run() { @@ -505,7 +576,7 @@ public void run() { if (user != null) { obj.put("user", user.toJson()); } - + HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); } catch (Exception e) { @@ -515,17 +586,17 @@ public void run() { }); } }; - - if (call.hasArgument("location") && call.argument("location") != null) { - HashMap locationMap = (HashMap)call.argument("location"); + + HashMap locationMap = getHashMapFromMethodCall(call, "location"); + if (locationMap != null) { Location location = locationForMap(locationMap); Radar.trackOnce(location, callback); } else { RadarTrackingOptions.RadarTrackingOptionsDesiredAccuracy accuracyLevel = RadarTrackingOptions.RadarTrackingOptionsDesiredAccuracy.MEDIUM; - boolean beaconsTrackingOption = false; - - if (call.hasArgument("desiredAccuracy") && call.argument("desiredAccuracy") != null) { - String desiredAccuracy = ((String)call.argument("desiredAccuracy")).toLowerCase(); + boolean beaconsTrackingOption = getBooleanFromMethodCall(call, "beacons", false); + String desiredAccuracy = (getStringFromMethodCall(call, "desiredAccuracy")); + if (desiredAccuracy != null){ + desiredAccuracy = desiredAccuracy.toLowerCase(); if (desiredAccuracy.equals("none")) { accuracyLevel = RadarTrackingOptions.RadarTrackingOptionsDesiredAccuracy.NONE; } else if (desiredAccuracy.equals("low")) { @@ -536,16 +607,13 @@ public void run() { accuracyLevel = RadarTrackingOptions.RadarTrackingOptionsDesiredAccuracy.HIGH; } } - if (call.hasArgument("beacons") && call.argument("beacons") != null) { - beaconsTrackingOption = call.argument("beacons"); - } - + Radar.trackOnce(accuracyLevel, beaconsTrackingOption, callback); } - } + } private void startTracking(MethodCall call, Result result) { - String preset = call.argument("preset"); + String preset = getStringFromMethodCall(call, "preset"); if (preset == null) { Radar.startTracking(RadarTrackingOptions.RESPONSIVE); } else if (preset.equals("continuous")) { @@ -561,7 +629,7 @@ private void startTracking(MethodCall call, Result result) { } private void startTrackingCustom(MethodCall call, Result result) { - HashMap optionsMap = (HashMap)call.arguments; + HashMap optionsMap = (HashMap) call.arguments; JSONObject optionsJson = new JSONObject(optionsMap); RadarTrackingOptions options = RadarTrackingOptions.fromJson(optionsJson); Radar.startTracking(options); @@ -569,34 +637,41 @@ private void startTrackingCustom(MethodCall call, Result result) { } private void startTrackingVerified(MethodCall call, Result result) { - Boolean token = call.hasArgument("token") ? call.argument("token") : false; - 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); + int interval = getIntFromMethodCall(call, "interval", 1); + Boolean beacons = getBooleanFromMethodCall(call, "beacons", false); + Radar.startTrackingVerified(interval, beacons); + result.success(true); + } + + private void stopTrackingVerified(MethodCall call, Result result) { + Radar.stopTrackingVerified(); result.success(true); } public void mockTracking(MethodCall call, final Result result) { - HashMap originMap = (HashMap)call.argument("origin"); + HashMap originMap = getHashMapFromMethodCall(call, "origin"); Location origin = locationForMap(originMap); - HashMap destinationMap = (HashMap)call.argument("destination"); + HashMap destinationMap = getHashMapFromMethodCall(call, "destination"); Location destination = locationForMap(destinationMap); - String modeStr = call.argument("mode"); + String modeStr = getStringFromMethodCall(call, "mode"); Radar.RadarRouteMode mode = Radar.RadarRouteMode.CAR; - if (modeStr.equals("FOOT") || modeStr.equals("foot")) { - mode = Radar.RadarRouteMode.FOOT; - } else if (modeStr.equals("BIKE") || modeStr.equals("bike")) { - mode = Radar.RadarRouteMode.BIKE; - } else if (modeStr.equals("CAR") || modeStr.equals("car")) { - mode = Radar.RadarRouteMode.CAR; + if (modeStr != null) { + if (modeStr.equals("FOOT") || modeStr.equals("foot")) { + mode = Radar.RadarRouteMode.FOOT; + } else if (modeStr.equals("BIKE") || modeStr.equals("bike")) { + mode = Radar.RadarRouteMode.BIKE; + } else if (modeStr.equals("CAR") || modeStr.equals("car")) { + mode = Radar.RadarRouteMode.CAR; + } } - int steps = call.hasArgument("steps") ? (int)call.argument("steps") : 10; - int interval = call.hasArgument("interval") ? (int)call.argument("interval") : 1; + + int steps = getIntFromMethodCall(call, "steps", 10); + int interval = getIntFromMethodCall(call, "interval", 1); Radar.mockTracking(origin, destination, mode, steps, interval, new Radar.RadarTrackCallback() { @Override public void onComplete(Radar.RadarStatus status, Location location, RadarEvent[] events, RadarUser user) { - + } }); } @@ -611,21 +686,21 @@ private void isTracking(Result result) { result.success(isTracking); } - private void getTrackingOptions(Result result) throws JSONException { - RadarTrackingOptions options = Radar.getTrackingOptions(); + private void getTrackingOptions(Result result) throws JSONException { + RadarTrackingOptions options = Radar.getTrackingOptions(); JSONObject optionsJson = options.toJson(); HashMap optionsMap = null; if (optionsJson != null) { - optionsMap = new Gson().fromJson(optionsJson.toString(), HashMap.class); + optionsMap = new Gson().fromJson(optionsJson.toString(), HashMap.class); } result.success(optionsMap); } public void startTrip(MethodCall call, Result result) throws JSONException { - HashMap tripOptionsMap = (HashMap)call.argument("tripOptions"); + HashMap tripOptionsMap = getHashMapFromMethodCall(call, "tripOptions"); JSONObject tripOptionsJson = jsonForMap(tripOptionsMap); RadarTripOptions tripOptions = RadarTripOptions.fromJson(tripOptionsJson); - HashMap trackingOptionsMap = (HashMap)call.argument("trackingOptions"); + HashMap trackingOptionsMap = getHashMapFromMethodCall(call, "trackingOptions"); JSONObject trackingOptionsJson = jsonForMap(trackingOptionsMap); RadarTrackingOptions trackingOptions = null; if (trackingOptionsJson != null) { @@ -634,8 +709,8 @@ public void startTrip(MethodCall call, Result result) throws JSONException { Radar.startTrip(tripOptions, trackingOptions, new Radar.RadarTripCallback() { @Override public void onComplete(@NonNull Radar.RadarStatus status, - @Nullable RadarTrip trip, - @Nullable RadarEvent[] events) { + @Nullable RadarTrip trip, + @Nullable RadarEvent[] events) { runOnMainThread(new Runnable() { @Override public void run() { @@ -661,29 +736,31 @@ public void run() { } public void updateTrip(MethodCall call, Result result) throws JSONException { - HashMap tripOptionsMap = (HashMap)call.argument("tripOptions"); + HashMap tripOptionsMap = getHashMapFromMethodCall(call, "tripOptions"); JSONObject tripOptionsJson = jsonForMap(tripOptionsMap); RadarTripOptions tripOptions = RadarTripOptions.fromJson(tripOptionsJson); - String statusStr = call.argument("status"); + String statusStr = getStringFromMethodCall(call, "status"); RadarTrip.RadarTripStatus status = RadarTrip.RadarTripStatus.UNKNOWN; - statusStr = statusStr.toLowerCase(); - if (statusStr.equals("started")) { - status = RadarTrip.RadarTripStatus.STARTED; - } else if (statusStr.equals("approaching")) { - status = RadarTrip.RadarTripStatus.APPROACHING; - } else if (statusStr.equals("arrived")) { - status = RadarTrip.RadarTripStatus.ARRIVED; - } else if (statusStr.equals("completed")) { - status = RadarTrip.RadarTripStatus.COMPLETED; - } else if (statusStr.equals("canceled")) { - status = RadarTrip.RadarTripStatus.CANCELED; + if (statusStr != null){ + statusStr = statusStr.toLowerCase(); + if (statusStr.equals("started")) { + status = RadarTrip.RadarTripStatus.STARTED; + } else if (statusStr.equals("approaching")) { + status = RadarTrip.RadarTripStatus.APPROACHING; + } else if (statusStr.equals("arrived")) { + status = RadarTrip.RadarTripStatus.ARRIVED; + } else if (statusStr.equals("completed")) { + status = RadarTrip.RadarTripStatus.COMPLETED; + } else if (statusStr.equals("canceled")) { + status = RadarTrip.RadarTripStatus.CANCELED; + } } - + Radar.updateTrip(tripOptions, status, new Radar.RadarTripCallback() { @Override public void onComplete(@NonNull Radar.RadarStatus status, - @Nullable RadarTrip trip, - @Nullable RadarEvent[] events) { + @Nullable RadarTrip trip, + @Nullable RadarEvent[] events) { runOnMainThread(new Runnable() { @Override public void run() { @@ -710,7 +787,7 @@ public void run() { public void getTripOptions(Result result) { RadarTripOptions tripOptions = Radar.getTripOptions(); - HashMap map = new Gson().fromJson(tripOptions.toJson().toString(), HashMap.class); + HashMap map = new Gson().fromJson(tripOptions.toJson().toString(), HashMap.class); result.success(map); } @@ -718,8 +795,8 @@ public void completeTrip(Result result) { Radar.completeTrip(new Radar.RadarTripCallback() { @Override public void onComplete(@NonNull Radar.RadarStatus status, - @Nullable RadarTrip trip, - @Nullable RadarEvent[] events) { + @Nullable RadarTrip trip, + @Nullable RadarEvent[] events) { runOnMainThread(new Runnable() { @Override public void run() { @@ -748,8 +825,8 @@ public void cancelTrip(Result result) { Radar.cancelTrip(new Radar.RadarTripCallback() { @Override public void onComplete(@NonNull Radar.RadarStatus status, - @Nullable RadarTrip trip, - @Nullable RadarEvent[] events) { + @Nullable RadarTrip trip, + @Nullable RadarEvent[] events) { runOnMainThread(new Runnable() { @Override public void run() { @@ -774,10 +851,24 @@ public void run() { }); } + public void acceptEvent(MethodCall call, Result result) { + String eventId = getStringFromMethodCall(call, "eventId"); + String verifiedPlaceId = getStringFromMethodCall(call, "verifiedPlaceId"); + Radar.acceptEvent(eventId, verifiedPlaceId); + result.success(true); + } + + public void rejectEvent(MethodCall call, Result result) { + String eventId = getStringFromMethodCall(call, "eventId"); + Radar.rejectEvent(eventId); + result.success(true); + } + public 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) { + public void onComplete(final Radar.RadarStatus status, final Location location, + final RadarContext context) { runOnMainThread(new Runnable() { @Override public void run() { @@ -800,9 +891,8 @@ public void run() { }); } }; - - if (call.hasArgument("location")) { - HashMap locationMap = (HashMap)call.argument("location"); + HashMap locationMap = getHashMapFromMethodCall(call, "location"); + if (locationMap != null) { Location location = locationForMap(locationMap); Radar.getContext(location, callback); } else { @@ -813,7 +903,8 @@ public void run() { private 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) { + public void onComplete(final Radar.RadarStatus status, final Location location, + final RadarGeofence[] geofences) { runOnMainThread(new Runnable() { @Override public void run() { @@ -838,21 +929,22 @@ public void run() { }; Location near = null; - if (call.hasArgument("near")) { - HashMap nearMap = (HashMap)call.argument("near"); + HashMap nearMap = getHashMapFromMethodCall(call, "near"); + if (nearMap != null) { near = locationForMap(nearMap); } - int radius = call.hasArgument("radius") ? (int)call.argument("radius") : 1000; - ArrayList tagsList = (ArrayList)call.argument("tags"); - String[] tags = (String[])tagsList.toArray(new String[0]); - HashMap metadataMap = (HashMap)call.argument("metadata"); + int radius = getIntFromMethodCall(call, "radius", 1000); + + String[] tags = getStringArrayFromMethodCall(call, "tags"); + HashMap metadataMap = getHashMapFromMethodCall(call, "metadata"); JSONObject metadata = jsonForMap(metadataMap); - int limit = call.hasArgument("limit") ? (int)call.argument("limit") : 10; + int limit = getIntFromMethodCall(call, "limit", 10); + boolean includeGeometry = getBooleanFromMethodCall(call, "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); } } @@ -884,19 +976,16 @@ public void run() { }; Location near = null; - if (call.hasArgument("near")) { - HashMap nearMap = (HashMap)call.argument("near"); + HashMap nearMap = getHashMapFromMethodCall(call, "near"); + if (nearMap != null) { near = locationForMap(nearMap); } - int radius = call.hasArgument("radius") ? (int)call.argument("radius") : 1000; - ArrayList chainsList = (ArrayList)call.argument("chains"); - String[] chains = (String[])chainsList.toArray(new String[0]); - Map chainMetadata = (Map)call.argument("chainMetadata"); - ArrayList categoriesList = (ArrayList)call.argument("categories"); - String[] categories = categoriesList != null ? (String[])categoriesList.toArray(new String[0]) : new String[0]; - ArrayList groupsList = (ArrayList)call.argument("groups"); - String[] groups = groupsList != null ? (String[])groupsList.toArray(new String[0]) : new String[0]; - int limit = call.hasArgument("limit") ? (int)call.argument("limit") : 10; + int radius = getIntFromMethodCall(call, "radius", 1000); + String[] chains = getStringArrayFromMethodCall(call, "chains"); + Map chainMetadata = (Map) call.argument("chainMetadata"); + String[] categories = getStringArrayFromMethodCall(call, "categories"); + String[] groups = getStringArrayFromMethodCall(call, "groups"); + int limit = getIntFromMethodCall(call, "limit", 10); if (near != null) { Radar.searchPlaces(near, radius, chains, chainMetadata, categories, groups, limit, callback); @@ -906,14 +995,13 @@ public void run() { } public void autocomplete(MethodCall call, final Result result) { - String query = call.argument("query"); - HashMap nearMap = (HashMap)call.argument("near"); + String query = getStringFromMethodCall(call, "query"); + HashMap nearMap = getHashMapFromMethodCall(call, "near"); Location near = locationForMap(nearMap); - int limit = call.hasArgument("limit") ? (int)call.argument("limit") : 10; - String country = call.argument("country"); - ArrayList layersList = (ArrayList)call.argument("layers"); - String[] layers = layersList != null ? (String[])layersList.toArray(new String[0]) : new String[0]; - Boolean mailable = call.argument("mailable"); + int limit = getIntFromMethodCall(call, "limit", 10); + String country = getStringFromMethodCall(call, "country"); + String[] layers = getStringArrayFromMethodCall(call, "layers"); + Boolean mailable = getBooleanFromMethodCall(call, "mailable", false); Radar.autocomplete(query, near, layers, limit, country, true, mailable, new Radar.RadarGeocodeCallback() { @Override @@ -940,9 +1028,9 @@ public void run() { } public void geocode(MethodCall call, final Result result) { - String query = call.argument("query"); + String query = getStringFromMethodCall(call, "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() { @@ -954,7 +1042,7 @@ public void run() { if (addresses != null) { obj.put("addresses", RadarAddress.toJson(addresses)); } - + HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); } catch (Exception e) { @@ -990,12 +1078,13 @@ public void run() { } }; - if (call.hasArgument("location")) { - HashMap locationMap = (HashMap)call.argument("location"); + String[] layers = getStringArrayFromMethodCall(call, "layers"); + HashMap locationMap = getHashMapFromMethodCall(call, "location"); + if (locationMap != null) { Location location = locationForMap(locationMap); - Radar.reverseGeocode(location, callback); + Radar.reverseGeocode(location, layers, callback); } else { - Radar.reverseGeocode(callback); + Radar.reverseGeocode(layers, callback); } } @@ -1050,15 +1139,14 @@ public void run() { }; Location origin = null; - if (call.hasArgument("origin")) { - HashMap originMap = (HashMap)call.argument("origin"); + HashMap originMap = getHashMapFromMethodCall(call, "origin"); + if (originMap != null) { origin = locationForMap(originMap); } - HashMap destinationMap = (HashMap)call.argument("destination"); + HashMap destinationMap = getHashMapFromMethodCall(call, "destination"); Location destination = locationForMap(destinationMap); EnumSet modes = EnumSet.noneOf(Radar.RadarRouteMode.class); - ArrayList modesList = call.argument("modes"); - String[] modesArr = (String[])(new String[0]); + String[] modesArr = getStringArrayFromMethodCall(call, "modes"); for (String modeStr : modesArr) { if (modeStr.equals("FOOT") || modeStr.equals("foot")) { modes.add(Radar.RadarRouteMode.FOOT); @@ -1070,8 +1158,10 @@ public void run() { modes.add(Radar.RadarRouteMode.CAR); } } - String unitsStr = call.argument("units"); - Radar.RadarRouteUnits units = unitsStr.equals("METRIC") || unitsStr.equals("metric") ? Radar.RadarRouteUnits.METRIC : Radar.RadarRouteUnits.IMPERIAL; + String unitsStr = getStringFromMethodCall(call, "units"); + Radar.RadarRouteUnits units = unitsStr.equals("METRIC") || unitsStr.equals("metric") + ? Radar.RadarRouteUnits.METRIC + : Radar.RadarRouteUnits.IMPERIAL; if (origin != null) { Radar.getDistance(origin, destination, modes, units, callback); @@ -1080,7 +1170,7 @@ public void run() { } } - public void logConversion(MethodCall call, final Result result) throws JSONException { + public 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) { @@ -1093,7 +1183,7 @@ public void run() { if (event != null) { obj.put("event", event.toJson()); } - + HashMap map = new Gson().fromJson(obj.toString(), HashMap.class); result.success(map); } catch (Exception e) { @@ -1104,11 +1194,14 @@ public void run() { } }; - String name = call.argument("name"); - HashMap metadataMap= call.argument("metadata"); - JSONObject metadataJson = jsonForMap(metadataMap); + String name = getStringFromMethodCall(call, "name"); + JSONObject metadataJson = null; + HashMap metadataMap = getHashMapFromMethodCall(call, "metadata"); + if (metadataMap == null) { + metadataJson = jsonForMap(metadataMap); + } if (call.hasArgument("revenue") && call.argument("revenue") != null) { - double revenue = (Double)call.argument("revenue"); + double revenue = (Double) call.argument("revenue"); Radar.logConversion(name, revenue, metadataJson, callback); } else { Radar.logConversion(name, metadataJson, callback); @@ -1126,7 +1219,7 @@ public void logResigningActive(Result result) { } public void getMatrix(MethodCall call, final Result result) throws JSONException { - ArrayList originsArr = call.argument("origins"); + ArrayList originsArr = call.argument("origins"); Location[] origins = new Location[originsArr.size()]; for (int i = 0; i < originsArr.size(); i++) { origins[i] = locationForMap(originsArr.get(i)); @@ -1136,11 +1229,11 @@ public void getMatrix(MethodCall call, final Result result) throws JSONException for (int i = 0; i < destinationsArr.size(); i++) { destinations[i] = locationForMap(destinationsArr.get(i)); } - String modeStr = call.argument("mode"); + String modeStr = getStringFromMethodCall(call, "mode"); Radar.RadarRouteMode mode = Radar.RadarRouteMode.CAR; if (modeStr != null) { modeStr = modeStr.toLowerCase(); - if ( modeStr.equals("foot")) { + if (modeStr.equals("foot")) { mode = Radar.RadarRouteMode.FOOT; } else if (modeStr.equals("bike")) { mode = Radar.RadarRouteMode.BIKE; @@ -1152,8 +1245,10 @@ public void getMatrix(MethodCall call, final Result result) throws JSONException mode = Radar.RadarRouteMode.MOTORBIKE; } } - String unitsStr = call.argument("units"); - Radar.RadarRouteUnits units = unitsStr != null && unitsStr.toLowerCase().equals("metric") ? Radar.RadarRouteUnits.METRIC : Radar.RadarRouteUnits.IMPERIAL; + String unitsStr = getStringFromMethodCall(call, "units"); + Radar.RadarRouteUnits units = unitsStr != null && unitsStr.toLowerCase().equals("metric") + ? Radar.RadarRouteUnits.METRIC + : Radar.RadarRouteUnits.IMPERIAL; Radar.getMatrix(origins, destinations, mode, units, new Radar.RadarMatrixCallback() { @Override @@ -1180,24 +1275,18 @@ public void run() { } public void trackVerified(MethodCall call, final Result result) { - Boolean beacons = call.hasArgument("beacons") ? call.argument("beacons") : false; + Boolean beacons = getBooleanFromMethodCall(call, "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,33 +1301,6 @@ 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) { Boolean isRemoteTracking = Radar.isUsingRemoteTrackingOptions(); result.success(isRemoteTracking); @@ -1247,7 +1309,8 @@ private void isUsingRemoteTrackingOptions(Result result) { public 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) { + public void onComplete(final Radar.RadarStatus status, final RadarAddress address, + final Radar.RadarAddressVerificationStatus verificationStatus) { runOnMainThread(new Runnable() { @Override public void run() { @@ -1271,21 +1334,21 @@ public void run() { } }; - HashMap addressMap= call.argument("address"); + HashMap addressMap = getHashMapFromMethodCall(call, "address"); JSONObject addressJSON = jsonForMap(addressMap); RadarAddress address = RadarAddress.fromJson(addressJSON); Radar.validateAddress(address, callback); } private Location locationForMap(HashMap locationMap) { - double latitude = (Double)locationMap.get("latitude"); - double longitude = (Double)locationMap.get("longitude"); + double latitude = (Double) locationMap.get("latitude"); + double longitude = (Double) locationMap.get("longitude"); Location location = new Location("RadarSDK"); location.setLatitude(latitude); location.setLongitude(longitude); if (locationMap.containsKey("accuracy")) { - double accuracyDouble = (Double)locationMap.get("accuracy"); - float accuracy = (float)accuracyDouble; + double accuracyDouble = (Double) locationMap.get("accuracy"); + float accuracy = (float) accuracyDouble; location.setAccuracy(accuracy); } return location; @@ -1307,31 +1370,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 +1399,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); } }); } @@ -1374,31 +1425,23 @@ public void run() { } } - public void onClientLocationUpdated(Context context, Location location, boolean stopped, Radar.RadarLocationSource source) { + 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); } }); } @@ -1406,31 +1449,22 @@ public void run() { Log.e(TAG, e.toString()); } } - + @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); } }); } @@ -1438,31 +1472,22 @@ public void run() { Log.e(TAG, e.toString()); } } - + @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,72 +1495,39 @@ 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()); } } } - - 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..de1d35c 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -4,8 +4,6 @@ import 'package:flutter_radar/flutter_radar.dart'; void main() => runApp(MyApp()); - - class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); @@ -68,14 +66,13 @@ class _MyAppState extends State with WidgetsBindingObserver { } Future initRadar() async { - Radar.initialize('prj_test_pk_0000000000000000000000000000000000000000'); - Radar.setUserId('flutter'); - Radar.setDescription('Flutter'); - Radar.setMetadata({'foo': 'bar', 'bax': true, 'qux': 1}); - Radar.setLogLevel('info'); - Radar.setAnonymousTrackingEnabled(false); - - Radar.attachListeners(); + Radar.initialize( + publishableKey: 'prj_test_pk_0000000000000000000000000000000000000000'); + Radar.setUserId(userId: 'flutter'); + Radar.setDescription(description: 'Flutter'); + Radar.setMetadata(metadata: {'foo': 'bar', 'bax': true, 'qux': 1}); + Radar.setLogLevel(logLevel: 'info'); + Radar.setAnonymousTrackingEnabled(enabled: false); Radar.onLocation(onLocation); Radar.onClientLocation(onClientLocation); @@ -84,13 +81,13 @@ class _MyAppState extends State with WidgetsBindingObserver { Radar.onLog(onLog); Radar.onToken(onToken); - await Radar.requestPermissions(false); - - await Radar.requestPermissions(true); + await Radar.requestPermissions(background: false); + + await Radar.requestPermissions(background: true); var permissionStatus = await Radar.getPermissionsStatus(); if (permissionStatus != "DENIED") { - var b = await Radar.startTrackingCustom({ - ... Radar.presetResponsive, + var b = await Radar.startTrackingCustom(options: { + ...Radar.presetResponsive, "showBlueBar": true, }); //Radar.startTracking('continuous'); @@ -102,316 +99,383 @@ class _MyAppState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { - return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('flutter_radar_example'), ), body: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Container( - child: Column(children: [ - Permissions(), - TrackOnce(), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var status = await Radar.requestPermissions(false); - print(status); - if (status == 'GRANTED_FOREGROUND') { - status = await Radar.requestPermissions(true); + scrollDirection: Axis.vertical, + child: Container( + child: Column(children: [ + Permissions(), + TrackOnce(), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var status = + await Radar.requestPermissions(background: false); print(status); - } - }, - child: Text('requestPermissions()'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - Radar.setForegroundServiceOptions({ - 'title': 'Tracking', - 'text': 'Trip tracking started', - 'icon': 2131165271, - 'importance': 2, - 'updatesOnly': false, - 'activity': 'io.radar.example.MainActivity' - }); - var resp = await Radar.startTrip( - tripOptions: { + if (status == 'GRANTED_FOREGROUND') { + status = await Radar.requestPermissions(background: true); + print(status); + } + }, + child: Text('requestPermissions()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + Radar.setForegroundServiceOptions(foregroundServiceOptions: { + 'title': 'Tracking', + 'text': 'Trip tracking started', + 'icon': 2131165271, + 'importance': 2, + 'updatesOnly': false, + 'activity': 'io.radar.example.MainActivity' + }); + var resp = await Radar.startTrip(tripOptions: { "externalId": '299', "destinationGeofenceTag": 'store', "destinationGeofenceExternalId": '123', "mode": 'car', "scheduledArrivalAt": "2020-08-20T10:30:55.837Z", "metadata": {"test": 123} - }, - trackingOptions: { - "desiredStoppedUpdateInterval": 30, - "fastestStoppedUpdateInterval": 30, - "desiredMovingUpdateInterval": 30, - "fastestMovingUpdateInterval": 30, - "desiredSyncInterval": 20, - "desiredAccuracy": "high", - "stopDuration": 0, - "stopDistance": 0, - "replay": "none", - "sync": "all", - "showBlueBar": true, - "useStoppedGeofence": false, - "stoppedGeofenceRadius": 0, - "useMovingGeofence": false, - "movingGeofenceRadius": 0, - "syncGeofences": false, - "syncGeofencesLimit": 0, - "beacons": false, - "foregroundServiceEnabled": true - } - ); - print("startTrip: $resp"); - }, - child: Text('startTrip'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var resp = await Radar.completeTrip(); - print("completeTrip: $resp"); - }, - child: Text('completeTrip'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var resp = await Radar.cancelTrip(); - print("cancelTrip: $resp"); - }, - child: Text('cancelTrip'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var resp = await Radar.getTrackingOptions(); - print("getTrackingOptions: $resp"); - }, - child: Text('getTrackingOptions'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var resp = await Radar.updateTrip( - status:'arrived', - options: { + }, trackingOptions: { + "desiredStoppedUpdateInterval": 30, + "fastestStoppedUpdateInterval": 30, + "desiredMovingUpdateInterval": 30, + "fastestMovingUpdateInterval": 30, + "desiredSyncInterval": 20, + "desiredAccuracy": "high", + "stopDuration": 0, + "stopDistance": 0, + "replay": "none", + "sync": "all", + "showBlueBar": true, + "useStoppedGeofence": false, + "stoppedGeofenceRadius": 0, + "useMovingGeofence": false, + "movingGeofenceRadius": 0, + "syncGeofences": false, + "syncGeofencesLimit": 0, + "beacons": false, + "foregroundServiceEnabled": true + }); + print("startTrip: $resp"); + }, + child: Text('startTrip'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.completeTrip(); + print("completeTrip: $resp"); + }, + child: Text('completeTrip'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.cancelTrip(); + print("cancelTrip: $resp"); + }, + child: Text('cancelTrip'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.getTrackingOptions(); + print("getTrackingOptions: $resp"); + }, + child: Text('getTrackingOptions'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = + await Radar.updateTrip(status: 'arrived', options: { "externalId": '299', - "metadata": { - "parkingSpot": '5' - } - } - ); - print("updateTrip: $resp"); - }, - child: Text('updateTrip'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var resp = await Radar.logConversion( - name: "in_app_purchase", - revenue: 0.2, - metadata: {"price": "150USD"}); - print("logConversion: $resp"); - }, - child: Text('logConversion'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - await Radar.setNotificationOptions({ - 'iconString': 'icon' - }); - }, - child: Text('setNotificationOptions'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var resp = await Radar.searchPlaces( - near: { - 'latitude': 40.783826, - 'longitude': -73.975363, - }, - radius: 1000, - chains: ["starbucks"], - chainMetadata: { - "customFlag": "true" - }, - limit: 10, - ); - print("searchPlaces: $resp"); - }, - child: Text('searchPlaces'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var resp = await Radar.autocomplete( - query: 'brooklyn roasting', - near: { - 'latitude': 40.783826, - 'longitude': -73.975363, - }, - limit: 10, - layers: ['address', 'street'], - country: 'US', - mailable: false - ); - print("autocomplete: $resp"); - }, - child: Text('autocomplete'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - var resp = await Radar.getMatrix( - origins: [ - { - 'latitude': 40.78382, - 'longitude': -73.97536, - }, - { - 'latitude': 40.70390, - 'longitude': -73.98670, + "metadata": {"parkingSpot": '5'} + }); + print("updateTrip: $resp"); + }, + child: Text('updateTrip'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.logConversion( + name: "in_app_purchase", + revenue: 0.2, + metadata: {"price": "150USD"}); + print("logConversion: $resp"); + }, + child: Text('logConversion'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + await Radar.setNotificationOptions( + notificationOptions: {'iconString': 'icon'}); + }, + child: Text('setNotificationOptions'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.searchPlaces( + radius: 1000, + limit: 10, + near: { + 'latitude': 40.783826, + 'longitude': -73.975363, }, - ], - destinations: [ - { - 'latitude': 40.64189, - 'longitude': -73.78779, + chains: ["starbucks"], + chainMetadata: {"customFlag": "true"}, + ); + print("searchPlaces: $resp"); + }, + child: Text('searchPlaces()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.searchGeofences( + near: { + 'latitude': 40.783826, + 'longitude': -73.975363, }, - { - 'latitude': 35.99801, - 'longitude': -78.94294, - }, - ], - mode: 'car', - units: 'imperial', - ); - print("getMatrix: $resp"); - }, - child: Text('getMatrix'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () { - Radar.startTracking('responsive'); - }, - child: Text('startTracking(\'responsive\')'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () { - - Radar.setForegroundServiceOptions({ - 'title': 'Tracking', - 'text': 'Continuous tracking started', - 'icon': 2131165271, - 'importance': 2, - 'updatesOnly': false, - 'activity': 'io.radar.example.MainActivity' - }); - Radar.startTrackingCustom({ - 'desiredStoppedUpdateInterval': 120, - 'fastestStoppedUpdateInterval': 120, - 'desiredMovingUpdateInterval': 30, - 'fastestMovingUpdateInterval': 30, - 'desiredSyncInterval': 20, - 'desiredAccuracy': 'high', - 'stopDuration': 140, - 'stopDistance': 70, - 'sync': 'all', - 'replay': 'none', - 'showBlueBar': true, - 'foregroundServiceEnabled': true - }); - }, - child: Text('startTrackingCustom()'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () { - Radar.startTrackingVerified(token: true); - }, - child: Text('startTrackingVerified(token: true)'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () { - Radar.stopTracking(); - }, - child: Text('stopTracking()'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () { - Radar.mockTracking( - origin: {'latitude': 40.78382, 'longitude': -73.97536}, - destination: {'latitude': 40.70390, 'longitude': -73.98670}, + 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( + query: '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, + onPressed: () async { + var resp = await Radar.autocomplete( + query: 'brooklyn roasting', + limit: 10, + near: { + 'latitude': 40.783826, + 'longitude': -73.975363, + }, + layers: ['address', 'street'], + country: 'US', + mailable: false); + print("autocomplete: $resp"); + }, + child: Text('autocomplete'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + var resp = await Radar.getMatrix( + origins: [ + { + 'latitude': 40.78382, + 'longitude': -73.97536, + }, + { + 'latitude': 40.70390, + 'longitude': -73.98670, + }, + ], + destinations: [ + { + 'latitude': 40.64189, + 'longitude': -73.78779, + }, + { + 'latitude': 35.99801, + 'longitude': -78.94294, + }, + ], mode: 'car', - steps: 3, - interval: 3); - }, - child: Text('mockTracking()'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - Map? location = await Radar.getLocation('high'); - print(location); - }, - child: Text('getLocation()'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - 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'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - bool? resp = await Radar.isUsingRemoteTrackingOptions(); - print("isUsingRemoteTrackingOptions: $resp"); - }, - child: Text('isUsingRemoteTrackingOptions'), - ), - ElevatedButton( - style: raisedButtonStyle, - onPressed: () async { - Map? resp = await Radar.validateAddress({ - "city": "NEW YORK", - "stateCode": "NY", - "postalCode": "10003", - "countryCode": "US", - "street": "BROADWAY", - "number": "841", - }); - print("validateAddress: $resp"); - }, - child: Text('validateAddress'), - ), - ]), - ) - ), + units: 'imperial', + ); + print("getMatrix: $resp"); + }, + child: Text('getMatrix'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () { + Radar.startTracking(preset: 'responsive'); + }, + child: Text('startTracking(\'responsive\')'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () { + Radar.setForegroundServiceOptions(foregroundServiceOptions: { + 'title': 'Tracking', + 'text': 'Continuous tracking started', + 'icon': 2131165271, + 'importance': 2, + 'updatesOnly': false, + 'activity': 'io.radar.example.MainActivity' + }); + Radar.startTrackingCustom(options: { + 'desiredStoppedUpdateInterval': 120, + 'fastestStoppedUpdateInterval': 120, + 'desiredMovingUpdateInterval': 30, + 'fastestMovingUpdateInterval': 30, + 'desiredSyncInterval': 20, + 'desiredAccuracy': 'high', + 'stopDuration': 140, + 'stopDistance': 70, + 'sync': 'all', + 'replay': 'none', + 'showBlueBar': true, + 'foregroundServiceEnabled': true + }); + }, + child: Text('startTrackingCustom()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () { + Radar.startTrackingVerified(interval: 30, beacons: false); + }, + child: Text('startTrackingVerified()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () { + Radar.stopTrackingVerified(); + }, + child: Text('stopTrackingVerified()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () { + Radar.stopTracking(); + }, + child: Text('stopTracking()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () { + Radar.mockTracking(origin: { + 'latitude': 40.78382, + 'longitude': -73.97536 + }, destination: { + 'latitude': 40.70390, + 'longitude': -73.98670 + }, mode: 'car', steps: 3, interval: 3); + }, + child: Text('mockTracking()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + Map? location = await Radar.getLocation(accuracy: 'high'); + print(location); + }, + child: Text('getLocation()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + Map? resp = await Radar.trackVerified(); + print("trackVerified: $resp"); + }, + child: Text('trackVerified()'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + bool? resp = await Radar.isUsingRemoteTrackingOptions(); + print("isUsingRemoteTrackingOptions: $resp"); + }, + child: Text('isUsingRemoteTrackingOptions'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + Map? resp = await Radar.validateAddress(address:{ + "city": "NEW YORK", + "stateCode": "NY", + "postalCode": "10003", + "countryCode": "US", + "street": "BROADWAY", + "number": "841", + }); + print("validateAddress: $resp"); + }, + child: Text('validateAddress'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + await Radar.acceptEvent( + eventId: 'event-id', + VerifiedPlaceId: 'verified-place-id'); + ; + print("accept event"); + }, + child: Text('acceptEvent'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + await Radar.rejectEvent(eventId: 'event-id'); + ; + print("reject event"); + }, + child: Text('rejectEvent'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + Map? res = await Radar.getContext( + location: {'latitude': 40.78382, 'longitude': -73.97536}); + ; + print("getContext: $res"); + }, + child: Text('getContext'), + ), + ElevatedButton( + style: raisedButtonStyle, + onPressed: () async { + Map? res = await Radar.getDistance(destination: { + 'latitude': 40.78382, + 'longitude': -73.97536 + }, modes: [ + 'car' + ], units: 'imperial'); + ; + print("getDistance: $res"); + }, + child: Text('getDistance'), + ), + ]), + )), )); } } @@ -462,6 +526,7 @@ class _PermissionsState extends State { setState(() { _status = status; }); + print('Permissions status: $status'); } } diff --git a/ios/Classes/RadarFlutterPlugin.m b/ios/Classes/RadarFlutterPlugin.m index 487b8fe..51c71a1 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]) { @@ -92,6 +94,10 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { [self completeTrip:call withResult:result]; } else if ([@"cancelTrip" isEqualToString:call.method]) { [self cancelTrip:call withResult:result]; + } else if ([@"acceptEvent" isEqualToString:call.method]) { + [self acceptEvent:call withResult:result]; + } else if ([@"rejectEvent" isEqualToString:call.method]) { + [self rejectEvent:call withResult:result]; } else if ([@"getContext" isEqualToString:call.method]) { [self getContext:call withResult:result]; } else if ([@"searchGeofences" isEqualToString:call.method]) { @@ -124,31 +130,67 @@ - (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); } } +- (NSString *)getStringValueForKey:(NSDictionary *)dictionary key:(NSString *)key { + id value = [dictionary objectForKey:key]; + + if (value && [value isKindOfClass:[NSString class]]) { + return (NSString *)value; + } + + return nil; +} + +- (BOOL)getBoolValueForKey:(NSDictionary *)dictionary key:(NSString *)key defaultValue:(BOOL)defaultValue { + id value = [dictionary objectForKey:key]; + if (value && [value isKindOfClass:[NSNumber class]]) { + return [(NSNumber *)value boolValue]; + } + + return defaultValue; +} + +- (NSDictionary *)getDictionaryValueForKey:(NSDictionary *)dictionary key:(NSString *)key { + id value = [dictionary objectForKey:key]; + if (value && [value isKindOfClass:[NSDictionary class]]) { + return (NSDictionary *)value; + } + + return nil; +} + +- (NSArray *)getArrayValueForKey:(NSDictionary *)dictionary key:(NSString *)key { + id value = [dictionary objectForKey:key]; + if (value && [value isKindOfClass:[NSArray class]]) { + return (NSArray *)value; + } + + return nil; +} + +- (int)getIntegerValueForKey:(NSDictionary *)dictionary key:(NSString *)key defaultValue:(int)defaultValue { + id value = [dictionary objectForKey:key]; + if (value && [value isKindOfClass:[NSNumber class]]) { + return [(NSNumber *)value intValue]; + } + + return defaultValue; +} + - (void)initialize:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSString *publishableKey = argsDict[@"publishableKey"]; + NSString *publishableKey = [self getStringValueForKey:argsDict key:@"publishableKey"]; [[NSUserDefaults standardUserDefaults] setObject:@"Flutter" forKey:@"radar-xPlatformSDKType"]; - [[NSUserDefaults standardUserDefaults] setObject:@"3.9.1" forKey:@"radar-xPlatformSDKVersion"]; + [[NSUserDefaults standardUserDefaults] setObject:@"3.10.0-beta.1" forKey:@"radar-xPlatformSDKVersion"]; [Radar initializeWithPublishableKey:publishableKey]; result(nil); } @@ -156,7 +198,7 @@ - (void)initialize:(FlutterMethodCall *)call withResult:(FlutterResult)result { - (void)setLogLevel:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSString *logLevel = argsDict[@"logLevel"]; + NSString *logLevel = [self getStringValueForKey:argsDict key:@"logLevel"]; if (!logLevel) { [Radar setLogLevel:RadarLogLevelNone]; } else if ([logLevel isEqualToString:@"debug"]) { @@ -207,9 +249,8 @@ - (void)requestPermissions:(FlutterMethodCall *)call withResult:(FlutterResult)r self.permissionsRequestResult = result; NSDictionary *argsDict = call.arguments; + BOOL background = [self getBoolValueForKey:argsDict key:@"background" defaultValue:NO]; - NSNumber *backgroundNumber = argsDict[@"background"]; - BOOL background = [backgroundNumber boolValue]; CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; if (background && status == kCLAuthorizationStatusAuthorizedWhenInUse) { [self.locationManager requestAlwaysAuthorization]; @@ -223,7 +264,7 @@ - (void)requestPermissions:(FlutterMethodCall *)call withResult:(FlutterResult)r - (void)setUserId:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSString *userId = argsDict[@"userId"]; + NSString *userId = [self getStringValueForKey:argsDict key:@"userId"]; [Radar setUserId:userId]; result(nil); } @@ -236,7 +277,7 @@ - (void)getUserId:(FlutterMethodCall *)call withResult:(FlutterResult)result { - (void)setDescription:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSString *description = argsDict[@"description"]; + NSString *description = [self getStringValueForKey:argsDict key:@"description"]; [Radar setDescription:description]; result(nil); } @@ -260,8 +301,7 @@ - (void)getMetadata:(FlutterMethodCall *)call withResult:(FlutterResult)result { - (void)setAnonymousTrackingEnabled:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSNumber* enabledNumber = argsDict[@"enabled"]; - BOOL enabled = [enabledNumber boolValue]; + BOOL enabled = [self getBoolValueForKey:argsDict key:@"enabled" defaultValue:NO]; [Radar setAnonymousTrackingEnabled:enabled]; result(nil); } @@ -280,7 +320,7 @@ - (void)getLocation:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSString *accuracy = argsDict[@"accuracy"]; + NSString *accuracy = [self getStringValueForKey:argsDict key:@"accuracy"]; if (!accuracy) { [Radar getLocationWithCompletionHandler:completionHandler]; } else if ([accuracy isEqualToString:@"high"]) { @@ -314,8 +354,8 @@ - (void)trackOnce:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSDictionary *locationDict = argsDict[@"location"]; - if (locationDict != nil && [locationDict isKindOfClass:[NSDictionary class]]) { + NSDictionary *locationDict = [self getDictionaryValueForKey:argsDict key:@"location"]; + if (locationDict != nil) { NSNumber *latitudeNumber = locationDict[@"latitude"]; NSNumber *longitudeNumber = locationDict[@"longitude"]; NSNumber *accuracyNumber = locationDict[@"accuracy"]; @@ -326,11 +366,11 @@ - (void)trackOnce:(FlutterMethodCall *)call withResult:(FlutterResult)result { [Radar trackOnceWithLocation:location completionHandler:completionHandler]; } else { RadarTrackingOptionsDesiredAccuracy desiredAccuracy = RadarTrackingOptionsDesiredAccuracyMedium; - BOOL beaconsTrackingOption = NO; + BOOL beaconsTrackingOption = [self getBoolValueForKey:argsDict key:@"beacons" defaultValue:NO]; - NSString *accuracy = argsDict[@"desiredAccuracy"]; + NSString *accuracy =[self getStringValueForKey:argsDict key:@"desiredAccuracy"]; - if (accuracy != nil && [accuracy isKindOfClass:[NSString class]]) { + if (accuracy != nil) { NSString *lowerAccuracy = [accuracy lowercaseString]; if ([lowerAccuracy isEqualToString:@"high"]) { desiredAccuracy = RadarTrackingOptionsDesiredAccuracyHigh; @@ -340,13 +380,7 @@ - (void)trackOnce:(FlutterMethodCall *)call withResult:(FlutterResult)result { desiredAccuracy = RadarTrackingOptionsDesiredAccuracyLow; } } - - BOOL beacons = argsDict[@"beacons"]; - - if (beacons) { - beaconsTrackingOption = beacons; - } - + [Radar trackOnceWithDesiredAccuracy:desiredAccuracy beacons:beaconsTrackingOption completionHandler:completionHandler]; } } @@ -354,7 +388,7 @@ - (void)trackOnce:(FlutterMethodCall *)call withResult:(FlutterResult)result { - (void)startTracking:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSString *preset = argsDict[@"preset"]; + NSString *preset = [self getStringValueForKey:argsDict key:@"preset"]; if (!preset) { [Radar startTrackingWithOptions:RadarTrackingOptions.presetResponsive]; } else if ([preset isEqualToString:@"continuous"]) { @@ -379,25 +413,16 @@ - (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 = [self getBoolValueForKey:argsDict key:@"beacons" defaultValue:NO]; - BOOL beacons = NO; - NSNumber *beaconsNumber = argsDict[@"beacons"]; - if (beaconsNumber != nil && [beaconsNumber isKindOfClass:[NSNumber class]]) { - beacons = [beaconsNumber boolValue]; - } + double interval = [argsDict[@"interval"] doubleValue]; - double interval = 1; - NSNumber *intervalNumber = argsDict[@"interval"]; - if (intervalNumber != nil && [intervalNumber isKindOfClass:[NSNumber class]]) { - interval = [intervalNumber doubleValue]; - } + [Radar startTrackingVerifiedWithInterval:interval beacons:beacons]; + result(nil); +} - [Radar startTrackingVerified:token interval:interval beacons:beacons]; +- (void)stopTrackingVerified:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Radar stopTrackingVerified]; result(nil); } @@ -424,19 +449,25 @@ - (void)getTrackingOptions:(FlutterMethodCall *)call withResult:(FlutterResult)r - (void)mockTracking:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSDictionary *originDict = argsDict[@"origin"]; + NSDictionary *originDict = [self getDictionaryValueForKey:argsDict key:@"origin"]; + NSDictionary *destinationDict = [self getDictionaryValueForKey:argsDict key:@"destination"]; + if (!originDict || !destinationDict) { + result(nil); + return; + } NSNumber *originLatitudeNumber = originDict[@"latitude"]; NSNumber *originLongitudeNumber = originDict[@"longitude"]; double originLatitude = [originLatitudeNumber doubleValue]; double originLongitude = [originLongitudeNumber doubleValue]; CLLocation *origin = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(originLatitude, originLongitude) altitude:-1 horizontalAccuracy:5 verticalAccuracy:-1 timestamp:[NSDate date]]; - NSDictionary *destinationDict = argsDict[@"destination"]; + NSNumber *destinationLatitudeNumber = destinationDict[@"latitude"]; NSNumber *destinationLongitudeNumber = destinationDict[@"longitude"]; double destinationLatitude = [destinationLatitudeNumber doubleValue]; double destinationLongitude = [destinationLongitudeNumber doubleValue]; CLLocation *destination = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(destinationLatitude, destinationLongitude) altitude:-1 horizontalAccuracy:5 verticalAccuracy:-1 timestamp:[NSDate date]]; - NSString *modeStr = argsDict[@"mode"]; + + NSString *modeStr = [self getStringValueForKey:argsDict key:@"mode"]; RadarRouteMode mode = RadarRouteModeCar; if ([modeStr isEqualToString:@"FOOT"] || [modeStr isEqualToString:@"foot"]) { mode = RadarRouteModeFoot; @@ -445,20 +476,8 @@ - (void)mockTracking:(FlutterMethodCall *)call withResult:(FlutterResult)result } else if ([modeStr isEqualToString:@"CAR"] || [modeStr isEqualToString:@"car"]) { mode = RadarRouteModeCar; } - NSNumber *stepsNumber = argsDict[@"steps"]; - int steps; - if (stepsNumber != nil && [stepsNumber isKindOfClass:[NSNumber class]]) { - steps = [stepsNumber intValue]; - } else { - steps = 10; - } - NSNumber *intervalNumber = argsDict[@"interval"]; - int interval; - if (intervalNumber != nil && [intervalNumber isKindOfClass:[NSNumber class]]) { - interval = [intervalNumber intValue]; - } else { - interval = 1; - } + int steps = [argsDict[@"steps"] intValue]; + int interval = [argsDict[@"interval"] intValue]; [Radar mockTrackingWithOrigin:origin destination:destination mode:mode steps:steps interval:interval completionHandler:nil]; } @@ -478,9 +497,9 @@ - (void)startTrip:(FlutterMethodCall *)call withResult:(FlutterResult)result { } }; NSDictionary *argsDict = call.arguments; - NSDictionary *tripOptionsDict = argsDict[@"tripOptions"]; + NSDictionary *tripOptionsDict = [self getDictionaryValueForKey:argsDict key:@"tripOptions"]; RadarTripOptions *tripOptions = [RadarTripOptions tripOptionsFromDictionary:tripOptionsDict]; - NSDictionary *trackingOptionsDict = argsDict[@"trackingOptions"]; + NSDictionary *trackingOptionsDict = [self getDictionaryValueForKey:argsDict key:@"trackingOptions"]; RadarTrackingOptions *trackingOptions; if (trackingOptionsDict) { trackingOptions = [RadarTrackingOptions trackingOptionsFromDictionary:trackingOptionsDict]; @@ -504,9 +523,9 @@ - (void)updateTrip:(FlutterMethodCall *)call withResult:(FlutterResult)result { } }; NSDictionary *argsDict = call.arguments; - NSDictionary *tripOptionsDict = argsDict[@"tripOptions"]; + NSDictionary *tripOptionsDict = [self getDictionaryValueForKey:argsDict key:@"tripOptions"]; RadarTripOptions *tripOptions = [RadarTripOptions tripOptionsFromDictionary:tripOptionsDict]; - NSString* statusStr = argsDict[@"status"]; + NSString* statusStr = [self getStringValueForKey:argsDict key:@"status"]; RadarTripStatus status = RadarTripStatusUnknown; statusStr = [statusStr lowercaseString]; if ([statusStr isEqualToString:@"started"]) { @@ -567,6 +586,21 @@ - (void)cancelTrip:(FlutterMethodCall *)call withResult:(FlutterResult)result { [Radar cancelTripWithCompletionHandler:completionHandler]; } +- (void) acceptEvent:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSDictionary *argsDict = call.arguments; + NSString *eventId = [self getStringValueForKey:argsDict key:@"eventId"]; + NSString *verifiedPlaceId = [self getStringValueForKey:argsDict key:@"verifiedPlaceId"]; + [Radar acceptEventId:eventId verifiedPlaceId:verifiedPlaceId]; + result(nil); +} + +- (void) rejectEvent:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSDictionary *argsDict = call.arguments; + NSString *eventId = [self getStringValueForKey:argsDict key:@"eventId"]; + [Radar rejectEventId:eventId]; + result(nil); +} + - (void)getContext:(FlutterMethodCall *)call withResult:(FlutterResult)result { RadarContextCompletionHandler completionHandler = ^(RadarStatus status, CLLocation * _Nullable location, RadarContext * _Nullable context) { NSMutableDictionary *dict = [NSMutableDictionary new]; @@ -582,7 +616,7 @@ - (void)getContext:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSDictionary *locationDict = argsDict[@"location"]; + NSDictionary *locationDict = [self getDictionaryValueForKey:argsDict key:@"location"]; if (locationDict) { NSNumber *latitudeNumber = locationDict[@"latitude"]; NSNumber *longitudeNumber = locationDict[@"longitude"]; @@ -615,7 +649,7 @@ - (void)searchGeofences:(FlutterMethodCall *)call withResult:(FlutterResult)resu NSDictionary *argsDict = call.arguments; CLLocation *near; - NSDictionary *nearDict = argsDict[@"near"]; + NSDictionary *nearDict = [self getDictionaryValueForKey:argsDict key:@"near"]; if (nearDict) { NSNumber *latitudeNumber = nearDict[@"latitude"]; NSNumber *longitudeNumber = nearDict[@"longitude"]; @@ -623,27 +657,20 @@ - (void)searchGeofences:(FlutterMethodCall *)call withResult:(FlutterResult)resu double longitude = [longitudeNumber doubleValue]; near = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) altitude:-1 horizontalAccuracy:5 verticalAccuracy:-1 timestamp:[NSDate date]]; } - NSNumber *radiusNumber = argsDict[@"radius"]; - int radius; - if (radiusNumber != nil && [radiusNumber isKindOfClass:[NSNumber class]]) { - radius = [radiusNumber intValue]; - } else { - radius = 1000; - } - NSArray *tags = argsDict[@"tags"]; - NSDictionary *metadata = argsDict[@"metadata"]; - NSNumber *limitNumber = argsDict[@"limit"]; - int limit; - if (limitNumber != nil && [limitNumber isKindOfClass:[NSNumber class]]) { - limit = [limitNumber intValue]; - } else { - limit = 10; - } + int radius = [self getIntegerValueForKey:argsDict key:@"radius" defaultValue:1000]; + + NSArray *tags = [self getArrayValueForKey:argsDict key:@"tags"]; + + NSDictionary *metadata = [self getDictionaryValueForKey:argsDict key:@"metadata"]; + + int limit = [self getIntegerValueForKey:argsDict key:@"limit" defaultValue:10]; + + BOOL includeGeometry = [self getBoolValueForKey:argsDict key:@"includeGeometry" defaultValue:NO]; 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]; } } @@ -665,7 +692,7 @@ - (void)searchPlaces:(FlutterMethodCall *)call withResult:(FlutterResult)result NSDictionary *argsDict = call.arguments; CLLocation *near; - NSDictionary *nearDict = argsDict[@"near"]; + NSDictionary *nearDict = [self getDictionaryValueForKey:argsDict key:@"near"]; if (nearDict) { NSNumber *latitudeNumber = nearDict[@"latitude"]; NSNumber *longitudeNumber = nearDict[@"longitude"]; @@ -673,25 +700,16 @@ - (void)searchPlaces:(FlutterMethodCall *)call withResult:(FlutterResult)result double longitude = [longitudeNumber doubleValue]; near = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) altitude:-1 horizontalAccuracy:5 verticalAccuracy:-1 timestamp:[NSDate date]]; } - NSNumber *radiusNumber = argsDict[@"radius"]; - int radius; - if (radiusNumber != nil && [radiusNumber isKindOfClass:[NSNumber class]]) { - radius = [radiusNumber intValue]; - } else { - radius = 1000; - } - NSArray *chains = argsDict[@"chains"]; - NSDictionary *chainMetadata = [argsDict[@"chainMetadata"] isKindOfClass:[NSNull class]] ? nil : argsDict[@"chainMetadata"]; - NSArray *categories = [argsDict[@"categories"] isKindOfClass:[NSNull class]] ? nil : argsDict[@"categories"]; - NSArray *groups = [argsDict[@"groups"] isKindOfClass:[NSNull class]] ? nil : argsDict[@"groups"]; - NSNumber *limitNumber = argsDict[@"limit"]; - int limit; - if (limitNumber != nil && [limitNumber isKindOfClass:[NSNumber class]]) { - limit = [limitNumber intValue]; - } else { - limit = 10; - } + + int radius = [self getIntegerValueForKey:argsDict key:@"radius" defaultValue:1000]; + NSArray *chains = [self getArrayValueForKey:argsDict key:@"chains"]; + NSDictionary *chainMetadata = [self getDictionaryValueForKey:argsDict key:@"chainMetadata"]; + NSArray *categories = [self getArrayValueForKey:argsDict key:@"categories"]; + NSArray *groups = [self getArrayValueForKey:argsDict key:@"groups"]; + + int limit = [self getIntegerValueForKey:argsDict key:@"limit" defaultValue:10]; + if (near != nil) { [Radar searchPlacesNear:near radius:radius chains:chains chainMetadata:chainMetadata categories:categories groups:groups limit:limit completionHandler:completionHandler]; } else { @@ -702,9 +720,9 @@ - (void)searchPlaces:(FlutterMethodCall *)call withResult:(FlutterResult)result - (void)autocomplete:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSString *query = argsDict[@"query"]; + NSString *query = [self getStringValueForKey:argsDict key:@"query"]; CLLocation *near; - NSDictionary *nearDict = argsDict[@"near"]; + NSDictionary *nearDict = [self getDictionaryValueForKey:argsDict key:@"near"]; if (nearDict) { NSNumber *latitudeNumber = nearDict[@"latitude"]; NSNumber *longitudeNumber = nearDict[@"longitude"]; @@ -712,15 +730,11 @@ - (void)autocomplete:(FlutterMethodCall *)call withResult:(FlutterResult)result double longitude = [longitudeNumber doubleValue]; near = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) altitude:-1 horizontalAccuracy:5 verticalAccuracy:-1 timestamp:[NSDate date]]; } - NSNumber *limitNumber = argsDict[@"limit"]; - int limit; - if (limitNumber != nil && [limitNumber isKindOfClass:[NSNumber class]]) { - limit = [limitNumber intValue]; - } else { - limit = 10; - } - NSArray *layers = [argsDict[@"layers"] isKindOfClass:[NSNull class]] ? nil : argsDict[@"layers"]; - NSString *country = [argsDict[@"country"] isKindOfClass:[NSNull class]] ? nil : argsDict[@"country"]; + + int limit = [self getIntegerValueForKey:argsDict key:@"limit" defaultValue:10]; + + NSArray *layers = [self getArrayValueForKey:argsDict key:@"layers"]; + NSString *country = [self getStringValueForKey:argsDict key:@"country"]; RadarGeocodeCompletionHandler completionHandler = ^(RadarStatus status, NSArray * _Nullable addresses) { NSMutableDictionary *dict = [NSMutableDictionary new]; @@ -731,20 +745,14 @@ - (void)autocomplete:(FlutterMethodCall *)call withResult:(FlutterResult)result result(dict); }; - - NSNumber *mailableNumber = argsDict[@"mailable"]; - if (mailableNumber != nil && [mailableNumber isKindOfClass:[NSNumber class]]) { - BOOL mailable = [mailableNumber boolValue]; - [Radar autocompleteQuery:query near:near layers:layers limit:limit country:country mailable:mailable completionHandler:completionHandler]; - } else { - [Radar autocompleteQuery:query near:near layers:layers limit:limit country:country completionHandler:completionHandler]; - } + BOOL mailable = [self getBoolValueForKey:argsDict key:@"mailable" defaultValue:NO]; + [Radar autocompleteQuery:query near:near layers:layers limit:limit country:country mailable:mailable completionHandler:completionHandler]; } - (void)geocode:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSString *query = argsDict[@"query"]; + NSString *query = [self getStringValueForKey:argsDict key:@"query"]; [Radar geocodeAddress:query completionHandler:^(RadarStatus status, NSArray * _Nullable addresses) { NSMutableDictionary *dict = [NSMutableDictionary new]; [dict setObject:[Radar stringForStatus:status] forKey:@"status"]; @@ -765,19 +773,22 @@ - (void)reverseGeocode:(FlutterMethodCall *)call withResult:(FlutterResult)resul result(dict); }; - NSDictionary *argsDict = call.arguments; + NSDictionary *argsDict = call.arguments; - NSDictionary *locationDict = argsDict[@"location"]; - if (locationDict) { + NSArray *layers = [self getArrayValueForKey:argsDict key:@"layers"]; + + NSDictionary *locationDict = [self getDictionaryValueForKey:argsDict key:@"location"]; + + if (locationDict) { NSNumber *latitudeNumber = locationDict[@"latitude"]; NSNumber *longitudeNumber = locationDict[@"longitude"]; double latitude = [latitudeNumber doubleValue]; 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]; } } @@ -806,7 +817,7 @@ - (void)getDistance:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; CLLocation *origin; - NSDictionary *originDict = argsDict[@"origin"]; + NSDictionary *originDict = [self getDictionaryValueForKey:argsDict key:@"origin"]; if (originDict) { NSNumber *originLatitudeNumber = originDict[@"latitude"]; NSNumber *originLongitudeNumber = originDict[@"longitude"]; @@ -814,13 +825,14 @@ - (void)getDistance:(FlutterMethodCall *)call withResult:(FlutterResult)result { double originLongitude = [originLongitudeNumber doubleValue]; origin = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(originLatitude, originLongitude) altitude:-1 horizontalAccuracy:5 verticalAccuracy:-1 timestamp:[NSDate date]]; } - NSDictionary *destinationDict = argsDict[@"destination"]; + NSDictionary *destinationDict = [self getDictionaryValueForKey:argsDict key:@"destination"]; NSNumber *destinationLatitudeNumber = destinationDict[@"latitude"]; NSNumber *destinationLongitudeNumber = destinationDict[@"longitude"]; double destinationLatitude = [destinationLatitudeNumber doubleValue]; double destinationLongitude = [destinationLongitudeNumber doubleValue]; CLLocation *destination = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(destinationLatitude, destinationLongitude) altitude:-1 horizontalAccuracy:5 verticalAccuracy:-1 timestamp:[NSDate date]]; - NSArray *modesArr = argsDict[@"modes"]; + + NSArray *modesArr = [self getArrayValueForKey:argsDict key:@"modes"]; RadarRouteMode modes = 0; if (modesArr != nil) { if ([modesArr containsObject:@"FOOT"] || [modesArr containsObject:@"foot"]) { @@ -835,7 +847,8 @@ - (void)getDistance:(FlutterMethodCall *)call withResult:(FlutterResult)result { } else { modes = RadarRouteModeCar; } - NSString *unitsStr = argsDict[@"units"]; + + NSString *unitsStr = [self getStringValueForKey:argsDict key:@"units"]; RadarRouteUnits units; if (unitsStr != nil && [unitsStr isKindOfClass:[NSString class]]) { units = [unitsStr isEqualToString:@"METRIC"] || [unitsStr isEqualToString:@"metric"] ? RadarRouteUnitsMetric : RadarRouteUnitsImperial; @@ -864,8 +877,8 @@ - (void)logConversion:(FlutterMethodCall *)call withResult:(FlutterResult)result NSDictionary *argsDict = call.arguments; - NSDictionary *metadata = argsDict[@"metadata"]; - NSString *name = argsDict[@"name"]; + NSDictionary *metadata = [self getDictionaryValueForKey:argsDict key:@"metadata"]; + NSString *name = [self getStringValueForKey:argsDict key:@"name"]; NSNumber *revenueNumber = argsDict[@"revenue"]; if (revenueNumber != nil && [revenueNumber isKindOfClass:[NSNumber class]]) { [Radar logConversionWithName:name revenue:revenueNumber metadata:metadata completionHandler:completionHandler]; @@ -892,7 +905,7 @@ - (void)logResigningActive:(FlutterResult)result { - (void)getMatrix:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSDictionary *argsDict = call.arguments; - NSArray *originsArr = argsDict[@"origins"]; + NSArray *originsArr = [self getArrayValueForKey:argsDict key:@"origins"]; NSMutableArray *origins = [NSMutableArray new]; for (NSDictionary *originDict in originsArr) { NSNumber *latitudeNumber = originDict[@"latitude"]; @@ -904,7 +917,7 @@ - (void)getMatrix:(FlutterMethodCall *)call withResult:(FlutterResult)result { CLLocation *origin = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) altitude:-1 horizontalAccuracy:accuracy verticalAccuracy:-1 timestamp:[NSDate date]]; [origins addObject:origin]; } - NSArray *destinationsArr = argsDict[@"destinations"]; + NSArray *destinationsArr = [self getArrayValueForKey:argsDict key:@"destinations"]; NSMutableArray *destinations = [NSMutableArray new]; for (NSDictionary *destinationDict in destinationsArr) { NSNumber *latitudeNumber = destinationDict[@"latitude"]; @@ -916,7 +929,7 @@ - (void)getMatrix:(FlutterMethodCall *)call withResult:(FlutterResult)result { CLLocation *destination = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) altitude:-1 horizontalAccuracy:accuracy verticalAccuracy:-1 timestamp:[NSDate date]]; [destinations addObject:destination]; } - NSString *modeStr = argsDict[@"mode"]; + NSString *modeStr = [self getStringValueForKey:argsDict key:@"mode"]; RadarRouteMode mode = RadarRouteModeCar; if ([modeStr isEqualToString:@"FOOT"] || [modeStr isEqualToString:@"foot"]) { mode = RadarRouteModeFoot; @@ -929,7 +942,7 @@ - (void)getMatrix:(FlutterMethodCall *)call withResult:(FlutterResult)result { } else if ([modeStr isEqualToString:@"MOTORBIKE"] || [modeStr isEqualToString:@"motorbike"]) { mode = RadarRouteModeMotorbike; } - NSString *unitsStr = argsDict[@"units"]; + NSString *unitsStr = [self getStringValueForKey:argsDict key:@"units"]; RadarRouteUnits units; if (unitsStr != nil && [unitsStr isKindOfClass:[NSString class]]) { units = [unitsStr isEqualToString:@"METRIC"] || [unitsStr isEqualToString:@"metric"] ? RadarRouteUnitsMetric : RadarRouteUnitsImperial; @@ -950,25 +963,13 @@ - (void)getMatrix:(FlutterMethodCall *)call withResult:(FlutterResult)result { - (void)trackVerified:(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]; - } + BOOL beacons = [self getBoolValueForKey:argsDict key:@"beacons" defaultValue:NO]; - 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 +977,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]; @@ -1010,116 +990,57 @@ - (void)validateAddress:(FlutterMethodCall *)call withResult:(FlutterResult)resu NSDictionary *argsDict = call.arguments; - NSDictionary *addressDict = argsDict[@"address"]; + NSDictionary *addressDict = [self getDictionaryValueForKey:argsDict key:@"address"]; RadarAddress *address = [RadarAddress addressFromObject:addressDict]; [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..87e11ed 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-beta.1' 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..78a7974 100644 --- a/lib/flutter_radar.dart +++ b/lib/flutter_radar.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:ffi'; import 'package:flutter/services.dart'; import 'dart:ui'; import 'package:flutter/material.dart'; @@ -20,39 +21,66 @@ 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 Future initialize(String publishableKey) async { + static LocationCallback? foregroundLocationCallback; + static ClientLocationCallback? foregroundClientLocationCallback; + static ErrorCallback? foregroundErrorCallback; + static LogCallback? foregroundLogCallback; + static EventsCallback? foregroundEventsCallback; + static TokenCallback? foregroundTokenCallback; + + static Future initialize( + {required String publishableKey, bool fraud = false}) async { + try { await _channel.invokeMethod('initialize', { 'publishableKey': publishableKey, + 'fraud': fraud, }); + _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 setLogLevel(String logLevel) async { + 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; + } + } + + static Future setLogLevel({required String logLevel}) async { try { await _channel.invokeMethod('setLogLevel', {'logLevel': logLevel}); } on PlatformException catch (e) { @@ -64,7 +92,7 @@ class Radar { return await _channel.invokeMethod('getPermissionsStatus'); } - static Future requestPermissions(bool background) async { + static Future requestPermissions({required bool background}) async { try { return await _channel .invokeMethod('requestPermissions', {'background': background}); @@ -73,7 +101,7 @@ class Radar { } } - static Future setUserId(String userId) async { + static Future setUserId({required String userId}) async { try { await _channel.invokeMethod('setUserId', {'userId': userId}); } on PlatformException catch (e) { @@ -85,7 +113,7 @@ class Radar { return await _channel.invokeMethod('getUserId'); } - static Future setDescription(String description) async { + static Future setDescription({required String description}) async { try { await _channel .invokeMethod('setDescription', {'description': description}); @@ -98,7 +126,7 @@ class Radar { return await _channel.invokeMethod('getDescription'); } - static Future setMetadata(Map metadata) async { + static Future setMetadata({required Map metadata}) async { try { await _channel.invokeMethod('setMetadata', metadata); } on PlatformException catch (e) { @@ -110,7 +138,7 @@ class Radar { return await _channel.invokeMethod('getMetadata'); } - static Future setAnonymousTrackingEnabled(bool enabled) async { + static Future setAnonymousTrackingEnabled({required bool enabled}) async { try { await _channel .invokeMethod('setAnonymousTrackingEnabled', {'enabled': enabled}); @@ -119,7 +147,7 @@ class Radar { } } - static Future getLocation([String? accuracy]) async { + static Future getLocation({String? accuracy}) async { try { return await _channel.invokeMethod('getLocation', {'accuracy': accuracy}); } on PlatformException catch (e) { @@ -129,6 +157,7 @@ class Radar { } static Future trackOnce( + // maybe type it more strongly in the future? {Map? location, String? desiredAccuracy, bool? beacons}) async { @@ -144,7 +173,7 @@ class Radar { } } - static Future startTracking(String preset) async { + static Future startTracking({required String preset}) async { try { await _channel.invokeMethod('startTracking', { 'preset': preset, @@ -154,7 +183,8 @@ class Radar { } } - static Future startTrackingCustom(Map options) async { + static Future startTrackingCustom( + {required Map options}) async { try { await _channel.invokeMethod('startTrackingCustom', options); } on PlatformException catch (e) { @@ -163,10 +193,10 @@ class Radar { } static Future startTrackingVerified( - {bool? token, int? interval, bool? beacons}) async { + {required int interval, required 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 +210,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'); } @@ -194,11 +232,11 @@ class Radar { } static Future mockTracking( - {Map? origin, - Map? destination, - String? mode, - int? steps, - int? interval}) async { + {required Map origin, + required Map destination, + required String mode, + required int steps, + required int interval}) async { try { return await _channel.invokeMethod('mockTracking', { 'origin': origin, @@ -214,7 +252,7 @@ class Radar { } static Future startTrip( - {Map? tripOptions, + {required Map tripOptions, Map? trackingOptions}) async { try { return await _channel.invokeMethod('startTrip', @@ -226,7 +264,7 @@ class Radar { } static Future updateTrip( - {required Map options, required String status}) async { + {required String status, required Map options}) async { try { return await _channel.invokeMethod( 'updateTrip', {'tripOptions': options, 'status': status}); @@ -258,7 +296,26 @@ class Radar { } } - static Future getContext(Map location) async { + static Future acceptEvent( + {required String eventId, String? VerifiedPlaceId}) async { + try { + _channel.invokeMethod('acceptEvent', + {'eventId': eventId, 'VerifiedPlaceId': VerifiedPlaceId}); + } on PlatformException catch (e) { + print(e); + } + } + + static Future rejectEvent({required String eventId}) async { + try { + _channel.invokeMethod('rejectEvent', {'eventId': eventId}); + } on PlatformException catch (e) { + print(e); + } + } + + static Future getContext( + {required Map location}) async { try { return await _channel.invokeMethod('getContext', {'location': location}); } on PlatformException catch (e) { @@ -267,19 +324,22 @@ class Radar { } } + // you have to pass in all or none of the parameters static Future searchGeofences( {Map? near, 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); @@ -288,9 +348,9 @@ class Radar { } static Future searchPlaces( - {Map? near, - int? radius, - int? limit, + {required int radius, + required limit, + Map? near, List? chains, Map? chainMetadata, List? categories, @@ -312,9 +372,9 @@ class Radar { } static Future autocomplete( - {String? query, + {required String query, + required int limit, Map? near, - int? limit, String? country, List? layers, bool? mailable}) async { @@ -333,10 +393,11 @@ class Radar { } } - static Future geocode(String query) async { + static Future geocode( + {required String query, List? layers, List? countries}) async { try { - final Map? geocodeResult = - await _channel.invokeMethod('forwardGeocode', {'query': query}); + final Map? geocodeResult = await _channel.invokeMethod('forwardGeocode', + {'query': query, 'layers': layers, 'countries': countries}); return geocodeResult; } on PlatformException catch (e) { print(e); @@ -344,10 +405,11 @@ class Radar { } } - static Future reverseGeocode(Map location) async { + static Future reverseGeocode( + {Map? location, List? layers}) async { try { - return await _channel - .invokeMethod('reverseGeocode', {'location': location}); + return await _channel.invokeMethod( + 'reverseGeocode', {'location': location, 'layers': layers}); } on PlatformException catch (e) { print(e); return {'error': e.code}; @@ -364,10 +426,10 @@ class Radar { } static Future getDistance( - {Map? origin, - Map? destination, - List? modes, - String? units}) async { + {required Map destination, + required List modes, + required String units, + Map? origin}) async { try { return await _channel.invokeMethod('getDistance', { 'origin': origin, @@ -384,7 +446,7 @@ class Radar { static Future logConversion( {required String name, double? revenue, - required Map metadata}) async { + Map? metadata}) async { try { return await _channel.invokeMethod('logConversion', {'name': name, 'revenue': revenue, 'metadata': metadata}); @@ -421,7 +483,7 @@ class Radar { // Android only static Future setNotificationOptions( - Map notificationOptions) async { + {required Map notificationOptions}) async { try { await _channel.invokeMethod( 'setNotificationOptions', notificationOptions); @@ -431,10 +493,7 @@ class Radar { } static Future getMatrix( - {required List origins, - required List destinations, - required String mode, - required String units}) async { + { required List origins, required List destinations,required String mode, required String units}) async { try { return await _channel.invokeMethod('getMatrix', { 'origins': origins, @@ -448,8 +507,9 @@ class Radar { } } + //Android only static Future setForegroundServiceOptions( - Map foregroundServiceOptions) async { + {required Map foregroundServiceOptions}) async { try { await _channel.invokeMethod( 'setForegroundServiceOptions', foregroundServiceOptions); @@ -460,17 +520,17 @@ class Radar { static Future trackVerified({bool? beacons}) async { try { - return await _channel.invokeMethod('trackVerified', {'beacons': beacons}); + return await _channel.invokeMethod( + 'trackVerified', {'beacons': beacons != null ? beacons : false}); } on PlatformException catch (e) { print(e); return {'error': e.code}; } } - static Future trackVerifiedToken({bool? beacons}) async { + static Future getVerifiedLocationToken() async { try { - return await _channel - .invokeMethod('trackVerifiedToken', {'beacons': beacons}); + return await _channel.invokeMethod('getVerifiedLocationToken'); } on PlatformException catch (e) { print(e); return {'error': e.code}; @@ -481,7 +541,7 @@ class Radar { return await _channel.invokeMethod('isUsingRemoteTrackingOptions'); } - static Future validateAddress(Map address) async { + static Future validateAddress({required Map address}) async { try { return await _channel .invokeMethod('validateAddress', {'address': address}); @@ -491,166 +551,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 +708,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..ed958f9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: flutter_radar description: Flutter package for Radar, the leading geofencing and location tracking platform -version: 3.9.1 +version: 3.10.0-beta.1 homepage: https://github.com/radarlabs/flutter-radar environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.12.0 <4.0.0' flutter: ">=1.20.0" dependencies: