From 85105732fdcc96a0fae356eb027b1a8c1e59b11a Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Tue, 4 Jan 2022 15:17:09 -0600 Subject: [PATCH 01/25] Add NMEA functionality --- geolocator/CHANGELOG.md | 4 + geolocator/example/lib/main.dart | 5 + geolocator/lib/geolocator.dart | 29 +++ geolocator/pubspec.yaml | 6 +- geolocator/test/geolocator_test.dart | 15 ++ geolocator_android/CHANGELOG.md | 4 + .../baseflow/geolocator/GeolocatorPlugin.java | 25 ++- .../geolocator/NmeaStreamHandlerImpl.java | 102 ++++++++++ .../nmea/GnssNmeaMessageClient.java | 85 ++++++++ .../geolocator/nmea/NmeaChangedCallback.java | 8 + .../geolocator/nmea/NmeaMessageManager.java | 43 ++++ .../geolocator/nmea/NmeaMessageaClient.java | 11 + geolocator_android/pubspec.yaml | 4 +- geolocator_platform_interface/CHANGELOG.md | 6 +- .../src/geolocator_platform_interface.dart | 29 +++ .../method_channel_geolocator.dart | 31 +++ .../lib/src/models/models.dart | 1 + .../lib/src/models/nmea_message.dart | 61 ++++++ geolocator_platform_interface/pubspec.yaml | 2 +- .../geolocator_platform_interface_test.dart | 16 +- .../method_channel_geolocator_test.dart | 190 +++++++++++++++++- .../test/src/models/nmea_test.dart | 87 ++++++++ 22 files changed, 750 insertions(+), 14 deletions(-) create mode 100644 geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java create mode 100644 geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java create mode 100644 geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaChangedCallback.java create mode 100644 geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java create mode 100644 geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java create mode 100644 geolocator_platform_interface/lib/src/models/nmea_message.dart create mode 100644 geolocator_platform_interface/test/src/models/nmea_test.dart diff --git a/geolocator/CHANGELOG.md b/geolocator/CHANGELOG.md index 4e0c4483..3a4d68ab 100644 --- a/geolocator/CHANGELOG.md +++ b/geolocator/CHANGELOG.md @@ -1,3 +1,7 @@ +## 8.1.0 + +- Added functionality to receive NMEA messages. + ## 8.0.1 - Fix "forceAndroidLocationManager" for getLastKnownPosition diff --git a/geolocator/example/lib/main.dart b/geolocator/example/lib/main.dart index e86b6ba1..8ac3d1dc 100644 --- a/geolocator/example/lib/main.dart +++ b/geolocator/example/lib/main.dart @@ -40,6 +40,7 @@ class _GeolocatorWidgetState extends State { final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance; final List<_PositionItem> _positionItems = <_PositionItem>[]; StreamSubscription? _positionStreamSubscription; + StreamSubscription? _nmeaStreamSubscription; StreamSubscription? _serviceStatusStreamSubscription; bool positionStreamStarted = false; @@ -337,6 +338,10 @@ class _GeolocatorWidgetState extends State { _positionStreamSubscription!.cancel(); _positionStreamSubscription = null; } + if (_nmeaStreamSubscription != null) { + _nmeaStreamSubscription!.cancel(); + _nmeaStreamSubscription = null; + } super.dispose(); } diff --git a/geolocator/lib/geolocator.dart b/geolocator/lib/geolocator.dart index 96d1d7cb..b3b43ef3 100644 --- a/geolocator/lib/geolocator.dart +++ b/geolocator/lib/geolocator.dart @@ -91,6 +91,35 @@ class Geolocator { ); } + /// Returns a stream emitting NMEA-0183 sentences Android only, no-op on iOS. + /// + /// With devices running an Android API level lower than 24 NMEA-0183 + /// sentences are received from the GPS engine. From API level 24 and up the + /// GNSS engine is used. + /// + /// This event starts all location sensors on the device and will keep them + /// active until you cancel listening to the stream or when the application + /// is killed. + /// + /// ``` + /// StreamSubscription nmeaStream = + /// Geolocator.getNmeaMessageStream().listen((NmeaMessage nmea) { + /// // Handle NMEA changes + /// }); + /// ``` + /// + /// When no longer needed cancel the subscription + /// nmeaStream.cancel(); + /// + /// Throws a [PermissionDeniedException] when trying to request the device's + /// location when the user denied access. + /// Throws a [LocationServiceDisabledException] when the user allowed access, + /// but the location services of the device are disabled. + /// + /// for more info about NMEA 0183 see https://en.wikipedia.org/wiki/NMEA_0183 + static Stream getNmeaMessageStream() => + GeolocatorPlatform.instance.getNmeaMessageStream(); + /// Fires whenever the location changes inside the bounds of the /// supplied [LocationSettings.accuracy]. /// diff --git a/geolocator/pubspec.yaml b/geolocator/pubspec.yaml index 937a5a00..9e7c604e 100644 --- a/geolocator/pubspec.yaml +++ b/geolocator/pubspec.yaml @@ -1,6 +1,6 @@ name: geolocator description: Geolocation plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API for generic location (GPS etc.) functions. -version: 8.0.1 +version: 8.1.0 repository: https://github.com/Baseflow/flutter-geolocator/tree/master/geolocator issue_tracker: https://github.com/Baseflow/flutter-geolocator/issues?q=is%3Aissue+is%3Aopen @@ -24,8 +24,8 @@ dependencies: flutter: sdk: flutter - geolocator_platform_interface: ^3.0.1 - geolocator_android: ^3.0.0+1 + geolocator_platform_interface: ^3.1.0 + geolocator_android: ^3.1.0 geolocator_apple: ^2.0.0+2 geolocator_web: ^2.1.1 diff --git a/geolocator/test/geolocator_test.dart b/geolocator/test/geolocator_test.dart index 29c9d490..f26d8e8b 100644 --- a/geolocator/test/geolocator_test.dart +++ b/geolocator/test/geolocator_test.dart @@ -16,6 +16,13 @@ Position get mockPosition => Position( speed: 0.0, speedAccuracy: 0.0); +NmeaMessage get mockNmeaMessage => NmeaMessage( + "GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75", + DateTime.fromMillisecondsSinceEpoch( + 500, + isUtc: true, + )); + void main() { group('Geolocator', () { setUp(() { @@ -89,6 +96,11 @@ void main() { expect(position, emitsInOrder([emits(mockPosition), emitsDone])); }); + test('getNmeaMessageStream', () async { + final nmeaMessage = Geolocator.getNmeaMessageStream(); + expect(nmeaMessage, emitsInOrder([emits(mockNmeaMessage), emitsDone])); + }); + test('openAppSettings', () async { final hasOpened = await Geolocator.openAppSettings(); expect(hasOpened, true); @@ -169,6 +181,9 @@ class MockGeolocatorPlatform extends Mock ); } + @override + Stream getNmeaMessageStream() => Stream.value(mockNmeaMessage); + @override Future openAppSettings() => Future.value(true); diff --git a/geolocator_android/CHANGELOG.md b/geolocator_android/CHANGELOG.md index 89526c9a..83ba89a6 100644 --- a/geolocator_android/CHANGELOG.md +++ b/geolocator_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.1.0 + +- Added functionality to receive NMEA messages. + ## 3.0.1 - Replace usage of unofficial GMS library diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index e9395e84..7e96898e 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -3,11 +3,13 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.baseflow.geolocator.location.GeolocationManager; +import com.baseflow.geolocator.nmea.NmeaMessageManager; import com.baseflow.geolocator.location.LocationAccuracyManager; import com.baseflow.geolocator.permission.PermissionManager; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; +import io.flutter.plugin.common.BinaryMessenger; /** GeolocatorPlugin */ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { @@ -23,6 +25,8 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { @Nullable private LocationServiceHandlerImpl locationServiceHandler; + @Nullable private NmeaStreamHandlerImpl nmeaStreamHandler; + @SuppressWarnings("deprecation") @Nullable private io.flutter.plugin.common.PluginRegistry.Registrar pluginRegistrar; @@ -33,6 +37,7 @@ public GeolocatorPlugin() { this.permissionManager = new PermissionManager(); this.geolocationManager = new GeolocationManager(); this.locationAccuracyManager = new LocationAccuracyManager(); + this.nmeaMessageManager = new NmeaMessageManager(); } // This static function is optional and equivalent to onAttachedToEngine. It supports the old @@ -54,7 +59,8 @@ public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registra new MethodCallHandlerImpl( geolocatorPlugin.permissionManager, geolocatorPlugin.geolocationManager, - geolocatorPlugin.locationAccuracyManager); + geolocatorPlugin.locationAccuracyManager, + geolocatorPlugin.nmeaMessageManager); methodCallHandler.startListening(registrar.context(), registrar.messenger()); methodCallHandler.setActivity(registrar.activity()); @@ -71,7 +77,7 @@ public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registra public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { methodCallHandler = new MethodCallHandlerImpl( - this.permissionManager, this.geolocationManager, this.locationAccuracyManager); + this.permissionManager, this.geolocationManager, this.locationAccuracyManager, this.nmeaStreamHandler); methodCallHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); streamHandler = new StreamHandlerImpl(this.geolocationManager, this.permissionManager); @@ -99,6 +105,11 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { locationServiceHandler.stopListening(); locationServiceHandler = null; } + + if (nmeaStreamHandler != null) { + nmeaStreamHandler.stopListening(); + nmeaStreamHandler = null; + } } @Override @@ -114,6 +125,10 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { locationServiceHandler.setActivity(binding.getActivity()); } + if (nmeaStreamHandler != null) { + nmeaStreamHandler.setActivity(binding.getActivity()); + } + this.pluginBinding = binding; registerListeners(); } @@ -139,6 +154,9 @@ public void onDetachedFromActivity() { if (locationServiceHandler != null) { streamHandler.setActivity(null); } + if (nmeaStreamHandler != null) { + nmeaStreamHandler.setActivity(null); + } deregisterListeners(); } @@ -146,9 +164,11 @@ public void onDetachedFromActivity() { private void registerListeners() { if (this.pluginRegistrar != null) { this.pluginRegistrar.addActivityResultListener(this.geolocationManager); + this.pluginRegistrar.addActivityResultListener(this.NmeaMessageManager); this.pluginRegistrar.addRequestPermissionsResultListener(this.permissionManager); } else if (pluginBinding != null) { this.pluginBinding.addActivityResultListener(this.geolocationManager); + this.pluginBinding.addActivityResultListener(this.NmeaMessageManager); this.pluginBinding.addRequestPermissionsResultListener(this.permissionManager); } } @@ -156,6 +176,7 @@ private void registerListeners() { private void deregisterListeners() { if (this.pluginBinding != null) { this.pluginBinding.removeActivityResultListener(this.geolocationManager); + this.pluginBinding.removeActivityResultListener(this.NmeaMessageManager); this.pluginBinding.removeRequestPermissionsResultListener(this.permissionManager); } } diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java new file mode 100644 index 00000000..d4d739d7 --- /dev/null +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java @@ -0,0 +1,102 @@ +package com.baseflow.geolocator; + +import android.app.Activity; +import android.content.Context; +import android.util.Log; +import androidx.annotation.Nullable; +import com.baseflow.geolocator.errors.ErrorCodes; +import com.baseflow.geolocator.location.GeolocationManager; +import com.baseflow.geolocator.nmea.NmeaMessageManager; +import com.baseflow.geolocator.nmea.NmeaMessageaClient; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.EventChannel; +import java.util.HashMap; +import java.util.Map; + +class NmeaStreamHandlerImpl implements EventChannel.StreamHandler { + + private static final String TAG = "NmeaStreamHandlerImpl"; + + private final NmeaMessageManager nmeaMessageManager; + + @Nullable private EventChannel channel; + @Nullable private Context context; + @Nullable private Activity activity; + @Nullable private NmeaMessageaClient nmeaMessageaClient; + + public NmeaStreamHandlerImpl(NmeaMessageManager nmeaMessageManager) { + this.nmeaMessageManager = nmeaMessageManager; + } + + private static Map toMap(String message, Long timestamp) { + if (message == null || timestamp == null) { + return null; + } + + Map nmeaMap = new HashMap<>(); + + nmeaMap.put("timestamp", timestamp); + nmeaMap.put("message", message); + + return nmeaMap; + } + + void setActivity(@Nullable Activity activity) { + this.activity = activity; + } + + /** + * Registers this instance as event stream handler on the given {@code messenger}. + * + *

Stops any previously started and unstopped calls. + * + *

This should be cleaned with {@link #stopListening} once the messenger is disposed of. + */ + void startListening(Context context, BinaryMessenger messenger) { + if (channel != null) { + Log.w(TAG, "Setting a event call handler before the last was disposed."); + stopListening(); + } + + channel = new EventChannel(messenger, "flutter.baseflow.com/nmea_updates"); + channel.setStreamHandler(this); + this.context = context; + } + + /** + * Clears this instance from listening to method calls. + * + *

Does nothing if {@link #startListening} hasn't been called, or if we're already stopped. + */ + void stopListening() { + if (channel == null) { + Log.d(TAG, "Tried to stop listening when no MethodChannel had been initialized."); + return; + } + + channel.setStreamHandler(null); + channel = null; + } + + @Override + public void onListen(Object arguments, EventChannel.EventSink events) { + + this.nmeaMessageaClient = nmeaMessageManager.createNmeaClient(context); + + nmeaMessageManager.startNmeaUpdates( + context, + activity, + this.nmeaMessageaClient, + (String message, long timestamp) -> events.success(toMap(message, timestamp)), + (ErrorCodes errorCodes) -> + events.error(errorCodes.toString(), errorCodes.toDescription(), null)); + } + + @Override + public void onCancel(Object arguments) { + if (this.nmeaMessageaClient != null) { + nmeaMessageManager.stopNmeaUpdates(this.nmeaMessageaClient); + } + } + +} \ No newline at end of file diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java new file mode 100644 index 00000000..993408ff --- /dev/null +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java @@ -0,0 +1,85 @@ +package com.baseflow.geolocator.nmea; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.location.OnNmeaMessageListener; +import android.os.Looper; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.errors.ErrorCodes; + + +@SuppressLint("NewApi") +public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationListener, + NmeaMessageaClient { + + private final LocationManager locationManager; + @Nullable + private NmeaChangedCallback nmeaChangedCallback; + + @Nullable + private ErrorCallback errorCallback; + + private boolean isListening = false; + + + public GnssNmeaMessageClient( + @NonNull Context context) { + this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + } + + @SuppressLint("MissingPermission") + public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback) { + + this.locationManager.addNmeaListener(this, null); + this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, this, + Looper.getMainLooper()); + this.nmeaChangedCallback = nmeaChangedCallback; + this.errorCallback = errorCallback; + this.isListening = true; + } + + @SuppressLint("MissingPermission") + @Override + public void stopNmeaUpdates() { + this.isListening = false; + this.locationManager.removeUpdates(this); + } + + + @Override + public void onNmeaMessage(String message, long timestamp) { + if (this.nmeaChangedCallback != null) { + this.nmeaChangedCallback.onNmeaMessage(message, timestamp); + } + } + + + @Override + public void onLocationChanged(@NonNull Location location) { + } + + + @Override + public void onProviderEnabled(String s) { + } + + @SuppressLint("MissingPermission") + @Override + public void onProviderDisabled(String provider) { + if (provider.equals(LocationManager.GPS_PROVIDER)) { + if (isListening) { + this.locationManager.removeUpdates(this); + } + + if (this.errorCallback != null) { + errorCallback.onError(ErrorCodes.locationServicesDisabled); + } + } + } +} \ No newline at end of file diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaChangedCallback.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaChangedCallback.java new file mode 100644 index 00000000..57f4d6e6 --- /dev/null +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaChangedCallback.java @@ -0,0 +1,8 @@ +package com.baseflow.geolocator.nmea; + + +@FunctionalInterface +public interface NmeaChangedCallback { + + void onNmeaMessage(String message, long timeStamp); +} \ No newline at end of file diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java new file mode 100644 index 00000000..53547302 --- /dev/null +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java @@ -0,0 +1,43 @@ +package com.baseflow.geolocator.nmea; + + +import android.app.Activity; +import android.content.Context; +import android.os.Build.VERSION_CODES; +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; + +import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.permission.PermissionManager; + +public class NmeaMessageManager { + + @NonNull + private final PermissionManager permissionManager; + + + public NmeaMessageManager(@NonNull PermissionManager permissionManager) { + this.permissionManager = permissionManager; + } + + + public void startNmeaUpdates(Context context, Activity activity, NmeaMessageaClient client, + NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback) { + + permissionManager.handlePermissions( + context, + activity, + () -> client.startNmeaUpdates(nmeaChangedCallback, errorCallback), + errorCallback); + } + + public void stopNmeaUpdates(NmeaMessageaClient client) { + client.stopNmeaUpdates(); + } + + @RequiresApi(api = VERSION_CODES.N) + public NmeaMessageaClient createNmeaClient(Context context) { + return new GnssNmeaMessageClient(context); + } + +} \ No newline at end of file diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java new file mode 100644 index 00000000..ea1a6b0d --- /dev/null +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java @@ -0,0 +1,11 @@ +package com.baseflow.geolocator.nmea; + +import com.baseflow.geolocator.errors.ErrorCallback; + +public interface NmeaMessageaClient { + + void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback); + + void stopNmeaUpdates(); +} \ No newline at end of file diff --git a/geolocator_android/pubspec.yaml b/geolocator_android/pubspec.yaml index 80d4436a..dc079713 100644 --- a/geolocator_android/pubspec.yaml +++ b/geolocator_android/pubspec.yaml @@ -1,6 +1,6 @@ name: geolocator_android description: Geolocation plugin for Flutter. This plugin provides the Android implementation for the geolocator. -version: 3.0.1 +version: 3.1.0 repository: https://github.com/Baseflow/flutter-geolocator/tree/master/geolocator_android issue_tracker: https://github.com/Baseflow/flutter-geolocator/issues?q=is%3Aissue+is%3Aopen @@ -18,7 +18,7 @@ flutter: dependencies: flutter: sdk: flutter - geolocator_platform_interface: ^3.0.0+1 + geolocator_platform_interface: ^3.1.0 dev_dependencies: flutter_test: diff --git a/geolocator_platform_interface/CHANGELOG.md b/geolocator_platform_interface/CHANGELOG.md index b64b316c..0bcac94a 100644 --- a/geolocator_platform_interface/CHANGELOG.md +++ b/geolocator_platform_interface/CHANGELOG.md @@ -1,6 +1,10 @@ +## 3.1.0 + +- Added functionality to receive NMEA messages. + ## 3.0.1 -- Remove unnexessary import statements from several source files. +- Remove unnecessary import statements from several source files. - Fix "forceAndroidLocationManager" for getLastKnownPosition ## 3.0.0+1 diff --git a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart index 8e56ece0..19b35504 100644 --- a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart +++ b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart @@ -121,6 +121,35 @@ abstract class GeolocatorPlatform extends PlatformInterface { 'getServiceStatusStream() has not been implemented.'); } + /// Returns a stream emitting NMEA-0183 sentences when they are received from + /// the GNSS engine. With devices running a Android API level lower than 24 + /// NMEA-0183 sentences are received from the GPS engine. + /// + /// This event starts all location sensors on the device and will keep them + /// active until you cancel listening to the stream or when the application + /// is killed. + /// + /// ``` + /// StreamSubscription nmeaStream = Geolocator.getNmeaStream() + /// .listen((NmeaMessage nmea) { + /// // Handle NMEA changes + /// }); + /// ``` + /// + /// When no longer needed cancel the subscription + /// nmeaStream.cancel(); + /// + /// Throws a [PermissionDeniedException] when trying to request the device's + /// location when the user denied access. + /// Throws a [LocationServiceDisabledException] when the user allowed access, + /// but the location services of the device are disabled. + /// + /// for more info about NMEA 0183 see https://en.wikipedia.org/wiki/NMEA_0183 + Stream getNmeaMessageStream() { + throw UnimplementedError( + 'getNmeaMessageStream() has not been implemented.'); + } + /// Fires whenever the location changes inside the bounds of the /// [desiredAccuracy]. /// diff --git a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart index 1afbc9c3..5b0e6920 100644 --- a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart +++ b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart @@ -25,6 +25,11 @@ class MethodChannelGeolocator extends GeolocatorPlatform { static const _serviceStatusEventChannel = EventChannel('flutter.baseflow.com/geolocator_service_updates'); + /// The event channel used to receive [NmeaMessage] updates from the native + /// platform. + static const _nmeaEventChannel = + EventChannel('flutter.baseflow.com/nmea_updates'); + /// On Android devices you can set [forcedLocationManager] /// to true to force the plugin to use the [LocationManager] to determine the /// position instead of the [FusedLocationProviderClient]. On iOS this is @@ -33,6 +38,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform { Stream? _positionStream; Stream? _serviceStatusStream; + Stream? _nmeaMessageStream; @override Future checkPermission() async { @@ -191,6 +197,31 @@ class MethodChannelGeolocator extends GeolocatorPlatform { return _positionStream!; } + @override + Stream getNmeaMessageStream() { + if (_nmeaMessageStream != null) { + return _nmeaMessageStream!; + } + + final nmeaStream = _nmeaEventChannel.receiveBroadcastStream(); + + _nmeaMessageStream = nmeaStream + .map((dynamic element) => + NmeaMessage.fromMap(element.cast())) + .handleError( + (error) { + _nmeaMessageStream = null; + if (error is PlatformException) { + _handlePlatformException(error); + } + + throw error; + }, + ); + + return _nmeaMessageStream!; + } + Stream _wrapStream(Stream incoming) { return incoming.asBroadcastStream(onCancel: (subscription) { subscription.cancel(); diff --git a/geolocator_platform_interface/lib/src/models/models.dart b/geolocator_platform_interface/lib/src/models/models.dart index 87dc67ae..e7219d84 100644 --- a/geolocator_platform_interface/lib/src/models/models.dart +++ b/geolocator_platform_interface/lib/src/models/models.dart @@ -1,2 +1,3 @@ export 'position.dart'; export 'location_settings.dart'; +export 'nmea_message.dart'; diff --git a/geolocator_platform_interface/lib/src/models/nmea_message.dart b/geolocator_platform_interface/lib/src/models/nmea_message.dart new file mode 100644 index 00000000..feda4c96 --- /dev/null +++ b/geolocator_platform_interface/lib/src/models/nmea_message.dart @@ -0,0 +1,61 @@ +import 'package:meta/meta.dart'; + +@immutable + +/// Contains all the NMEA information. +class NmeaMessage { + /// Constructs a NMEA message instance with the given values. + const NmeaMessage(this.message, this.timestamp); + + /// The full NMEA-0183 message, as reported by the GNSS chipset. + final String message; + + /// Date and time of the location fix, as reported by the GNSS chipset. + /// The value is specified in milliseconds since 0:00 UTC 1 January 1970. + final DateTime? timestamp; + + /// Converts the supplied [Map] to an instance of the [NmeaMessage] class. + static NmeaMessage fromMap(Map message) { + final Map nmeaMessageMap = message; + + if (!nmeaMessageMap.containsKey('message')) { + throw ArgumentError.value(nmeaMessageMap, 'nmeaMessageMap', + 'The supplied map doesn\'t contain the mandatory key `message`.'); + } + + if (!nmeaMessageMap.containsKey('timestamp')) { + throw ArgumentError.value(nmeaMessageMap, 'nmeaMessageMap', + 'The supplied map doesn\'t contain the mandatory key `timestamp`.'); + } + + final timestamp = nmeaMessageMap['timestamp'] != null + ? DateTime.fromMillisecondsSinceEpoch( + nmeaMessageMap['timestamp'].toInt(), + isUtc: true) + : null; + + return NmeaMessage( + nmeaMessageMap['message'], + timestamp, + ); + } + + /// Converts the [NmeaMessage] instance into a [Map] instance that can be + /// serialized to JSON. + Map toJson() => { + 'message': message, + 'timestamp': timestamp?.millisecondsSinceEpoch, + }; + + @override + bool operator ==(Object other) { + var areEqual = other is NmeaMessage && + other.message == message && + other.timestamp == timestamp; + + return areEqual; + } + + @override + int get hashCode => message.hashCode ^ timestamp.hashCode; +} diff --git a/geolocator_platform_interface/pubspec.yaml b/geolocator_platform_interface/pubspec.yaml index a3dc2751..35df2966 100644 --- a/geolocator_platform_interface/pubspec.yaml +++ b/geolocator_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the geolocator plugin. homepage: https://github.com/baseflow/flutter-geolocator # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 3.0.1 +version: 3.1.0 dependencies: flutter: diff --git a/geolocator_platform_interface/test/geolocator_platform_interface_test.dart b/geolocator_platform_interface/test/geolocator_platform_interface_test.dart index cd86f49e..0e730448 100644 --- a/geolocator_platform_interface/test/geolocator_platform_interface_test.dart +++ b/geolocator_platform_interface/test/geolocator_platform_interface_test.dart @@ -158,6 +158,20 @@ void main() { ); }); + test( + // ignore: lines_longer_than_80_chars + 'Default implementation of getNmeaMessageStream should throw unimplemented error', + () { + // Arrange + final geolocatorPlatform = ExtendsGeolocatorPlatform(); + + // Act & Assert + expect( + geolocatorPlatform.getNmeaMessageStream, + throwsUnimplementedError, + ); + }); + test( // ignore: lines_longer_than_80_chars 'Default implementation of openAppSettings should throw unimplemented error', @@ -250,7 +264,7 @@ void main() { expect(bearing, 0.0); }); - test('the North pole to the Sounth pole bearing should be 180', () async { + test('the North pole to the South pole bearing should be 180', () async { const startLatitude = 90.0; const startLongitude = 0.0; const endLatitude = -90.0; diff --git a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart index 4f50ee12..24cd26e1 100644 --- a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart +++ b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart @@ -23,6 +23,13 @@ Position get mockPosition => Position( speedAccuracy: 0.0, isMocked: false); +NmeaMessage get mockNmeaMessage => NmeaMessage( + "GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75", + DateTime.fromMillisecondsSinceEpoch( + 500, + isUtc: true, + )); + void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -1032,17 +1039,28 @@ void main() { group( // ignore: lines_longer_than_80_chars - 'getServiceStream: When requesting a stream of location service status updates', + 'getServiceStream: When requesting a stream of location service status and NMEA updates', () { - group('And requesting for location service status updates multiple times', + group( + 'And requesting for NMEA and location service status updates multiple times', () { test('Should return the same stream', () { final methodChannelGeolocator = MethodChannelGeolocator(); final firstStream = methodChannelGeolocator.getServiceStatusStream(); - final secondstream = methodChannelGeolocator.getServiceStatusStream(); + final secondStream = methodChannelGeolocator.getServiceStatusStream(); + + expect( + identical(firstStream, secondStream), + true, + ); + + final firstStreamNmea = + methodChannelGeolocator.getNmeaMessageStream(); + final secondStreamNmea = + methodChannelGeolocator.getNmeaMessageStream(); expect( - identical(firstStream, secondstream), + identical(firstStreamNmea, secondStreamNmea), true, ); }); @@ -1076,6 +1094,37 @@ void main() { await streamController.close(); }); + test( + // ignore: lines_longer_than_80_chars + 'Should receive a stream with NMEA updates if permissions are granted', + () async { + // Arrange + final streamController = + StreamController>.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/nmea_updates', + stream: streamController.stream, + ); + + // Act + final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test events + streamController.add(mockNmeaMessage.toJson()); + streamController.add(mockNmeaMessage.toJson()); + streamController.add(mockNmeaMessage.toJson()); + + // Assert + expect(await streamQueue.next, mockNmeaMessage); + expect(await streamQueue.next, mockNmeaMessage); + expect(await streamQueue.next, mockNmeaMessage); + + // Clean up + await streamQueue.cancel(); + await streamController.close(); + }); + test( // ignore: lines_longer_than_80_chars 'Should receive an exception if android activity is missing', @@ -1114,6 +1163,139 @@ void main() { streamQueue.cancel(); streamController.close(); }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a location service disabled exception if location service is disabled', + () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/nmea_updates', + stream: streamController.stream, + ); + + // Act + final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'LOCATION_SERVICES_DISABLED', + message: 'Location services disabled', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA(), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a already subscribed exception', () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/nmea_updates', + stream: streamController.stream, + ); + + // Act + final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'PERMISSION_REQUEST_IN_PROGRESS', + message: 'A permission request is already in progress', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA(), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a already subscribed exception', () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/nmea_updates', + stream: streamController.stream, + ); + + // Act + final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'LOCATION_SUBSCRIPTION_ACTIVE', + message: 'Already subscribed to receive a position stream', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA(), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a position update exception', () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/nmea_updates', + stream: streamController.stream, + ); + + // Act + final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'LOCATION_UPDATE_FAILURE', + message: 'A permission request is already in progress', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA(), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); }); group('openAppSettings: When opening the App settings', () { diff --git a/geolocator_platform_interface/test/src/models/nmea_test.dart b/geolocator_platform_interface/test/src/models/nmea_test.dart new file mode 100644 index 00000000..fcc4536a --- /dev/null +++ b/geolocator_platform_interface/test/src/models/nmea_test.dart @@ -0,0 +1,87 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; + +void main() { + group('hashCode tests:', () { + test('hashCode should be the same for two instances with the same values', + () { + // Arrange + final firstNmeaMessage = + NmeaMessage("message", DateTime.fromMicrosecondsSinceEpoch(500)); + final secondNmeaMessage = + NmeaMessage("message", DateTime.fromMicrosecondsSinceEpoch(500)); + + // Act & Assert + expect( + firstNmeaMessage.hashCode, + secondNmeaMessage.hashCode, + ); + }); + + test('hashCode should not match when the message property is different', + () { + // Arrange + final firstNmeaMessage = NmeaMessage( + "first", + DateTime.fromMillisecondsSinceEpoch(0), + ); + final secondNmeaMessage = NmeaMessage( + "second", + DateTime.fromMillisecondsSinceEpoch(0), + ); + + // Act & Assert + expect( + firstNmeaMessage.hashCode != secondNmeaMessage.hashCode, + true, + ); + }); + + test('hashCode should not match when the timestamp property is different', + () { + // Arrange + final firstNmeaMessage = NmeaMessage( + "message", + DateTime.fromMillisecondsSinceEpoch(0), + ); + final secondNmeaMessage = NmeaMessage( + "message", + DateTime.fromMillisecondsSinceEpoch(1), + ); + + // Act & Assert + expect( + firstNmeaMessage.hashCode != secondNmeaMessage.hashCode, + true, + ); + }); + }); + + group('fromMap tests:', () { + test( + // ignore: lines_longer_than_80_chars + 'fromMap should throw argument error when map does not contain message', + () { + // Arrange + final map = { + 'timestamp': 0, + }; + + // Act & Assert + expect(() => NmeaMessage.fromMap(map), throwsArgumentError); + }); + + test( + // ignore: lines_longer_than_80_chars + 'fromMap should throw argument error when map does not contain timestamp', + () { + // Arrange + final map = { + 'message': "nmeaMessage", + }; + + // Act & Assert + expect(() => NmeaMessage.fromMap(map), throwsArgumentError); + }); + }); +} From edd20588368191c0625eafac01d0654b01f8da67 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Tue, 4 Jan 2022 15:40:22 -0600 Subject: [PATCH 02/25] Update geolocator_platform_interface.dart --- .../lib/src/geolocator_platform_interface.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart index 19b35504..7cf3f60a 100644 --- a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart +++ b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart @@ -7,6 +7,7 @@ import 'package:vector_math/vector_math.dart'; import 'enums/enums.dart'; import 'implementations/method_channel_geolocator.dart'; import 'models/models.dart'; +import 'models/nmea_message.dart'; /// The interface that implementations of geolocator must implement. /// From 0bbb181e95ffec40f7ee61e3f7c6028abd12c03d Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Tue, 4 Jan 2022 15:50:24 -0600 Subject: [PATCH 03/25] Update method_channel_geolocator.dart --- .../src/implementations/method_channel_geolocator.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart index 5b0e6920..95e7a020 100644 --- a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart +++ b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart @@ -6,8 +6,9 @@ import '../enums/enums.dart'; import '../errors/errors.dart'; import '../extensions/extensions.dart'; import '../geolocator_platform_interface.dart'; -import '../models/position.dart'; import '../models/location_settings.dart'; +import '../models/nmea_message.dart'; +import '../models/position.dart'; /// An implementation of [GeolocatorPlatform] that uses method channels. class MethodChannelGeolocator extends GeolocatorPlatform { @@ -28,7 +29,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform { /// The event channel used to receive [NmeaMessage] updates from the native /// platform. static const _nmeaEventChannel = - EventChannel('flutter.baseflow.com/nmea_updates'); + EventChannel('flutter.baseflow.com/nmea_updates'); /// On Android devices you can set [forcedLocationManager] /// to true to force the plugin to use the [LocationManager] to determine the @@ -207,9 +208,9 @@ class MethodChannelGeolocator extends GeolocatorPlatform { _nmeaMessageStream = nmeaStream .map((dynamic element) => - NmeaMessage.fromMap(element.cast())) + NmeaMessage.fromMap(element.cast())) .handleError( - (error) { + (error) { _nmeaMessageStream = null; if (error is PlatformException) { _handlePlatformException(error); From 912c572904765324992d2f80308256a1d3ac7e9a Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 10:23:19 -0600 Subject: [PATCH 04/25] NmeaMessageManager setup changes --- .../main/java/com/baseflow/geolocator/GeolocatorPlugin.java | 4 +--- .../java/com/baseflow/geolocator/MethodCallHandlerImpl.java | 6 +++++- .../com/baseflow/geolocator/nmea/NmeaMessageManager.java | 4 +--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index 7e96898e..e1767ba5 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -18,6 +18,7 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { private final PermissionManager permissionManager; private final GeolocationManager geolocationManager; private final LocationAccuracyManager locationAccuracyManager; + private final NmeaMessageManager nmeaMessageManager; @Nullable private MethodCallHandlerImpl methodCallHandler; @@ -164,11 +165,9 @@ public void onDetachedFromActivity() { private void registerListeners() { if (this.pluginRegistrar != null) { this.pluginRegistrar.addActivityResultListener(this.geolocationManager); - this.pluginRegistrar.addActivityResultListener(this.NmeaMessageManager); this.pluginRegistrar.addRequestPermissionsResultListener(this.permissionManager); } else if (pluginBinding != null) { this.pluginBinding.addActivityResultListener(this.geolocationManager); - this.pluginBinding.addActivityResultListener(this.NmeaMessageManager); this.pluginBinding.addRequestPermissionsResultListener(this.permissionManager); } } @@ -176,7 +175,6 @@ private void registerListeners() { private void deregisterListeners() { if (this.pluginBinding != null) { this.pluginBinding.removeActivityResultListener(this.geolocationManager); - this.pluginBinding.removeActivityResultListener(this.NmeaMessageManager); this.pluginBinding.removeRequestPermissionsResultListener(this.permissionManager); } } diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/MethodCallHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/MethodCallHandlerImpl.java index a04fb69a..5db456b4 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/MethodCallHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/MethodCallHandlerImpl.java @@ -17,6 +17,7 @@ import com.baseflow.geolocator.location.LocationClient; import com.baseflow.geolocator.location.LocationMapper; import com.baseflow.geolocator.location.LocationOptions; +import com.baseflow.geolocator.nmea.NmeaMessageManager; import com.baseflow.geolocator.permission.LocationPermission; import com.baseflow.geolocator.permission.PermissionManager; import com.baseflow.geolocator.utils.Utils; @@ -36,6 +37,7 @@ class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { private final PermissionManager permissionManager; private final GeolocationManager geolocationManager; private final LocationAccuracyManager locationAccuracyManager; + private final NmeaMessageManager nmeaMessageManager; @Nullable private Context context; @@ -44,10 +46,12 @@ class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { MethodCallHandlerImpl( PermissionManager permissionManager, GeolocationManager geolocationManager, - LocationAccuracyManager locationAccuracyManager) { + LocationAccuracyManager locationAccuracyManager, + NmeaMessageManager nmeaMessageManager) { this.permissionManager = permissionManager; this.geolocationManager = geolocationManager; this.locationAccuracyManager = locationAccuracyManager; + this.nmeaMessageManager = nmeaMessageManager; } @Nullable private MethodChannel channel; diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java index 53547302..1eecb7cb 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java @@ -16,9 +16,7 @@ public class NmeaMessageManager { private final PermissionManager permissionManager; - public NmeaMessageManager(@NonNull PermissionManager permissionManager) { - this.permissionManager = permissionManager; - } + public NmeaMessageManager(); public void startNmeaUpdates(Context context, Activity activity, NmeaMessageaClient client, From 16fb1f186be380179a7191ad4a3b103dae50df6b Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 16:05:04 -0600 Subject: [PATCH 05/25] move permissionmanager to nmea handler --- .../baseflow/geolocator/GeolocatorPlugin.java | 12 +++++-- .../geolocator/NmeaStreamHandlerImpl.java | 27 ++++++++++----- .../nmea/GnssNmeaMessageClient.java | 33 ++++++++++++++++--- .../geolocator/nmea/NmeaMessageManager.java | 29 +++++++++------- .../geolocator/nmea/NmeaMessageaClient.java | 14 +++++++- 5 files changed, 85 insertions(+), 30 deletions(-) diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index e1767ba5..7776ca64 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -78,16 +78,22 @@ public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registra public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { methodCallHandler = new MethodCallHandlerImpl( - this.permissionManager, this.geolocationManager, this.locationAccuracyManager, this.nmeaStreamHandler); + this.permissionManager, + this.geolocationManager, + this.locationAccuracyManager, + this.nmeaMessageManager); methodCallHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); streamHandler = new StreamHandlerImpl(this.geolocationManager, this.permissionManager); streamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - locationServiceHandler = new LocationServiceHandlerImpl(); locationServiceHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); + nmeaStreamHandler = new NmeaStreamHandlerImpl(nmeaMessageManager); + nmeaStreamHandler.startListening( + flutterPluginBinding.getApplicationContext(), + flutterPluginBinding.getBinaryMessenger()); } @Override @@ -127,7 +133,7 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { } if (nmeaStreamHandler != null) { - nmeaStreamHandler.setActivity(binding.getActivity()); + nmeaStreamHandler.setActivity(binding.getActivity()); } this.pluginBinding = binding; diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java index d4d739d7..3daeae8c 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java @@ -5,7 +5,7 @@ import android.util.Log; import androidx.annotation.Nullable; import com.baseflow.geolocator.errors.ErrorCodes; -import com.baseflow.geolocator.location.GeolocationManager; +import com.baseflow.geolocator.permission.PermissionManager; import com.baseflow.geolocator.nmea.NmeaMessageManager; import com.baseflow.geolocator.nmea.NmeaMessageaClient; import io.flutter.plugin.common.BinaryMessenger; @@ -14,18 +14,19 @@ import java.util.Map; class NmeaStreamHandlerImpl implements EventChannel.StreamHandler { - private static final String TAG = "NmeaStreamHandlerImpl"; private final NmeaMessageManager nmeaMessageManager; + private final PermissionManager permissionManager; @Nullable private EventChannel channel; @Nullable private Context context; @Nullable private Activity activity; @Nullable private NmeaMessageaClient nmeaMessageaClient; - public NmeaStreamHandlerImpl(NmeaMessageManager nmeaMessageManager) { + public NmeaStreamHandlerImpl(NmeaMessageManager nmeaMessageManager, PermissionManager permissionManager) { this.nmeaMessageManager = nmeaMessageManager; + this.permissionManager = permissionManager; } private static Map toMap(String message, Long timestamp) { @@ -80,16 +81,24 @@ void stopListening() { @Override public void onListen(Object arguments, EventChannel.EventSink events) { + try { + if (!permissionManager.hasPermission(this.context)){ + events.error(ErrorCodes.permissionDenied.toString(),ErrorCodes.permissionDenied.toDescription(),null); + return; + } + } catch (PermissionUndefinedException e) { + events.error(ErrorCodes.permissionDefinitionsNotFound.toString(), ErrorCodes.permissionDefinitionsNotFound.toDescription(), null); + return; + } - this.nmeaMessageaClient = nmeaMessageManager.createNmeaClient(context); + this.nmeaMessageaClient = nmeaMessageManager.createNmeaClient(this.context); nmeaMessageManager.startNmeaUpdates( - context, - activity, - this.nmeaMessageaClient, - (String message, long timestamp) -> events.success(toMap(message, timestamp)), + this.nmeaMessageaClient, + activity, + (String message, long timestamp) -> events.success(toMap(message, timestamp)), (ErrorCodes errorCodes) -> - events.error(errorCodes.toString(), errorCodes.toDescription(), null)); + events.error(errorCodes.toString(), errorCodes.toDescription(), null)); } @Override diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java index 993408ff..5d401dc7 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java @@ -17,6 +17,7 @@ public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationListener, NmeaMessageaClient { + public Context context; private final LocationManager locationManager; @Nullable private NmeaChangedCallback nmeaChangedCallback; @@ -30,18 +31,40 @@ public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationLis public GnssNmeaMessageClient( @NonNull Context context) { this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + this.context = context; + } + + @Override + public void isLocationServiceEnabled(LocationServiceListener listener) { + if (locationManager == null) { + listener.onLocationServiceResult(false); + return; + } + + listener.onLocationServiceResult(checkLocationService(context)); } @SuppressLint("MissingPermission") - public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, - ErrorCallback errorCallback) { + public void startNmeaUpdates( + Activity activity, + NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback) { + + if (!checkLocationService(context)) { + errorCallback.onError(ErrorCodes.locationServicesDisabled); + return; + } + + long timeInterval = 10000; + float distanceFilter = 0; - this.locationManager.addNmeaListener(this, null); - this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, this, - Looper.getMainLooper()); this.nmeaChangedCallback = nmeaChangedCallback; this.errorCallback = errorCallback; + this.isListening = true; + this.locationManager.addNmeaListener(this, null); + this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, timeInterval, distanceFilter, this, + Looper.getMainLooper()); } @SuppressLint("MissingPermission") diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java index 1eecb7cb..18d3e61f 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java @@ -12,21 +12,25 @@ public class NmeaMessageManager { - @NonNull - private final PermissionManager permissionManager; - - public NmeaMessageManager(); + public void isLocationServiceEnabled( + @Nullable Context context, LocationServiceListener listener) { + if (context == null) { + listener.onLocationServiceError(ErrorCodes.locationServicesDisabled); + } + + NmeaMessageaClient nmeaMessageaClient = createNmeaClient(context, null); + nmeaMessageaClient.isLocationServiceEnabled(listener); + } - public void startNmeaUpdates(Context context, Activity activity, NmeaMessageaClient client, - NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback) { + public void startNmeaUpdates( + @NonNull NmeaMessageaClient client, + @Nullable Activity activity, + @NonNull NmeaChangedCallback nmeaChangedCallback, + @NonNull ErrorCallback errorCallback) { - permissionManager.handlePermissions( - context, - activity, - () -> client.startNmeaUpdates(nmeaChangedCallback, errorCallback), - errorCallback); + client.startNmeaUpdates(activity, nmeaChangedCallback, errorCallback); } public void stopNmeaUpdates(NmeaMessageaClient client) { @@ -34,7 +38,8 @@ public void stopNmeaUpdates(NmeaMessageaClient client) { } @RequiresApi(api = VERSION_CODES.N) - public NmeaMessageaClient createNmeaClient(Context context) { + public NmeaMessageaClient createNmeaClient( + Context context) { return new GnssNmeaMessageClient(context); } diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java index ea1a6b0d..09e5f4f0 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java @@ -1,11 +1,23 @@ package com.baseflow.geolocator.nmea; +import android.app.Activity; + +import android.content.Context; +import android.location.LocationManager; import com.baseflow.geolocator.errors.ErrorCallback; public interface NmeaMessageaClient { + void isLocationServiceEnabled(LocationServiceListener listener) - void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + void startNmeaUpdates(Activity activity, NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback); void stopNmeaUpdates(); + + default boolean checkLocationService(Context context){ + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + boolean gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + boolean network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); + return gps_enabled || network_enabled; + } } \ No newline at end of file From 2e34eaca67c6bcb9e63c5474ab93abd7556ec047 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 16:06:58 -0600 Subject: [PATCH 06/25] Update NmeaMessageaClient.java --- .../java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java index 09e5f4f0..f546f13b 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java @@ -7,7 +7,7 @@ import com.baseflow.geolocator.errors.ErrorCallback; public interface NmeaMessageaClient { - void isLocationServiceEnabled(LocationServiceListener listener) + void isLocationServiceEnabled(LocationServiceListener listener); void startNmeaUpdates(Activity activity, NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback); From aed919a047d31e1ba55d4abdfcb7c6f9740f02a7 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 16:54:50 -0600 Subject: [PATCH 07/25] fix imports and method calls --- .../java/com/baseflow/geolocator/GeolocatorPlugin.java | 2 +- .../com/baseflow/geolocator/NmeaStreamHandlerImpl.java | 1 + .../baseflow/geolocator/nmea/GnssNmeaMessageClient.java | 2 ++ .../com/baseflow/geolocator/nmea/NmeaMessageManager.java | 8 +++++--- .../com/baseflow/geolocator/nmea/NmeaMessageaClient.java | 1 + 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index 7776ca64..5ce70732 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -90,7 +90,7 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin locationServiceHandler = new LocationServiceHandlerImpl(); locationServiceHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - nmeaStreamHandler = new NmeaStreamHandlerImpl(nmeaMessageManager); + nmeaStreamHandler = new NmeaStreamHandlerImpl(this.nmeaMessageManager, this.permissionManager); nmeaStreamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java index 3daeae8c..59a6f7c4 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java @@ -5,6 +5,7 @@ import android.util.Log; import androidx.annotation.Nullable; import com.baseflow.geolocator.errors.ErrorCodes; +import com.baseflow.geolocator.errors.PermissionUndefinedException; import com.baseflow.geolocator.permission.PermissionManager; import com.baseflow.geolocator.nmea.NmeaMessageManager; import com.baseflow.geolocator.nmea.NmeaMessageaClient; diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java index 5d401dc7..3ea90c31 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java @@ -1,6 +1,7 @@ package com.baseflow.geolocator.nmea; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; import android.location.Location; import android.location.LocationListener; @@ -11,6 +12,7 @@ import androidx.annotation.Nullable; import com.baseflow.geolocator.errors.ErrorCallback; import com.baseflow.geolocator.errors.ErrorCodes; +import com.baseflow.geolocator.location.LocationServiceListener; @SuppressLint("NewApi") diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java index 18d3e61f..47f1bb3f 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java @@ -1,18 +1,20 @@ package com.baseflow.geolocator.nmea; - import android.app.Activity; import android.content.Context; import android.os.Build.VERSION_CODES; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.errors.ErrorCodes; +import com.baseflow.geolocator.location.LocationServiceListener; import com.baseflow.geolocator.permission.PermissionManager; public class NmeaMessageManager { - public NmeaMessageManager(); + public NmeaMessageManager() {} public void isLocationServiceEnabled( @Nullable Context context, LocationServiceListener listener) { @@ -20,7 +22,7 @@ public void isLocationServiceEnabled( listener.onLocationServiceError(ErrorCodes.locationServicesDisabled); } - NmeaMessageaClient nmeaMessageaClient = createNmeaClient(context, null); + NmeaMessageaClient nmeaMessageaClient = createNmeaClient(context); nmeaMessageaClient.isLocationServiceEnabled(listener); } diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java index f546f13b..ae53dc3d 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java @@ -5,6 +5,7 @@ import android.content.Context; import android.location.LocationManager; import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.location.LocationServiceListener; public interface NmeaMessageaClient { void isLocationServiceEnabled(LocationServiceListener listener); From 22782391c579ee91afbfe4d0c81e4f6fe3970a1e Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 19:27:16 -0600 Subject: [PATCH 08/25] fix formatting --- .../lib/src/models/nmea_message.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/geolocator_platform_interface/lib/src/models/nmea_message.dart b/geolocator_platform_interface/lib/src/models/nmea_message.dart index feda4c96..3d457b36 100644 --- a/geolocator_platform_interface/lib/src/models/nmea_message.dart +++ b/geolocator_platform_interface/lib/src/models/nmea_message.dart @@ -30,8 +30,8 @@ class NmeaMessage { final timestamp = nmeaMessageMap['timestamp'] != null ? DateTime.fromMillisecondsSinceEpoch( - nmeaMessageMap['timestamp'].toInt(), - isUtc: true) + nmeaMessageMap['timestamp'].toInt(), + isUtc: true) : null; return NmeaMessage( @@ -43,9 +43,9 @@ class NmeaMessage { /// Converts the [NmeaMessage] instance into a [Map] instance that can be /// serialized to JSON. Map toJson() => { - 'message': message, - 'timestamp': timestamp?.millisecondsSinceEpoch, - }; + 'message': message, + 'timestamp': timestamp?.millisecondsSinceEpoch, + }; @override bool operator ==(Object other) { From c2649405b07233f9683c0a4d9cca937c9bde9713 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 21:18:45 -0600 Subject: [PATCH 09/25] fix error catching and dependency issues --- geolocator/pubspec.yaml | 7 +++++++ .../java/com/baseflow/geolocator/GeolocatorPlugin.java | 4 ++++ .../com/baseflow/geolocator/NmeaStreamHandlerImpl.java | 4 ++-- geolocator_android/example/pubspec.yaml | 5 +++++ geolocator_android/pubspec.yaml | 5 +++++ .../lib/src/geolocator_platform_interface.dart | 1 - .../lib/src/implementations/method_channel_geolocator.dart | 4 +--- .../implementations/method_channel_geolocator_test.dart | 2 +- 8 files changed, 25 insertions(+), 7 deletions(-) diff --git a/geolocator/pubspec.yaml b/geolocator/pubspec.yaml index 9e7c604e..b47089d3 100644 --- a/geolocator/pubspec.yaml +++ b/geolocator/pubspec.yaml @@ -35,3 +35,10 @@ dev_dependencies: flutter_lints: ^1.0.4 mockito: ^5.0.0-nullsafety.7 plugin_platform_interface: ^2.0.0 + +# TODO: REMOVE BEFORE MERGING +dependency_overrides: + geolocator_platform_interface: + path: ../geolocator_platform_interface/ + geolocator_android: + path: ../geolocator_android/ diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index 5ce70732..da09c8e4 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -72,6 +72,10 @@ public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registra LocationServiceHandlerImpl locationServiceHandler = new LocationServiceHandlerImpl(); locationServiceHandler.startListening(registrar.context(), registrar.messenger()); locationServiceHandler.setActivity(registrar.activity()); + + NmeaStreamHandlerImpl nmeaStreamHandler = new NmeaStreamHandlerImpl(geolocatorPlugin.nmeaMessageManager, geolocatorPlugin.permissionManager); + nmeaStreamHandler.startListening(registrar.context(), registrar.messenger()); + nmeaStreamHandler.setActivity(registrar.activity()); } @Override diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java index 59a6f7c4..4275c144 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java @@ -98,8 +98,8 @@ public void onListen(Object arguments, EventChannel.EventSink events) { this.nmeaMessageaClient, activity, (String message, long timestamp) -> events.success(toMap(message, timestamp)), - (ErrorCodes errorCodes) -> - events.error(errorCodes.toString(), errorCodes.toDescription(), null)); + (ErrorCodes errorCodes) -> + events.error(errorCodes.toString(), errorCodes.toDescription(), null)); } @Override diff --git a/geolocator_android/example/pubspec.yaml b/geolocator_android/example/pubspec.yaml index 9392a132..a6f4fad4 100644 --- a/geolocator_android/example/pubspec.yaml +++ b/geolocator_android/example/pubspec.yaml @@ -37,6 +37,11 @@ dev_dependencies: sdk: flutter flutter_lints: ^1.0.4 +# TODO: REMOVE BEFORE MERGING +dependency_overrides: + geolocator_platform_interface: + path: ../../geolocator_platform_interface/ + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/geolocator_android/pubspec.yaml b/geolocator_android/pubspec.yaml index dc079713..12b3c99e 100644 --- a/geolocator_android/pubspec.yaml +++ b/geolocator_android/pubspec.yaml @@ -26,3 +26,8 @@ dev_dependencies: flutter_lints: ^1.0.4 mockito: ^5.0.0-nullsafety.7 plugin_platform_interface: ^2.0.0 + +# TODO: REMOVE BEFORE MERGING +dependency_overrides: + geolocator_platform_interface: + path: ../geolocator_platform_interface/ \ No newline at end of file diff --git a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart index 7cf3f60a..19b35504 100644 --- a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart +++ b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart @@ -7,7 +7,6 @@ import 'package:vector_math/vector_math.dart'; import 'enums/enums.dart'; import 'implementations/method_channel_geolocator.dart'; import 'models/models.dart'; -import 'models/nmea_message.dart'; /// The interface that implementations of geolocator must implement. /// diff --git a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart index 95e7a020..4150fe8a 100644 --- a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart +++ b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart @@ -213,13 +213,11 @@ class MethodChannelGeolocator extends GeolocatorPlatform { (error) { _nmeaMessageStream = null; if (error is PlatformException) { - _handlePlatformException(error); + error = _handlePlatformException(error); } - throw error; }, ); - return _nmeaMessageStream!; } diff --git a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart index 24cd26e1..4f44133b 100644 --- a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart +++ b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart @@ -1039,7 +1039,7 @@ void main() { group( // ignore: lines_longer_than_80_chars - 'getServiceStream: When requesting a stream of location service status and NMEA updates', + 'getNmeaMessageStream: When requesting a stream of location service status and NMEA updates', () { group( 'And requesting for NMEA and location service status updates multiple times', From 33983e24d46cd11e5d291ce0083fa455ddd4c296 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 21:28:50 -0600 Subject: [PATCH 10/25] override dependency in example pubspec --- geolocator/example/pubspec.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/geolocator/example/pubspec.yaml b/geolocator/example/pubspec.yaml index 1f5b16eb..48e80c44 100644 --- a/geolocator/example/pubspec.yaml +++ b/geolocator/example/pubspec.yaml @@ -37,6 +37,11 @@ dev_dependencies: sdk: flutter flutter_lints: ^1.0.4 +# TODO: REMOVE BEFORE MERGING +dependency_overrides: + geolocator_platform_interface: + path: ../geolocator_platform_interface/ + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From affa8a0565acf135e1a48836b828275ae7b486ce Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 21:36:16 -0600 Subject: [PATCH 11/25] fix path --- geolocator/example/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geolocator/example/pubspec.yaml b/geolocator/example/pubspec.yaml index 48e80c44..ec03788d 100644 --- a/geolocator/example/pubspec.yaml +++ b/geolocator/example/pubspec.yaml @@ -40,7 +40,7 @@ dev_dependencies: # TODO: REMOVE BEFORE MERGING dependency_overrides: geolocator_platform_interface: - path: ../geolocator_platform_interface/ + path: ../../geolocator_platform_interface/ # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From 2d2c8572ef64e5b5715a45fd89859e83c821e70e Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 5 Jan 2022 21:41:30 -0600 Subject: [PATCH 12/25] Update pubspec.yaml --- geolocator/example/pubspec.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geolocator/example/pubspec.yaml b/geolocator/example/pubspec.yaml index ec03788d..68db5571 100644 --- a/geolocator/example/pubspec.yaml +++ b/geolocator/example/pubspec.yaml @@ -41,6 +41,8 @@ dev_dependencies: dependency_overrides: geolocator_platform_interface: path: ../../geolocator_platform_interface/ + geolocator_android: + path: ../../geolocator_android/ # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From 80c52c92adbc485fa0e587ada825de9fa7ffc815 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Tue, 18 Jan 2022 10:58:40 -0600 Subject: [PATCH 13/25] add test to expand coverage --- geolocator/test/geolocator_test.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/geolocator/test/geolocator_test.dart b/geolocator/test/geolocator_test.dart index f26d8e8b..36adfa6c 100644 --- a/geolocator/test/geolocator_test.dart +++ b/geolocator/test/geolocator_test.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:geolocator/geolocator.dart'; import 'package:mockito/mockito.dart'; @@ -60,6 +61,12 @@ void main() { expect(position, mockPosition); }); + test('getCurrentPosition iOS', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + final position = await Geolocator.getCurrentPosition(); + expect(position, mockPosition); + }); + test('getLocationAccuracy', () async { final accuracy = await Geolocator.getLocationAccuracy(); From 11a37ad75a6cae262f84ec5280bcd5de3e922c48 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 19 Jan 2022 10:44:12 -0600 Subject: [PATCH 14/25] fix code coverage issue --- geolocator/lib/geolocator.dart | 7 +++---- geolocator/test/geolocator_test.dart | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/geolocator/lib/geolocator.dart b/geolocator/lib/geolocator.dart index b3b43ef3..c3ed6f33 100644 --- a/geolocator/lib/geolocator.dart +++ b/geolocator/lib/geolocator.dart @@ -5,10 +5,10 @@ import 'package:geolocator_android/geolocator_android.dart'; import 'package:geolocator_apple/geolocator_apple.dart'; import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; -export 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; export 'package:geolocator_android/geolocator_android.dart' show AndroidSettings; export 'package:geolocator_apple/geolocator_apple.dart' show AppleSettings; +export 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; /// Wraps CLLocationManager (on iOS) and FusedLocationProviderClient or /// LocationManager @@ -86,9 +86,8 @@ class Geolocator { ); } - return GeolocatorPlatform.instance.getCurrentPosition( - locationSettings: locationSettings, - ); + return GeolocatorPlatform.instance + .getCurrentPosition(locationSettings: locationSettings); } /// Returns a stream emitting NMEA-0183 sentences Android only, no-op on iOS. diff --git a/geolocator/test/geolocator_test.dart b/geolocator/test/geolocator_test.dart index 36adfa6c..2e9219ba 100644 --- a/geolocator/test/geolocator_test.dart +++ b/geolocator/test/geolocator_test.dart @@ -65,6 +65,7 @@ void main() { debugDefaultTargetPlatformOverride = TargetPlatform.iOS; final position = await Geolocator.getCurrentPosition(); expect(position, mockPosition); + debugDefaultTargetPlatformOverride = null; }); test('getLocationAccuracy', () async { From 05e5177dacd956f977a4e1b47be65981371b2e62 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Mon, 24 Jan 2022 11:18:45 -0600 Subject: [PATCH 15/25] fix export --- geolocator/lib/geolocator.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/geolocator/lib/geolocator.dart b/geolocator/lib/geolocator.dart index c4b8b354..094d7661 100644 --- a/geolocator/lib/geolocator.dart +++ b/geolocator/lib/geolocator.dart @@ -9,6 +9,7 @@ export 'package:geolocator_android/geolocator_android.dart' show AndroidSettings; export 'package:geolocator_apple/geolocator_apple.dart' show AppleSettings, ActivityType; +export 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; /// Wraps CLLocationManager (on iOS) and FusedLocationProviderClient or /// LocationManager From 76af741dafa6346f785fc9b6905bfd67e8e4fbbf Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Fri, 13 May 2022 14:25:49 -0700 Subject: [PATCH 16/25] Cleanup Nmea interfaces --- geolocator/lib/geolocator.dart | 6 +- geolocator/test/geolocator_test.dart | 6 +- .../baseflow/geolocator/GeolocatorPlugin.java | 14 ++--- .../geolocator/MethodCallHandlerImpl.java | 6 +- .../geolocator/NmeaStreamHandlerImpl.java | 57 ++++++++++++------- ...MessageClient.java => GnssNmeaClient.java} | 8 +-- ...meaMessageaClient.java => NmeaClient.java} | 2 +- ...eaMessageManager.java => NmeaManager.java} | 16 +++--- .../lib/src/geolocator_android.dart | 27 +++++++++ .../src/geolocator_platform_interface.dart | 5 +- .../method_channel_geolocator.dart | 14 ++--- .../lib/src/models/nmea_message.dart | 17 +++--- .../geolocator_platform_interface_test.dart | 4 +- .../method_channel_geolocator_test.dart | 18 +++--- 14 files changed, 116 insertions(+), 84 deletions(-) rename geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/{GnssNmeaMessageClient.java => GnssNmeaClient.java} (93%) rename geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/{NmeaMessageaClient.java => NmeaClient.java} (95%) rename geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/{NmeaMessageManager.java => NmeaManager.java} (73%) diff --git a/geolocator/lib/geolocator.dart b/geolocator/lib/geolocator.dart index 69f0bb8f..145b561a 100644 --- a/geolocator/lib/geolocator.dart +++ b/geolocator/lib/geolocator.dart @@ -103,7 +103,7 @@ class Geolocator { /// /// ``` /// StreamSubscription nmeaStream = - /// Geolocator.getNmeaMessageStream().listen((NmeaMessage nmea) { + /// Geolocator.getNmeaStream().listen((NmeaMessage nmea) { /// // Handle NMEA changes /// }); /// ``` @@ -117,8 +117,8 @@ class Geolocator { /// but the location services of the device are disabled. /// /// for more info about NMEA 0183 see https://en.wikipedia.org/wiki/NMEA_0183 - static Stream getNmeaMessageStream() => - GeolocatorPlatform.instance.getNmeaMessageStream(); + static Stream getNmeaStream() => + GeolocatorPlatform.instance.getNmeaStream(); /// Fires whenever the location changes inside the bounds of the /// supplied [LocationSettings.accuracy]. diff --git a/geolocator/test/geolocator_test.dart b/geolocator/test/geolocator_test.dart index 2e9219ba..03c9f044 100644 --- a/geolocator/test/geolocator_test.dart +++ b/geolocator/test/geolocator_test.dart @@ -104,8 +104,8 @@ void main() { expect(position, emitsInOrder([emits(mockPosition), emitsDone])); }); - test('getNmeaMessageStream', () async { - final nmeaMessage = Geolocator.getNmeaMessageStream(); + test('getNmeaStream', () async { + final nmeaMessage = Geolocator.getNmeaStream(); expect(nmeaMessage, emitsInOrder([emits(mockNmeaMessage), emitsDone])); }); @@ -190,7 +190,7 @@ class MockGeolocatorPlatform extends Mock } @override - Stream getNmeaMessageStream() => Stream.value(mockNmeaMessage); + Stream getNmeaStream() => Stream.value(mockNmeaMessage); @override Future openAppSettings() => Future.value(true); diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index 86725a2e..278673c1 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -10,7 +10,6 @@ import androidx.annotation.Nullable; import com.baseflow.geolocator.location.GeolocationManager; -import com.baseflow.geolocator.nmea.NmeaMessageManager; import com.baseflow.geolocator.location.LocationAccuracyManager; import com.baseflow.geolocator.permission.PermissionManager; @@ -27,7 +26,6 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { private final PermissionManager permissionManager; private final GeolocationManager geolocationManager; private final LocationAccuracyManager locationAccuracyManager; - private final NmeaMessageManager nmeaMessageManager; @Nullable private GeolocatorLocationService foregroundLocationService; @@ -68,7 +66,6 @@ public GeolocatorPlugin() { permissionManager = new PermissionManager(); geolocationManager = new GeolocationManager(); locationAccuracyManager = new LocationAccuracyManager(); - nmeaMessageManager = new NmeaMessageManager(); } // This static function is optional and equivalent to onAttachedToEngine. It supports the old @@ -90,8 +87,7 @@ public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registra new MethodCallHandlerImpl( geolocatorPlugin.permissionManager, geolocatorPlugin.geolocationManager, - geolocatorPlugin.locationAccuracyManager, - geolocatorPlugin.nmeaMessageManager); + geolocatorPlugin.locationAccuracyManager); methodCallHandler.startListening(registrar.context(), registrar.messenger()); methodCallHandler.setActivity(registrar.activity()); @@ -102,7 +98,7 @@ public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registra locationServiceHandler.startListening(registrar.context(), registrar.messenger()); locationServiceHandler.setContext(registrar.activeContext()); - NmeaStreamHandlerImpl nmeaStreamHandler = new NmeaStreamHandlerImpl(geolocatorPlugin.nmeaMessageManager, geolocatorPlugin.permissionManager); + NmeaStreamHandlerImpl nmeaStreamHandler = new NmeaStreamHandlerImpl(geolocatorPlugin.permissionManager); nmeaStreamHandler.startListening(registrar.context(), registrar.messenger()); nmeaStreamHandler.setActivity(registrar.activity()); @@ -115,8 +111,7 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin new MethodCallHandlerImpl( this.permissionManager, this.geolocationManager, - this.locationAccuracyManager, - this.nmeaMessageManager); + this.locationAccuracyManager); methodCallHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); streamHandler = new StreamHandlerImpl(this.permissionManager); @@ -128,7 +123,7 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin locationServiceHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - nmeaStreamHandler = new NmeaStreamHandlerImpl(this.nmeaMessageManager, this.permissionManager); + nmeaStreamHandler = new NmeaStreamHandlerImpl(this.permissionManager); nmeaStreamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); @@ -254,6 +249,5 @@ private void dispose() { if (foregroundLocationService != null) { foregroundLocationService.setActivity(null); } - } } diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/MethodCallHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/MethodCallHandlerImpl.java index d58a66f9..c96209ac 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/MethodCallHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/MethodCallHandlerImpl.java @@ -17,7 +17,6 @@ import com.baseflow.geolocator.location.LocationClient; import com.baseflow.geolocator.location.LocationMapper; import com.baseflow.geolocator.location.LocationOptions; -import com.baseflow.geolocator.nmea.NmeaMessageManager; import com.baseflow.geolocator.permission.LocationPermission; import com.baseflow.geolocator.permission.PermissionManager; import com.baseflow.geolocator.utils.Utils; @@ -37,7 +36,6 @@ class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { private final PermissionManager permissionManager; private final GeolocationManager geolocationManager; private final LocationAccuracyManager locationAccuracyManager; - private final NmeaMessageManager nmeaMessageManager; @Nullable private Context context; @@ -46,12 +44,10 @@ class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { MethodCallHandlerImpl( PermissionManager permissionManager, GeolocationManager geolocationManager, - LocationAccuracyManager locationAccuracyManager, - NmeaMessageManager nmeaMessageManager) { + LocationAccuracyManager locationAccuracyManager) { this.permissionManager = permissionManager; this.geolocationManager = geolocationManager; this.locationAccuracyManager = locationAccuracyManager; - this.nmeaMessageManager = nmeaMessageManager; } @Nullable private MethodChannel channel; diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java index 4275c144..022e47cf 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java @@ -1,32 +1,32 @@ package com.baseflow.geolocator; -import android.app.Activity; import android.content.Context; import android.util.Log; + import androidx.annotation.Nullable; + import com.baseflow.geolocator.errors.ErrorCodes; import com.baseflow.geolocator.errors.PermissionUndefinedException; import com.baseflow.geolocator.permission.PermissionManager; -import com.baseflow.geolocator.nmea.NmeaMessageManager; -import com.baseflow.geolocator.nmea.NmeaMessageaClient; +import com.baseflow.geolocator.nmea.NmeaManager; +import com.baseflow.geolocator.nmea.NmeaClient; + import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; -import java.util.HashMap; -import java.util.Map; -class NmeaStreamHandlerImpl implements EventChannel.StreamHandler { - private static final String TAG = "NmeaStreamHandlerImpl"; +public class NmeaStreamHandlerImpl implements EventChannel.StreamHandler { + private static final String TAG = "FlutterGeolocator"; - private final NmeaMessageManager nmeaMessageManager; + private final NmeaManager nmeaManager; private final PermissionManager permissionManager; @Nullable private EventChannel channel; @Nullable private Context context; @Nullable private Activity activity; - @Nullable private NmeaMessageaClient nmeaMessageaClient; + @Nullable private NmeaClient nmeaClient; - public NmeaStreamHandlerImpl(NmeaMessageManager nmeaMessageManager, PermissionManager permissionManager) { - this.nmeaMessageManager = nmeaMessageManager; + public NmeaStreamHandlerImpl(PermissionManager permissionManager) { + this.nmeaManager = new NmeaManager(); this.permissionManager = permissionManager; } @@ -44,6 +44,11 @@ private static Map toMap(String message, Long timestamp) { } void setActivity(@Nullable Activity activity) { + + if (activity == null && nmeaClient != null && channel != null) { + stopListening(); + } + this.activity = activity; } @@ -60,7 +65,7 @@ void startListening(Context context, BinaryMessenger messenger) { stopListening(); } - channel = new EventChannel(messenger, "flutter.baseflow.com/nmea_updates"); + channel = new EventChannel(messenger, "flutter.baseflow.com/geolocator_nmea_updates_android"); channel.setStreamHandler(this); this.context = context; } @@ -76,6 +81,7 @@ void stopListening() { return; } + disposeListeners(); channel.setStreamHandler(null); channel = null; } @@ -84,18 +90,24 @@ void stopListening() { public void onListen(Object arguments, EventChannel.EventSink events) { try { if (!permissionManager.hasPermission(this.context)){ - events.error(ErrorCodes.permissionDenied.toString(),ErrorCodes.permissionDenied.toDescription(),null); + events.error( + ErrorCodes.permissionDenied.toString(), + ErrorCodes.permissionDenied.toDescription(), + null); return; } } catch (PermissionUndefinedException e) { - events.error(ErrorCodes.permissionDefinitionsNotFound.toString(), ErrorCodes.permissionDefinitionsNotFound.toDescription(), null); + events.error( + ErrorCodes.permissionDefinitionsNotFound.toString(), + ErrorCodes.permissionDefinitionsNotFound.toDescription(), + null); return; } - this.nmeaMessageaClient = nmeaMessageManager.createNmeaClient(this.context); + this.nmeaClient = nmeaManager.createNmeaClient(this.context); - nmeaMessageManager.startNmeaUpdates( - this.nmeaMessageaClient, + nmeaManager.startNmeaUpdates( + this.nmeaClient, activity, (String message, long timestamp) -> events.success(toMap(message, timestamp)), (ErrorCodes errorCodes) -> @@ -104,9 +116,16 @@ public void onListen(Object arguments, EventChannel.EventSink events) { @Override public void onCancel(Object arguments) { - if (this.nmeaMessageaClient != null) { - nmeaMessageManager.stopNmeaUpdates(this.nmeaMessageaClient); + if (this.nmeaClient != null) { + disposeListeners(); } } + private void disposeListeners() { + Log.e(TAG, "Geolocator nmea updates stopped"); + if (nmeaClient != null && nmeaManager != null) { + nmeaManager.stopNmeaUpdates(nmeaClient); + nmeaClient = null; + } + } } \ No newline at end of file diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaClient.java similarity index 93% rename from geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java rename to geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaClient.java index 3ea90c31..53fe92a4 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaMessageClient.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaClient.java @@ -6,7 +6,7 @@ import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; -import android.location.OnNmeaMessageListener; +import android.location.OnNmeaListener; import android.os.Looper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -16,8 +16,8 @@ @SuppressLint("NewApi") -public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationListener, - NmeaMessageaClient { +public class GnssNmeaClient implements OnNmeaListener, LocationListener, + NmeaClient { public Context context; private final LocationManager locationManager; @@ -30,7 +30,7 @@ public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationLis private boolean isListening = false; - public GnssNmeaMessageClient( + public GnssNmeaClient( @NonNull Context context) { this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); this.context = context; diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaClient.java similarity index 95% rename from geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java rename to geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaClient.java index ae53dc3d..b5cb89d6 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageaClient.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaClient.java @@ -7,7 +7,7 @@ import com.baseflow.geolocator.errors.ErrorCallback; import com.baseflow.geolocator.location.LocationServiceListener; -public interface NmeaMessageaClient { +public interface NmeaClient { void isLocationServiceEnabled(LocationServiceListener listener); void startNmeaUpdates(Activity activity, NmeaChangedCallback nmeaChangedCallback, diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaManager.java similarity index 73% rename from geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java rename to geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaManager.java index 47f1bb3f..e8882c82 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaMessageManager.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/NmeaManager.java @@ -12,9 +12,9 @@ import com.baseflow.geolocator.location.LocationServiceListener; import com.baseflow.geolocator.permission.PermissionManager; -public class NmeaMessageManager { +public class NmeaManager { - public NmeaMessageManager() {} + public NmeaManager() {} public void isLocationServiceEnabled( @Nullable Context context, LocationServiceListener listener) { @@ -22,12 +22,12 @@ public void isLocationServiceEnabled( listener.onLocationServiceError(ErrorCodes.locationServicesDisabled); } - NmeaMessageaClient nmeaMessageaClient = createNmeaClient(context); - nmeaMessageaClient.isLocationServiceEnabled(listener); + NmeaClient nmeaClient = createNmeaClient(context); + nmeaClient.isLocationServiceEnabled(listener); } public void startNmeaUpdates( - @NonNull NmeaMessageaClient client, + @NonNull NmeaClient client, @Nullable Activity activity, @NonNull NmeaChangedCallback nmeaChangedCallback, @NonNull ErrorCallback errorCallback) { @@ -35,14 +35,14 @@ public void startNmeaUpdates( client.startNmeaUpdates(activity, nmeaChangedCallback, errorCallback); } - public void stopNmeaUpdates(NmeaMessageaClient client) { + public void stopNmeaUpdates(NmeaClient client) { client.stopNmeaUpdates(); } @RequiresApi(api = VERSION_CODES.N) - public NmeaMessageaClient createNmeaClient( + public NmeaClient createNmeaClient( Context context) { - return new GnssNmeaMessageClient(context); + return new GnssNmeaClient(context); } } \ No newline at end of file diff --git a/geolocator_android/lib/src/geolocator_android.dart b/geolocator_android/lib/src/geolocator_android.dart index 8dc27edb..598932c8 100644 --- a/geolocator_android/lib/src/geolocator_android.dart +++ b/geolocator_android/lib/src/geolocator_android.dart @@ -19,6 +19,11 @@ class GeolocatorAndroid extends GeolocatorPlatform { static const _serviceStatusEventChannel = EventChannel('flutter.baseflow.com/geolocator_service_updates_android'); + /// The event channel used to receive [NmeaMessage] updates from the + /// native platform. + static const _nmeaEventChannel = + EventChannel('flutter.baseflow.com/geolocator_nmea_updates_android'); + /// Registers this class as the default instance of [GeolocatorPlatform]. static void registerWith() { GeolocatorPlatform.instance = GeolocatorAndroid(); @@ -31,6 +36,7 @@ class GeolocatorAndroid extends GeolocatorPlatform { bool forcedLocationManager = false; Stream? _positionStream; + Stream? _nmeaStream; Stream? _serviceStatusStream; @override @@ -148,6 +154,27 @@ class GeolocatorAndroid extends GeolocatorPlatform { return _serviceStatusStream!; } + @override + Stream getNmeaStream() { + if (_nmeaStream != null) { + return _nmeaStream!; + } + var nmeaMessagesStream = _nmeaEventChannel.receiveBroadcastStream(); + + _nmeaStream = nmeaMessagesStream + .map((dynamic element) => + NmeaMessage.fromMap(element.cast())) + .handleError((error) { + _nmeaStream = null; + if (error is PlatformException) { + error = _handlePlatformException(error); + } + throw error; + }); + + return _nmeaStream!; + } + @override Stream getPositionStream({ LocationSettings? locationSettings, diff --git a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart index 63f8c063..6ac16895 100644 --- a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart +++ b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart @@ -149,9 +149,8 @@ abstract class GeolocatorPlatform extends PlatformInterface { /// but the location services of the device are disabled. /// /// for more info about NMEA 0183 see https://en.wikipedia.org/wiki/NMEA_0183 - Stream getNmeaMessageStream() { - throw UnimplementedError( - 'getNmeaMessageStream() has not been implemented.'); + Stream getNmeaStream() { + throw UnimplementedError('getNmeaStream() has not been implemented.'); } /// Fires whenever the location changes inside the bounds of the diff --git a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart index 86734a26..83bff1f1 100644 --- a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart +++ b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart @@ -39,7 +39,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform { Stream? _positionStream; Stream? _serviceStatusStream; - Stream? _nmeaMessageStream; + Stream? _nmeaStream; @override Future checkPermission() async { @@ -199,26 +199,26 @@ class MethodChannelGeolocator extends GeolocatorPlatform { } @override - Stream getNmeaMessageStream() { - if (_nmeaMessageStream != null) { - return _nmeaMessageStream!; + Stream getNmeaStream() { + if (_nmeaStream != null) { + return _nmeaStream!; } final nmeaStream = _nmeaEventChannel.receiveBroadcastStream(); - _nmeaMessageStream = nmeaStream + _nmeaStream = nmeaStream .map((dynamic element) => NmeaMessage.fromMap(element.cast())) .handleError( (error) { - _nmeaMessageStream = null; + _nmeaStream = null; if (error is PlatformException) { error = _handlePlatformException(error); } throw error; }, ); - return _nmeaMessageStream!; + return _nmeaStream!; } Stream _wrapStream(Stream incoming) { diff --git a/geolocator_platform_interface/lib/src/models/nmea_message.dart b/geolocator_platform_interface/lib/src/models/nmea_message.dart index 3d457b36..eeea465d 100644 --- a/geolocator_platform_interface/lib/src/models/nmea_message.dart +++ b/geolocator_platform_interface/lib/src/models/nmea_message.dart @@ -16,26 +16,25 @@ class NmeaMessage { /// Converts the supplied [Map] to an instance of the [NmeaMessage] class. static NmeaMessage fromMap(Map message) { - final Map nmeaMessageMap = message; + final Map nmeaMap = message; - if (!nmeaMessageMap.containsKey('message')) { - throw ArgumentError.value(nmeaMessageMap, 'nmeaMessageMap', + if (!nmeaMap.containsKey('message')) { + throw ArgumentError.value(nmeaMap, 'nmeaMap', 'The supplied map doesn\'t contain the mandatory key `message`.'); } - if (!nmeaMessageMap.containsKey('timestamp')) { - throw ArgumentError.value(nmeaMessageMap, 'nmeaMessageMap', + if (!nmeaMap.containsKey('timestamp')) { + throw ArgumentError.value(nmeaMap, 'nmeaMap', 'The supplied map doesn\'t contain the mandatory key `timestamp`.'); } - final timestamp = nmeaMessageMap['timestamp'] != null - ? DateTime.fromMillisecondsSinceEpoch( - nmeaMessageMap['timestamp'].toInt(), + final timestamp = nmeaMap['timestamp'] != null + ? DateTime.fromMillisecondsSinceEpoch(nmeaMap['timestamp'].toInt(), isUtc: true) : null; return NmeaMessage( - nmeaMessageMap['message'], + nmeaMap['message'], timestamp, ); } diff --git a/geolocator_platform_interface/test/geolocator_platform_interface_test.dart b/geolocator_platform_interface/test/geolocator_platform_interface_test.dart index 0e730448..5d2fcb00 100644 --- a/geolocator_platform_interface/test/geolocator_platform_interface_test.dart +++ b/geolocator_platform_interface/test/geolocator_platform_interface_test.dart @@ -160,14 +160,14 @@ void main() { test( // ignore: lines_longer_than_80_chars - 'Default implementation of getNmeaMessageStream should throw unimplemented error', + 'Default implementation of getNmeaStream should throw unimplemented error', () { // Arrange final geolocatorPlatform = ExtendsGeolocatorPlatform(); // Act & Assert expect( - geolocatorPlatform.getNmeaMessageStream, + geolocatorPlatform.getNmeaStream, throwsUnimplementedError, ); }); diff --git a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart index 7a755cbf..6bcba5c5 100644 --- a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart +++ b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart @@ -1085,7 +1085,7 @@ void main() { group( // ignore: lines_longer_than_80_chars - 'getNmeaMessageStream: When requesting a stream of location service status and NMEA updates', + 'getNmeaStream: When requesting a stream of location service status and NMEA updates', () { group( 'And requesting for NMEA and location service status updates multiple times', @@ -1100,10 +1100,8 @@ void main() { true, ); - final firstStreamNmea = - methodChannelGeolocator.getNmeaMessageStream(); - final secondStreamNmea = - methodChannelGeolocator.getNmeaMessageStream(); + final firstStreamNmea = methodChannelGeolocator.getNmeaStream(); + final secondStreamNmea = methodChannelGeolocator.getNmeaStream(); expect( identical(firstStreamNmea, secondStreamNmea), @@ -1153,7 +1151,7 @@ void main() { ); // Act - final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final nmeaStream = MethodChannelGeolocator().getNmeaStream(); final streamQueue = StreamQueue(nmeaStream); // Emit test events @@ -1223,7 +1221,7 @@ void main() { ); // Act - final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final nmeaStream = MethodChannelGeolocator().getNmeaStream(); final streamQueue = StreamQueue(nmeaStream); // Emit test error @@ -1256,7 +1254,7 @@ void main() { ); // Act - final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final nmeaStream = MethodChannelGeolocator().getNmeaStream(); final streamQueue = StreamQueue(nmeaStream); // Emit test error @@ -1289,7 +1287,7 @@ void main() { ); // Act - final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final nmeaStream = MethodChannelGeolocator().getNmeaStream(); final streamQueue = StreamQueue(nmeaStream); // Emit test error @@ -1322,7 +1320,7 @@ void main() { ); // Act - final nmeaStream = MethodChannelGeolocator().getNmeaMessageStream(); + final nmeaStream = MethodChannelGeolocator().getNmeaStream(); final streamQueue = StreamQueue(nmeaStream); // Emit test error From bebd9aa95811b07f8a87f9e659202c5b0e1b7d72 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Fri, 13 May 2022 14:34:31 -0700 Subject: [PATCH 17/25] fix imports --- .../java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java | 3 +++ .../java/com/baseflow/geolocator/nmea/GnssNmeaClient.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java index 022e47cf..3f261fa1 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/NmeaStreamHandlerImpl.java @@ -1,5 +1,6 @@ package com.baseflow.geolocator; +import android.app.Activity; import android.content.Context; import android.util.Log; @@ -13,6 +14,8 @@ import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; +import java.util.HashMap; +import java.util.Map; public class NmeaStreamHandlerImpl implements EventChannel.StreamHandler { private static final String TAG = "FlutterGeolocator"; diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaClient.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaClient.java index 53fe92a4..40855f20 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaClient.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/nmea/GnssNmeaClient.java @@ -6,7 +6,7 @@ import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; -import android.location.OnNmeaListener; +import android.location.OnNmeaMessageListener; import android.os.Looper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -16,7 +16,7 @@ @SuppressLint("NewApi") -public class GnssNmeaClient implements OnNmeaListener, LocationListener, +public class GnssNmeaClient implements OnNmeaMessageListener, LocationListener, NmeaClient { public Context context; From e0845ab47dfeecfa43272533f6bc9fe1c7b4c90e Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Sun, 15 May 2022 11:12:04 -0700 Subject: [PATCH 18/25] Fix code coverage --- geolocator/test/geolocator_test.dart | 5 +- .../lib/geolocator_android.dart | 3 + .../lib/src/geolocator_android.dart | 17 +- .../test/geolocator_android_test.dart | 354 +++++++++++++++++- .../lib/src/errors/errors.dart | 2 + .../nmea_already_subscribed_exception.dart | 11 + .../lib/src/errors/nmea_update_exception.dart | 18 + .../method_channel_geolocator.dart | 4 + .../lib/src/models/nmea_message.dart | 6 +- ...mea_already_subscribed_exception_test.dart | 18 + .../errors/nmea_update_exception_test.dart | 42 +++ .../method_channel_geolocator_test.dart | 25 +- .../test/src/models/nmea_test.dart | 26 +- 13 files changed, 499 insertions(+), 32 deletions(-) create mode 100644 geolocator_platform_interface/lib/src/errors/nmea_already_subscribed_exception.dart create mode 100644 geolocator_platform_interface/lib/src/errors/nmea_update_exception.dart create mode 100644 geolocator_platform_interface/test/src/errors/nmea_already_subscribed_exception_test.dart create mode 100644 geolocator_platform_interface/test/src/errors/nmea_update_exception_test.dart diff --git a/geolocator/test/geolocator_test.dart b/geolocator/test/geolocator_test.dart index 03c9f044..5b1a9690 100644 --- a/geolocator/test/geolocator_test.dart +++ b/geolocator/test/geolocator_test.dart @@ -18,8 +18,9 @@ Position get mockPosition => Position( speedAccuracy: 0.0); NmeaMessage get mockNmeaMessage => NmeaMessage( - "GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75", - DateTime.fromMillisecondsSinceEpoch( + message: + "GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75", + timestamp: DateTime.fromMillisecondsSinceEpoch( 500, isUtc: true, )); diff --git a/geolocator_android/lib/geolocator_android.dart b/geolocator_android/lib/geolocator_android.dart index 35b6d84e..cb636a99 100644 --- a/geolocator_android/lib/geolocator_android.dart +++ b/geolocator_android/lib/geolocator_android.dart @@ -8,6 +8,9 @@ export 'package:geolocator_platform_interface/geolocator_platform_interface.dart LocationPermission, LocationServiceDisabledException, LocationSettings, + NmeaAlreadySubscribedException, + NmeaMessage, + NmeaUpdateException, PermissionDefinitionsNotFoundException, PermissionDeniedException, PermissionRequestInProgressException, diff --git a/geolocator_android/lib/src/geolocator_android.dart b/geolocator_android/lib/src/geolocator_android.dart index 598932c8..1eb7f0dc 100644 --- a/geolocator_android/lib/src/geolocator_android.dart +++ b/geolocator_android/lib/src/geolocator_android.dart @@ -159,9 +159,11 @@ class GeolocatorAndroid extends GeolocatorPlatform { if (_nmeaStream != null) { return _nmeaStream!; } - var nmeaMessagesStream = _nmeaEventChannel.receiveBroadcastStream(); + var originalStream = _nmeaEventChannel.receiveBroadcastStream(); - _nmeaStream = nmeaMessagesStream + var nmeaStream = _wrapNmeaStream(originalStream); + + _nmeaStream = nmeaStream .map((dynamic element) => NmeaMessage.fromMap(element.cast())) .handleError((error) { @@ -224,6 +226,13 @@ class GeolocatorAndroid extends GeolocatorPlatform { }); } + Stream _wrapNmeaStream(Stream incoming) { + return incoming.asBroadcastStream(onCancel: (subscription) { + subscription.cancel(); + _nmeaStream = null; + }); + } + @override Future requestTemporaryFullAccuracy({ required String purposeKey, @@ -268,6 +277,10 @@ class GeolocatorAndroid extends GeolocatorPlatform { return PermissionRequestInProgressException(exception.message); case 'LOCATION_UPDATE_FAILURE': return PositionUpdateException(exception.message); + case 'NMEA_SUBSCRIPTION_ACTIVE': + return const NmeaAlreadySubscribedException(); + case 'NMEA_UPDATE_FAILURE': + return NmeaUpdateException(exception.message); default: return exception; } diff --git a/geolocator_android/test/geolocator_android_test.dart b/geolocator_android/test/geolocator_android_test.dart index d1550548..6eebf167 100644 --- a/geolocator_android/test/geolocator_android_test.dart +++ b/geolocator_android/test/geolocator_android_test.dart @@ -22,6 +22,14 @@ Position get mockPosition => Position( speedAccuracy: 0.0, isMocked: false); +NmeaMessage get mockNmeaMessage => NmeaMessage( + message: + "GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75", + timestamp: DateTime.fromMillisecondsSinceEpoch( + 500, + isUtc: true, + )); + void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -1074,6 +1082,348 @@ void main() { }); }); + group('getNmeaStream: When requesting a stream of nmea updates', () { + group('And requesting for nmea update multiple times', () { + test('Should return the same stream', () { + final plugin = GeolocatorAndroid(); + final firstStream = plugin.getNmeaStream(); + final secondStream = plugin.getNmeaStream(); + + expect( + identical(firstStream, secondStream), + true, + ); + }); + + test('Should return a new stream when all subscriptions are cancelled', + () { + final plugin = GeolocatorAndroid(); + + // Get two nmea streams + final firstStream = plugin.getNmeaStream(); + final secondStream = plugin.getNmeaStream(); + + // Streams are the same object + expect(firstStream == secondStream, true); + + // Add multiple subscriptions + StreamSubscription? firstSubscription = + firstStream.listen((event) {}); + StreamSubscription? secondSubscription = + secondStream.listen((event) {}); + + // Cancel first subscription + firstSubscription.cancel(); + firstSubscription = null; + + // Stream is still the same as the first one + final cachedStream = plugin.getNmeaStream(); + expect(firstStream == cachedStream, true); + + // Cancel second subscription + secondSubscription.cancel(); + secondSubscription = null; + + // After all listeners have been removed, the next stream + // retrieved is a new one. + final thirdStream = plugin.getNmeaStream(); + expect(firstStream != thirdStream, true); + }); + }); + + test('NmeaStream can be listened to and can be canceled', () { + // Arrange + final streamController = + StreamController>.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + var stream = GeolocatorAndroid().getNmeaStream(); + StreamSubscription? streamSubscription = + stream.listen((event) {}); + + streamSubscription.pause(); + expect(streamSubscription.isPaused, true); + streamSubscription.resume(); + expect(streamSubscription.isPaused, false); + streamSubscription.cancel(); + streamSubscription = null; + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should correctly handle done event', () async { + // Arrange + final completer = Completer(); + completer.future.timeout(const Duration(milliseconds: 50), + onTimeout: () => + fail('getNmeaStream should trigger done and not timeout.')); + final streamController = + StreamController>.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + // Act + GeolocatorAndroid().getNmeaStream().listen( + (event) {}, + onDone: completer.complete, + ); + + await streamController.close(); + + //Assert + await completer.future; + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a stream with nmea updates if permissions are granted', + () async { + // Arrange + final streamController = + StreamController>.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + // Act + final nmeaStream = GeolocatorAndroid().getNmeaStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test events + streamController.add(mockNmeaMessage.toJson()); + streamController.add(mockNmeaMessage.toJson()); + streamController.add(mockNmeaMessage.toJson()); + + // Assert + expect(await streamQueue.next, mockNmeaMessage); + expect(await streamQueue.next, mockNmeaMessage); + expect(await streamQueue.next, mockNmeaMessage); + + // Clean up + await streamQueue.cancel(); + await streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should continue listening to the stream when exception is thrown ', + () async { + // Arrange + final streamController = + StreamController>.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + // Act + final nmeaStream = GeolocatorAndroid().getNmeaStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test events + streamController.add(mockNmeaMessage.toJson()); + streamController.addError(PlatformException( + code: 'PERMISSION_DENIED', + message: 'Permission denied', + details: null)); + streamController.add(mockNmeaMessage.toJson()); + + // Assert + expect(await streamQueue.next, mockNmeaMessage); + expect( + streamQueue.next, + throwsA( + isA().having( + (e) => e.message, + 'message', + 'Permission denied', + ), + )); + expect(await streamQueue.next, mockNmeaMessage); + + // Clean up + await streamQueue.cancel(); + await streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a permission denied exception if permission is denied', + () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + // Act + final nmeaStream = GeolocatorAndroid().getNmeaStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'PERMISSION_DENIED', + message: 'Permission denied', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA().having( + (e) => e.message, + 'message', + 'Permission denied', + ), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a location service disabled exception if location service is disabled', + () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + // Act + final nmeaStream = GeolocatorAndroid().getNmeaStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'LOCATION_SERVICES_DISABLED', + message: 'Location services disabled', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA(), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a already subscribed exception', () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + // Act + final nmeaStream = GeolocatorAndroid().getNmeaStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'PERMISSION_REQUEST_IN_PROGRESS', + message: 'A permission request is already in progress', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA(), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a already subscribed exception', () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + // Act + final nmeaStream = GeolocatorAndroid().getNmeaStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'LOCATION_SUBSCRIPTION_ACTIVE', + message: 'Already subscribed to receive a nmea stream', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA(), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); + + test( + // ignore: lines_longer_than_80_chars + 'Should receive a nmea update exception', () async { + // Arrange + final streamController = + StreamController.broadcast(); + EventChannelMock( + channelName: 'flutter.baseflow.com/geolocator_nmea_updates_android', + stream: streamController.stream, + ); + + // Act + final nmeaStream = GeolocatorAndroid().getNmeaStream(); + final streamQueue = StreamQueue(nmeaStream); + + // Emit test error + streamController.addError(PlatformException( + code: 'NMEA_UPDATE_FAILURE', + message: 'A nmea request is already in progress', + details: null)); + + // Assert + expect( + streamQueue.next, + throwsA( + isA(), + )); + + // Clean up + streamQueue.cancel(); + streamController.close(); + }); + }); + group( // ignore: lines_longer_than_80_chars 'getServiceStream: When requesting a stream of location service status updates', @@ -1083,10 +1433,10 @@ void main() { test('Should return the same stream', () { final plugin = GeolocatorAndroid(); final firstStream = plugin.getServiceStatusStream(); - final secondstream = plugin.getServiceStatusStream(); + final secondStream = plugin.getServiceStatusStream(); expect( - identical(firstStream, secondstream), + identical(firstStream, secondStream), true, ); }); diff --git a/geolocator_platform_interface/lib/src/errors/errors.dart b/geolocator_platform_interface/lib/src/errors/errors.dart index 3bbfcfe5..611fcf00 100644 --- a/geolocator_platform_interface/lib/src/errors/errors.dart +++ b/geolocator_platform_interface/lib/src/errors/errors.dart @@ -2,6 +2,8 @@ export 'activity_missing_exception.dart'; export 'already_subscribed_exception.dart'; export 'invalid_permission_exception.dart'; export 'location_service_disabled_exception.dart'; +export 'nmea_already_subscribed_exception.dart'; +export 'nmea_update_exception.dart'; export 'permission_definitions_not_found_exception.dart'; export 'permission_denied_exception.dart'; export 'permission_request_in_progress_exception.dart'; diff --git a/geolocator_platform_interface/lib/src/errors/nmea_already_subscribed_exception.dart b/geolocator_platform_interface/lib/src/errors/nmea_already_subscribed_exception.dart new file mode 100644 index 00000000..b9a90f2a --- /dev/null +++ b/geolocator_platform_interface/lib/src/errors/nmea_already_subscribed_exception.dart @@ -0,0 +1,11 @@ +/// An exception thrown when subscribing to receive positions while another +/// subscription is already active. +class NmeaAlreadySubscribedException implements Exception { + /// Constructs the [NmeaAlreadySubscribedException] + const NmeaAlreadySubscribedException(); + + @override + String toString() => + 'The App is already listening to a stream of nmea updates. It is not ' + 'possible to listen to more then one stream at the same time.'; +} diff --git a/geolocator_platform_interface/lib/src/errors/nmea_update_exception.dart b/geolocator_platform_interface/lib/src/errors/nmea_update_exception.dart new file mode 100644 index 00000000..0ade4694 --- /dev/null +++ b/geolocator_platform_interface/lib/src/errors/nmea_update_exception.dart @@ -0,0 +1,18 @@ +/// An exception thrown when something went wrong while listening for position +/// updates. +class NmeaUpdateException implements Exception { + /// Constructs the [NmeaUpdateException] + const NmeaUpdateException(this.message); + + /// A [message] describing more details on the update exception + final String? message; + + @override + String toString() { + if (message == null || message == '') { + return 'Something went wrong while listening for nmea updates.'; + } + + return message!; + } +} diff --git a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart index 83bff1f1..8f64a20e 100644 --- a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart +++ b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart @@ -272,6 +272,10 @@ class MethodChannelGeolocator extends GeolocatorPlatform { return PermissionRequestInProgressException(exception.message); case 'LOCATION_UPDATE_FAILURE': return PositionUpdateException(exception.message); + case 'NMEA_SUBSCRIPTION_ACTIVE': + return const NmeaAlreadySubscribedException(); + case 'NMEA_UPDATE_FAILURE': + return NmeaUpdateException(exception.message); default: return exception; } diff --git a/geolocator_platform_interface/lib/src/models/nmea_message.dart b/geolocator_platform_interface/lib/src/models/nmea_message.dart index eeea465d..b22dfb66 100644 --- a/geolocator_platform_interface/lib/src/models/nmea_message.dart +++ b/geolocator_platform_interface/lib/src/models/nmea_message.dart @@ -5,7 +5,7 @@ import 'package:meta/meta.dart'; /// Contains all the NMEA information. class NmeaMessage { /// Constructs a NMEA message instance with the given values. - const NmeaMessage(this.message, this.timestamp); + const NmeaMessage({required this.message, required this.timestamp}); /// The full NMEA-0183 message, as reported by the GNSS chipset. final String message; @@ -34,8 +34,8 @@ class NmeaMessage { : null; return NmeaMessage( - nmeaMap['message'], - timestamp, + message: nmeaMap['message'], + timestamp: timestamp, ); } diff --git a/geolocator_platform_interface/test/src/errors/nmea_already_subscribed_exception_test.dart b/geolocator_platform_interface/test/src/errors/nmea_already_subscribed_exception_test.dart new file mode 100644 index 00000000..4896a7a7 --- /dev/null +++ b/geolocator_platform_interface/test/src/errors/nmea_already_subscribed_exception_test.dart @@ -0,0 +1,18 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; + +void main() { + test('toString: Should return a description of the exception', () { + // Arrange + const expected = 'The App is already listening to a stream of nmea ' + 'updates. It is not possible to listen to more then one stream at the ' + 'same time.'; + const exception = NmeaAlreadySubscribedException(); + + // Act + final actual = exception.toString(); + + // Assert + expect(actual, expected); + }); +} diff --git a/geolocator_platform_interface/test/src/errors/nmea_update_exception_test.dart b/geolocator_platform_interface/test/src/errors/nmea_update_exception_test.dart new file mode 100644 index 00000000..ccbd4c68 --- /dev/null +++ b/geolocator_platform_interface/test/src/errors/nmea_update_exception_test.dart @@ -0,0 +1,42 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; + +void main() { + test('toString: Should return the default description when message is null', + () { + // Arrange + const expected = 'Something went wrong while listening for nmea updates.'; + const exception = NmeaUpdateException(null); + + // Act + final actual = exception.toString(); + + // Assert + expect(actual, expected); + }); + + test('toString: Should return the default description when message is empty', + () { + // Arrange + const expected = 'Something went wrong while listening for nmea updates.'; + const exception = NmeaUpdateException(''); + + // Act + final actual = exception.toString(); + + // Assert + expect(actual, expected); + }); + + test('toString: Should return the message as description', () { + // Arrange + const expected = 'Dummy error message.'; + const exception = NmeaUpdateException(expected); + + // Act + final actual = exception.toString(); + + // Assert + expect(actual, expected); + }); +} diff --git a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart index 6bcba5c5..faa1b23a 100644 --- a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart +++ b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart @@ -24,8 +24,9 @@ Position get mockPosition => Position( isMocked: false); NmeaMessage get mockNmeaMessage => NmeaMessage( - "GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75", - DateTime.fromMillisecondsSinceEpoch( + message: + "GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75", + timestamp: DateTime.fromMillisecondsSinceEpoch( 500, isUtc: true, )); @@ -908,7 +909,8 @@ void main() { test( // ignore: lines_longer_than_80_chars - 'Should receive a already subscribed exception', () async { + 'Should receive a permission request is already in progress exception', + () async { // Arrange final streamController = StreamController.broadcast(); @@ -1244,7 +1246,8 @@ void main() { test( // ignore: lines_longer_than_80_chars - 'Should receive a already subscribed exception', () async { + 'Should receive a permission request is already in progress exception', + () async { // Arrange final streamController = StreamController.broadcast(); @@ -1292,15 +1295,15 @@ void main() { // Emit test error streamController.addError(PlatformException( - code: 'LOCATION_SUBSCRIPTION_ACTIVE', - message: 'Already subscribed to receive a position stream', + code: 'NMEA_SUBSCRIPTION_ACTIVE', + message: 'Already subscribed to receive a nmea stream', details: null)); // Assert expect( streamQueue.next, throwsA( - isA(), + isA(), )); // Clean up @@ -1310,7 +1313,7 @@ void main() { test( // ignore: lines_longer_than_80_chars - 'Should receive a position update exception', () async { + 'Should receive a nmea update exception', () async { // Arrange final streamController = StreamController.broadcast(); @@ -1325,15 +1328,15 @@ void main() { // Emit test error streamController.addError(PlatformException( - code: 'LOCATION_UPDATE_FAILURE', - message: 'A permission request is already in progress', + code: 'NMEA_UPDATE_FAILURE', + message: 'A nmea request is already in progress', details: null)); // Assert expect( streamQueue.next, throwsA( - isA(), + isA(), )); // Clean up diff --git a/geolocator_platform_interface/test/src/models/nmea_test.dart b/geolocator_platform_interface/test/src/models/nmea_test.dart index fcc4536a..64d2bc02 100644 --- a/geolocator_platform_interface/test/src/models/nmea_test.dart +++ b/geolocator_platform_interface/test/src/models/nmea_test.dart @@ -6,10 +6,12 @@ void main() { test('hashCode should be the same for two instances with the same values', () { // Arrange - final firstNmeaMessage = - NmeaMessage("message", DateTime.fromMicrosecondsSinceEpoch(500)); - final secondNmeaMessage = - NmeaMessage("message", DateTime.fromMicrosecondsSinceEpoch(500)); + final firstNmeaMessage = NmeaMessage( + message: "message", + timestamp: DateTime.fromMicrosecondsSinceEpoch(500)); + final secondNmeaMessage = NmeaMessage( + message: "message", + timestamp: DateTime.fromMicrosecondsSinceEpoch(500)); // Act & Assert expect( @@ -22,12 +24,12 @@ void main() { () { // Arrange final firstNmeaMessage = NmeaMessage( - "first", - DateTime.fromMillisecondsSinceEpoch(0), + message: "first", + timestamp: DateTime.fromMillisecondsSinceEpoch(0), ); final secondNmeaMessage = NmeaMessage( - "second", - DateTime.fromMillisecondsSinceEpoch(0), + message: "second", + timestamp: DateTime.fromMillisecondsSinceEpoch(0), ); // Act & Assert @@ -41,12 +43,12 @@ void main() { () { // Arrange final firstNmeaMessage = NmeaMessage( - "message", - DateTime.fromMillisecondsSinceEpoch(0), + message: "message", + timestamp: DateTime.fromMillisecondsSinceEpoch(0), ); final secondNmeaMessage = NmeaMessage( - "message", - DateTime.fromMillisecondsSinceEpoch(1), + message: "message", + timestamp: DateTime.fromMillisecondsSinceEpoch(1), ); // Act & Assert From 26127a8611aa710f6375a974b23d1b72ae80f053 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Sun, 15 May 2022 12:15:34 -0700 Subject: [PATCH 19/25] update nmea channel name --- .../src/implementations/method_channel_geolocator.dart | 2 +- .../method_channel_geolocator_test.dart | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart index 8f64a20e..6bf4f49e 100644 --- a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart +++ b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart @@ -29,7 +29,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform { /// The event channel used to receive [NmeaMessage] updates from the native /// platform. static const _nmeaEventChannel = - EventChannel('flutter.baseflow.com/nmea_updates'); + EventChannel('flutter.baseflow.com/geolocator_nmea_updates'); /// On Android devices you can set [forcedLocationManager] /// to true to force the plugin to use the [LocationManager] to determine the diff --git a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart index faa1b23a..d80bae1c 100644 --- a/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart +++ b/geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart @@ -1148,7 +1148,7 @@ void main() { final streamController = StreamController>.broadcast(); EventChannelMock( - channelName: 'flutter.baseflow.com/nmea_updates', + channelName: 'flutter.baseflow.com/geolocator_nmea_updates', stream: streamController.stream, ); @@ -1218,7 +1218,7 @@ void main() { final streamController = StreamController.broadcast(); EventChannelMock( - channelName: 'flutter.baseflow.com/nmea_updates', + channelName: 'flutter.baseflow.com/geolocator_nmea_updates', stream: streamController.stream, ); @@ -1252,7 +1252,7 @@ void main() { final streamController = StreamController.broadcast(); EventChannelMock( - channelName: 'flutter.baseflow.com/nmea_updates', + channelName: 'flutter.baseflow.com/geolocator_nmea_updates', stream: streamController.stream, ); @@ -1285,7 +1285,7 @@ void main() { final streamController = StreamController.broadcast(); EventChannelMock( - channelName: 'flutter.baseflow.com/nmea_updates', + channelName: 'flutter.baseflow.com/geolocator_nmea_updates', stream: streamController.stream, ); @@ -1318,7 +1318,7 @@ void main() { final streamController = StreamController.broadcast(); EventChannelMock( - channelName: 'flutter.baseflow.com/nmea_updates', + channelName: 'flutter.baseflow.com/geolocator_nmea_updates', stream: streamController.stream, ); From 1f02cff1790f4123fd5b4ab9ae2d2492448f138c Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Sun, 15 May 2022 12:33:57 -0700 Subject: [PATCH 20/25] add test increase coverage --- geolocator_android/test/geolocator_android_test.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/geolocator_android/test/geolocator_android_test.dart b/geolocator_android/test/geolocator_android_test.dart index 6eebf167..74b4cde8 100644 --- a/geolocator_android/test/geolocator_android_test.dart +++ b/geolocator_android/test/geolocator_android_test.dart @@ -4,6 +4,7 @@ import 'package:async/async.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:geolocator_android/geolocator_android.dart'; +import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; import 'event_channel_mock.dart'; import 'method_channel_mock.dart'; @@ -38,6 +39,15 @@ void main() { tearDown(log.clear); + test('registers instance', () { + GeolocatorAndroid.registerWith(); + expect(GeolocatorPlatform.instance, isA()); + }); + + tearDown(() { + log.clear(); + }); + group('checkPermission: When checking for permission', () { test( // ignore: lines_longer_than_80_chars From 8951952dc4057bf5737a259d2201e469a9bd2fc4 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Sun, 15 May 2022 13:11:11 -0700 Subject: [PATCH 21/25] expand coverage --- .../test/geolocator_android_test.dart | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/geolocator_android/test/geolocator_android_test.dart b/geolocator_android/test/geolocator_android_test.dart index 74b4cde8..bcd7b7c2 100644 --- a/geolocator_android/test/geolocator_android_test.dart +++ b/geolocator_android/test/geolocator_android_test.dart @@ -594,6 +594,60 @@ void main() { ]); }); + test( + 'Should receive a position for each call using AndroidSettings and ForegroundNotificationConfig', + () async { + // Arrange + final channel = MethodChannelMock( + channelName: 'flutter.baseflow.com/geolocator_android', + method: 'getCurrentPosition', + result: mockPosition.toJson(), + ); + + ForegroundNotificationConfig foregroundNotificationConfig = + const ForegroundNotificationConfig( + notificationText: + "App will continue to receive your location even when you aren't using it", + notificationTitle: "Running in Background", + enableWakeLock: false); + + AndroidSettings expectedFirstArguments = AndroidSettings( + forceLocationManager: false, + accuracy: LocationAccuracy.low, + foregroundNotificationConfig: foregroundNotificationConfig); + AndroidSettings expectedSecondArguments = AndroidSettings( + forceLocationManager: false, + accuracy: LocationAccuracy.high, + foregroundNotificationConfig: foregroundNotificationConfig); + + // Act + final plugin = GeolocatorAndroid(); + final firstPosition = await plugin.getCurrentPosition( + locationSettings: AndroidSettings( + forceLocationManager: false, + accuracy: LocationAccuracy.low, + foregroundNotificationConfig: foregroundNotificationConfig)); + final secondPosition = await plugin.getCurrentPosition( + locationSettings: AndroidSettings( + forceLocationManager: false, + accuracy: LocationAccuracy.high, + foregroundNotificationConfig: foregroundNotificationConfig)); + + // Assert + expect(firstPosition, mockPosition); + expect(secondPosition, mockPosition); + expect(channel.log, [ + isMethodCall( + 'getCurrentPosition', + arguments: expectedFirstArguments.toJson(), + ), + isMethodCall( + 'getCurrentPosition', + arguments: expectedSecondArguments.toJson(), + ), + ]); + }); + test('Should throw a permission denied exception if permission is denied', () async { // Arrange @@ -1600,5 +1654,9 @@ void main() { ); }); }); + + group('Android Settings Tests', () {}); + + group('Foreground Settings Tests', () {}); }); } From fb8904031f2809f3fcbc2dae52e3b907d76b99ab Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Sun, 15 May 2022 13:25:21 -0700 Subject: [PATCH 22/25] remove empty tests --- geolocator_android/test/geolocator_android_test.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/geolocator_android/test/geolocator_android_test.dart b/geolocator_android/test/geolocator_android_test.dart index bcd7b7c2..f274721e 100644 --- a/geolocator_android/test/geolocator_android_test.dart +++ b/geolocator_android/test/geolocator_android_test.dart @@ -1654,9 +1654,5 @@ void main() { ); }); }); - - group('Android Settings Tests', () {}); - - group('Foreground Settings Tests', () {}); }); } From 895e4b457f5ac6c071b2faaecdf15e9698975022 Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 31 Aug 2022 22:54:51 -0700 Subject: [PATCH 23/25] fix for deprecated button --- geolocator/example/pubspec.yaml | 2 +- geolocator_android/example/pubspec.yaml | 2 +- geolocator_apple/example/pubspec.yaml | 2 +- geolocator_linux/example/pubspec.yaml | 2 +- geolocator_web/example/pubspec.yaml | 2 +- geolocator_windows/example/pubspec.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/geolocator/example/pubspec.yaml b/geolocator/example/pubspec.yaml index ec19f876..c85dc1ab 100644 --- a/geolocator/example/pubspec.yaml +++ b/geolocator/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: v2.1.0 + ref: update-deprecated-button flutter: sdk: flutter diff --git a/geolocator_android/example/pubspec.yaml b/geolocator_android/example/pubspec.yaml index 56353b64..28807bc9 100644 --- a/geolocator_android/example/pubspec.yaml +++ b/geolocator_android/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: v2.1.0 + ref: update-deprecated-button flutter: sdk: flutter diff --git a/geolocator_apple/example/pubspec.yaml b/geolocator_apple/example/pubspec.yaml index 76247c5e..f46fe536 100644 --- a/geolocator_apple/example/pubspec.yaml +++ b/geolocator_apple/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: v2.1.0 + ref: update-deprecated-button flutter: sdk: flutter diff --git a/geolocator_linux/example/pubspec.yaml b/geolocator_linux/example/pubspec.yaml index 55c3f5ed..575947ad 100644 --- a/geolocator_linux/example/pubspec.yaml +++ b/geolocator_linux/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: v2.1.0 + ref: update-deprecated-button flutter: sdk: flutter diff --git a/geolocator_web/example/pubspec.yaml b/geolocator_web/example/pubspec.yaml index eda2355c..0b2d5662 100644 --- a/geolocator_web/example/pubspec.yaml +++ b/geolocator_web/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: v2.1.0 + ref: update-deprecated-button flutter: sdk: flutter diff --git a/geolocator_windows/example/pubspec.yaml b/geolocator_windows/example/pubspec.yaml index 32ff4f28..ae8f84d9 100644 --- a/geolocator_windows/example/pubspec.yaml +++ b/geolocator_windows/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: v2.1.0 + ref: update-deprecated-button flutter: sdk: flutter From e7051971e8b9a4d9307d6baef0954f5122dddf4a Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Wed, 14 Sep 2022 11:00:36 -0600 Subject: [PATCH 24/25] use new plugin template tagged version --- geolocator/example/pubspec.yaml | 2 +- geolocator_android/example/pubspec.yaml | 2 +- geolocator_apple/example/pubspec.yaml | 2 +- geolocator_linux/example/pubspec.yaml | 2 +- geolocator_web/example/pubspec.yaml | 2 +- geolocator_windows/example/pubspec.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/geolocator/example/pubspec.yaml b/geolocator/example/pubspec.yaml index c85dc1ab..729fdccc 100644 --- a/geolocator/example/pubspec.yaml +++ b/geolocator/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: update-deprecated-button + ref: baseflow_plugin_template_v2.1.1 flutter: sdk: flutter diff --git a/geolocator_android/example/pubspec.yaml b/geolocator_android/example/pubspec.yaml index 28807bc9..a5e93c0e 100644 --- a/geolocator_android/example/pubspec.yaml +++ b/geolocator_android/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: update-deprecated-button + ref: baseflow_plugin_template_v2.1.1 flutter: sdk: flutter diff --git a/geolocator_apple/example/pubspec.yaml b/geolocator_apple/example/pubspec.yaml index f46fe536..c30664d4 100644 --- a/geolocator_apple/example/pubspec.yaml +++ b/geolocator_apple/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: update-deprecated-button + ref: baseflow_plugin_template_v2.1.1 flutter: sdk: flutter diff --git a/geolocator_linux/example/pubspec.yaml b/geolocator_linux/example/pubspec.yaml index 575947ad..5305c3dc 100644 --- a/geolocator_linux/example/pubspec.yaml +++ b/geolocator_linux/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: update-deprecated-button + ref: baseflow_plugin_template_v2.1.1 flutter: sdk: flutter diff --git a/geolocator_web/example/pubspec.yaml b/geolocator_web/example/pubspec.yaml index 0b2d5662..cccf0fce 100644 --- a/geolocator_web/example/pubspec.yaml +++ b/geolocator_web/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: update-deprecated-button + ref: baseflow_plugin_template_v2.1.1 flutter: sdk: flutter diff --git a/geolocator_windows/example/pubspec.yaml b/geolocator_windows/example/pubspec.yaml index ae8f84d9..eabeb590 100644 --- a/geolocator_windows/example/pubspec.yaml +++ b/geolocator_windows/example/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: baseflow_plugin_template: git: url: https://github.com/Baseflow/baseflow_plugin_template.git - ref: update-deprecated-button + ref: baseflow_plugin_template_v2.1.1 flutter: sdk: flutter From 068eb284b829286ef55f435016066d00e3859eaa Mon Sep 17 00:00:00 2001 From: Rick Casson <4932864+rickcasson@users.noreply.github.com> Date: Tue, 27 Sep 2022 12:58:08 -0600 Subject: [PATCH 25/25] remove unnecessary import --- geolocator_android/test/geolocator_android_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/geolocator_android/test/geolocator_android_test.dart b/geolocator_android/test/geolocator_android_test.dart index 3656d784..d84af838 100644 --- a/geolocator_android/test/geolocator_android_test.dart +++ b/geolocator_android/test/geolocator_android_test.dart @@ -5,7 +5,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:geolocator_android/geolocator_android.dart'; import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; -import 'package:geolocator_android/src/types/foreground_settings.dart'; import 'event_channel_mock.dart'; import 'method_channel_mock.dart';