From e46ddf919717ba5b8fccfaf417e934ef57c3815b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danilo=20Andrade=20Peixoto=20R=C3=AAgo?= Date: Sat, 28 Nov 2020 21:50:20 -0300 Subject: [PATCH 01/26] fix: return LocationPermission.always for requestPermission on Android under Marshmellow --- .../com/baseflow/geolocator/permission/PermissionManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java b/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java index d41aa55f..89dd219d 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java @@ -72,6 +72,7 @@ public void requestPermission( // Before Android M, requesting permissions was not needed. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + this.resultCallback.onResult(LocationPermission.always); return; } From f8c4be4d5785c00216af9d93a0fdc75364e28682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danilo=20Andrade=20Peixoto=20R=C3=AAgo?= Date: Sat, 28 Nov 2020 21:52:01 -0300 Subject: [PATCH 02/26] fix: result callback --- .../com/baseflow/geolocator/permission/PermissionManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java b/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java index 89dd219d..c195f95f 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/permission/PermissionManager.java @@ -72,7 +72,7 @@ public void requestPermission( // Before Android M, requesting permissions was not needed. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - this.resultCallback.onResult(LocationPermission.always); + resultCallback.onResult(LocationPermission.always); return; } From 9f3db185ff32dd4307551f303dac981d0fc2ea88 Mon Sep 17 00:00:00 2001 From: Sempakonka <47318358+Sempakonka@users.noreply.github.com> Date: Tue, 17 Nov 2020 11:07:57 +0100 Subject: [PATCH 03/26] push voor daniel --- .../android/src/main/AndroidManifest.xml | 2 + .../baseflow/geolocator/GeolocatorPlugin.java | 22 ++++ .../baseflow/geolocator/NmeaStreamImpl.java | 110 ++++++++++++++++++ .../geolocator/StreamHandlerImpl.java | 1 + .../location/FusedLocationClient.java | 7 ++ .../location/GeolocationManager.java | 26 ++++- .../geolocator/location/LocationClient.java | 2 + .../location/LocationManagerClient.java | 31 ++++- .../geolocator/location/LocationMapper.java | 2 +- .../location/NmeaChangedCallback.java | 7 ++ .../location/OnNmeaMessageListener.java | 18 +++ geolocator/lib/geolocator.dart | 4 + geolocator/pubspec.yaml | 3 +- .../src/geolocator_platform_interface.dart | 6 + .../method_channel_geolocator.dart | 36 ++++++ .../lib/src/models/models.dart | 1 + .../lib/src/models/nmea_message.dart | 71 +++++++++++ .../lib/src/models/position.dart | 46 ++++---- 18 files changed, 366 insertions(+), 29 deletions(-) create mode 100644 geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java create mode 100644 geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaChangedCallback.java create mode 100644 geolocator/android/src/main/java/com/baseflow/geolocator/location/OnNmeaMessageListener.java create mode 100644 geolocator_platform_interface/lib/src/models/nmea_message.dart diff --git a/geolocator/android/src/main/AndroidManifest.xml b/geolocator/android/src/main/AndroidManifest.xml index 4ac47fcd..7b9cd8e8 100644 --- a/geolocator/android/src/main/AndroidManifest.xml +++ b/geolocator/android/src/main/AndroidManifest.xml @@ -1,3 +1,5 @@ + + diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index 17efe836..84070e0c 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -23,6 +23,8 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { @Nullable private StreamHandlerImpl streamHandler; + @NonNull private NmeaStreamImpl nmeaStream; + @Nullable private Registrar pluginRegistrar; @Nullable private ActivityPluginBinding pluginBinding; @@ -56,6 +58,10 @@ public static void registerWith(Registrar registrar) { StreamHandlerImpl streamHandler = new StreamHandlerImpl(geolocatorPlugin.geolocationManager); streamHandler.startListening(registrar.context(), registrar.messenger()); streamHandler.setActivity(registrar.activity()); + + NmeaStreamImpl nmeaStream = new NmeaStreamImpl(geolocatorPlugin.geolocationManager); + nmeaStream.startListening(registrar.context(), registrar.messenger()); + nmeaStream.setActivity(registrar.activity()); } @Override @@ -66,6 +72,9 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin streamHandler = new StreamHandlerImpl(this.geolocationManager); streamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); + nmeaStream = new NmeaStreamImpl(this.geolocationManager); + nmeaStream.startListening( + flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); } @Override @@ -79,6 +88,11 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { streamHandler.stopListening(); streamHandler = null; } + + if (nmeaStream != null){ + nmeaStream.stopListening(); + nmeaStream = null; + } } @Override @@ -90,6 +104,10 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { streamHandler.setActivity(binding.getActivity()); } + if (nmeaStream != null){ + nmeaStream.setActivity(binding.getActivity()); + } + this.pluginBinding = binding; registerListeners(); } @@ -113,6 +131,10 @@ public void onDetachedFromActivity() { streamHandler.setActivity(null); } + if (nmeaStream != null){ + nmeaStream.setActivity(null); + } + deregisterListeners(); } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java b/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java new file mode 100644 index 00000000..3db1c680 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java @@ -0,0 +1,110 @@ +package com.baseflow.geolocator; + +import android.app.Activity; +import android.content.Context; +import android.location.Location; +import android.util.Log; +import android.util.Pair; +import androidx.annotation.Nullable; +import com.baseflow.geolocator.errors.ErrorCodes; +import com.baseflow.geolocator.location.GeolocationManager; +import com.baseflow.geolocator.location.LocationClient; +import com.baseflow.geolocator.location.LocationMapper; +import com.baseflow.geolocator.location.LocationOptions; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.EventChannel; + +import java.util.HashMap; +import java.util.Map; + +class NmeaStreamImpl implements EventChannel.StreamHandler { + private static final String TAG = "NmeaStreamImpl"; + + private final GeolocationManager geolocationManager; + + @Nullable private EventChannel channel; + @Nullable private Context context; + @Nullable private Activity activity; + @Nullable private LocationClient locationClient; + + public NmeaStreamImpl(GeolocationManager geolocationManager) { + this.geolocationManager = geolocationManager; + System.out.println("Called"); + } + + 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(); + } + System.out.println("Start listening"); + + 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) { + @SuppressWarnings("unchecked") + Map map = (Map) arguments; + + System.out.println("onListen..."); + boolean forceLocationManager = true; + LocationOptions locationOptions = null; + + this.locationClient = + geolocationManager.createLocationClient( + this.context, forceLocationManager, locationOptions); + + geolocationManager.startNmeaUpdates( + context, + activity, + this.locationClient, + (String n, long l) -> events.success(toMap(n,l)), + (ErrorCodes errorCodes) -> + events.error(errorCodes.toString(), errorCodes.toDescription(), null)); + } + + public static Map toMap(String n, Long l) { + Map Nmea = new HashMap<>(); + + Nmea.put(n, l); + System.out.println(Nmea.values().toString() + " NMEA VALUES"); + + return Nmea; + } + + @Override + public void onCancel(Object arguments) { + if (this.locationClient != null) { + geolocationManager.stopPositionUpdates(this.locationClient); + } + } +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java b/geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java index eaf83cdd..6e84f410 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java @@ -46,6 +46,7 @@ void startListening(Context context, BinaryMessenger messenger) { stopListening(); } + channel = new EventChannel(messenger, "flutter.baseflow.com/geolocator_updates"); channel.setStreamHandler(this); this.context = context; diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/FusedLocationClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/FusedLocationClient.java index 84b8fbd8..66271136 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/FusedLocationClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/FusedLocationClient.java @@ -189,6 +189,13 @@ public void stopPositionUpdates() { fusedLocationProviderClient.removeLocationUpdates(locationCallback); } + @Override + public void startNmeaUpdates( + NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback) { + + } + private static LocationRequest buildLocationRequest(@Nullable LocationOptions options) { LocationRequest locationRequest = new LocationRequest(); diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java index d7fb9347..5505eb1a 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.location.OnNmeaMessageListener; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -19,7 +20,9 @@ import java.util.List; public class GeolocationManager implements ActivityResultListener { - @NonNull private final PermissionManager permissionManager; + + @NonNull + private final PermissionManager permissionManager; private final List locationClients; public GeolocationManager(@NonNull PermissionManager permissionManager) { @@ -70,11 +73,28 @@ public void startPositionUpdates( errorCallback); } + public void startNmeaUpdates(Context context, + Activity activity, + LocationClient locationClient, + NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback + ) { + + this.locationClients.add(locationClient); + + handlePermissions( + context, + activity, + () -> locationClient.startNmeaUpdates(nmeaChangedCallback, errorCallback), + errorCallback); + } + public void stopPositionUpdates(@NonNull LocationClient locationClient) { locationClients.remove(locationClient); locationClient.stopPositionUpdates(); } + public LocationClient createLocationClient( Context context, boolean forceAndroidLocationManager, @@ -83,9 +103,7 @@ public LocationClient createLocationClient( return new LocationManagerClient(context, locationOptions); } - return isGooglePlayServicesAvailable(context) - ? new FusedLocationClient(context, locationOptions) - : new LocationManagerClient(context, locationOptions); + return new LocationManagerClient(context, locationOptions); } private boolean isGooglePlayServicesAvailable(Context context) { diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationClient.java index 8ae4530e..13bda06b 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationClient.java @@ -18,4 +18,6 @@ void startPositionUpdates( ErrorCallback errorCallback); void stopPositionUpdates(); + + void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback); } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java index 6a7f9268..6597ede1 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java @@ -1,26 +1,35 @@ package com.baseflow.geolocator.location; +import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; +import android.content.pm.PackageManager; import android.location.Criteria; +import android.location.GpsStatus; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.location.LocationProvider; +import android.location.OnNmeaMessageListener; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Looper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.core.app.ActivityCompat; import com.baseflow.geolocator.errors.ErrorCallback; import com.baseflow.geolocator.errors.ErrorCodes; import com.google.android.gms.common.util.Strings; import java.util.List; -class LocationManagerClient implements LocationClient, LocationListener { + +@SuppressLint("NewApi") +class LocationManagerClient implements LocationClient, LocationListener, OnNmeaMessageListener{ private static final long TWO_MINUTES = 120000; private final LocationManager locationManager; @@ -32,13 +41,16 @@ class LocationManagerClient implements LocationClient, LocationListener { @Nullable private String currentLocationProvider; @Nullable private PositionChangedCallback positionChangedCallback; @Nullable private ErrorCallback errorCallback; + @Nullable private NmeaChangedCallback nmeaChangedCallback; public LocationManagerClient( @NonNull Context context, @Nullable LocationOptions locationOptions) { this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); this.locationOptions = locationOptions; + this.locationManager.addNmeaListener(this); } + @Override public void isLocationServiceEnabled(LocationServiceListener listener) { if (locationManager == null) { @@ -122,6 +134,13 @@ public void stopPositionUpdates() { this.locationManager.removeUpdates(this); } + @Override + public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback) { + + this.nmeaChangedCallback = nmeaChangedCallback; + this.errorCallback = errorCallback; + } + @Override public synchronized void onLocationChanged(Location location) { float desiredAccuracy = @@ -198,6 +217,8 @@ static boolean isBetterLocation(Location location, Location bestLocation) { return false; } + + private static String getBestProvider( LocationManager locationManager, LocationAccuracy accuracy) { Criteria criteria = new Criteria(); @@ -253,4 +274,12 @@ private static float accuracyToFloat(LocationAccuracy accuracy) { return 100; } } + + @Override + public void onNmeaMessage(String s, long l) { + + if (this.nmeaChangedCallback != null){ + this.nmeaChangedCallback.onNmeaMessage(s, l); + } + } } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationMapper.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationMapper.java index b35990ba..fc3dac3e 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationMapper.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationMapper.java @@ -14,6 +14,7 @@ public static Map toHashMap(Location location) { Map position = new HashMap<>(); + position.put("satellites", location.getExtras().getInt("satellites")); position.put("latitude", location.getLatitude()); position.put("longitude", location.getLongitude()); position.put("timestamp", location.getTime()); @@ -30,7 +31,6 @@ public static Map toHashMap(Location location) { } else { position.put("is_mocked", false); } - return position; } } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaChangedCallback.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaChangedCallback.java new file mode 100644 index 00000000..38fdeb84 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaChangedCallback.java @@ -0,0 +1,7 @@ +package com.baseflow.geolocator.location; + + +@FunctionalInterface +public interface NmeaChangedCallback { + void onNmeaMessage(String message, long timeStamp); +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/OnNmeaMessageListener.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/OnNmeaMessageListener.java new file mode 100644 index 00000000..833c06b6 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/OnNmeaMessageListener.java @@ -0,0 +1,18 @@ +package android.location; + +/** + * Used for receiving NMEA sentences from the GNSS. + * NMEA 0183 is a standard for communicating with marine electronic devices + * and is a common method for receiving data from a GNSS, typically over a serial port. + * See NMEA 0183 for more details. + * You can implement this interface and call {@link LocationManager#addNmeaListener} + * to receive NMEA data from the GNSS engine. + */ +public interface OnNmeaMessageListener { + /** + * Called when an NMEA message is received. + * @param message NMEA message + * @param timestamp milliseconds since January 1, 1970. + */ + void onNmeaMessage(String message, long timestamp); +} \ No newline at end of file diff --git a/geolocator/lib/geolocator.dart b/geolocator/lib/geolocator.dart index bc7ab76c..de0bc178 100644 --- a/geolocator/lib/geolocator.dart +++ b/geolocator/lib/geolocator.dart @@ -261,6 +261,10 @@ class Geolocator { timeLimit: timeLimit, ); + static Stream getNmeaMessageStream() => + GeolocatorPlatform.instance.getNmeaMessageStream(); + + /// Fires whenever the location changes inside the bounds of the /// [desiredAccuracy]. /// diff --git a/geolocator/pubspec.yaml b/geolocator/pubspec.yaml index 0cd814f9..2ae510c5 100644 --- a/geolocator/pubspec.yaml +++ b/geolocator/pubspec.yaml @@ -11,7 +11,8 @@ dependencies: flutter: sdk: flutter - geolocator_platform_interface: ^1.0.8 + geolocator_platform_interface: + path: ../geolocator_platform_interface dev_dependencies: flutter_test: diff --git a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart index ba4b982e..f7bf06b5 100644 --- a/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart +++ b/geolocator_platform_interface/lib/src/geolocator_platform_interface.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:math'; +import 'package:geolocator_platform_interface/src/models/nmea_message.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; import 'package:vector_math/vector_math.dart'; @@ -151,6 +152,11 @@ abstract class GeolocatorPlatform extends PlatformInterface { throw UnimplementedError('getPositionStream() has not been implemented.'); } + + Stream getNmeaMessageStream (){ + throw UnimplementedError('requestPermission() has not been implemented.'); + } + /// Opens the App settings page. /// /// Returns [true] if the app settings page could be opened, otherwise 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 2aec118c..7cab0e24 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 { EventChannel eventChannel = EventChannel('flutter.baseflow.com/geolocator_updates'); + /// The event channel used to receive [NmeaMessage] updates from the native + /// platform. + @visibleForTesting + EventChannel nmeaChannel = EventChannel('flutter.baseflow.com/nmea_updates'); + /// On Android devices you can set [forceAndroidLocationManager] /// to true to force the plugin to use the [LocationManager] to determine the /// position instead of the [FusedLocationProviderClient]. On iOS this is @@ -32,6 +37,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform { bool forceAndroidLocationManager = false; Stream _positionStream; + Stream _nmeaMessageStream; @override Future checkPermission() async { @@ -178,6 +184,36 @@ class MethodChannelGeolocator extends GeolocatorPlatform { return _positionStream; } + @override + Stream getNmeaMessageStream() { + print("lala"); + + if (_nmeaMessageStream != null) { + return _nmeaMessageStream; + } + + var nmeaStream = nmeaChannel.receiveBroadcastStream(); + + _nmeaMessageStream = nmeaStream + .map((dynamic element) { + print("stream binnen"); + return NmeaMessage.fromMap(element.cast()); + }) + .handleError( + (error) { + _nmeaMessageStream = null; + if (error is PlatformException) { + _handlePlatformException(error); + } + + throw error; + }, + ); + print("Huts"); + + return _nmeaMessageStream; + } + @override Future openAppSettings() async => methodChannel.invokeMethod('openAppSettings'); diff --git a/geolocator_platform_interface/lib/src/models/models.dart b/geolocator_platform_interface/lib/src/models/models.dart index 2ddfd20b..130cc3ab 100644 --- a/geolocator_platform_interface/lib/src/models/models.dart +++ b/geolocator_platform_interface/lib/src/models/models.dart @@ -1,2 +1,3 @@ export 'location_options.dart'; +export 'nmea_message.dart'; export 'position.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..d23ee1c8 --- /dev/null +++ b/geolocator_platform_interface/lib/src/models/nmea_message.dart @@ -0,0 +1,71 @@ + +import 'package:meta/meta.dart'; + + +@immutable +///nmea message +class NmeaMessage { + + ///nmea message + NmeaMessage(this.message, this.timestamp); + + ///message + final String message; + + ///timestamp + final DateTime timestamp; + + /// Converts the supplied [Map] to an instance of the [NmeaMessage] class. + static NmeaMessage fromMap(dynamic message) { + if (message == null) { + return null; + } + print("using from map..."); + + 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 ==(dynamic o) { + var areEqual = o is NmeaMessage && + o.message == message && + o.timestamp == timestamp; + + + return areEqual; + } + + @override + int get hashCode => + message.hashCode ^ + timestamp.hashCode; + +} diff --git a/geolocator_platform_interface/lib/src/models/position.dart b/geolocator_platform_interface/lib/src/models/position.dart index 0194de63..25ea2fc5 100644 --- a/geolocator_platform_interface/lib/src/models/position.dart +++ b/geolocator_platform_interface/lib/src/models/position.dart @@ -88,6 +88,7 @@ class Position { o.timestamp == timestamp && o.isMocked == isMocked; + return areEqual; } @@ -114,6 +115,7 @@ class Position { if (message == null) { return null; } + print("using from map..."); final Map positionMap = message; @@ -129,35 +131,35 @@ class Position { final timestamp = positionMap['timestamp'] != null ? DateTime.fromMillisecondsSinceEpoch(positionMap['timestamp'].toInt(), - isUtc: true) + isUtc: true) : null; return Position( - latitude: positionMap['latitude'], - longitude: positionMap['longitude'], - timestamp: timestamp, - altitude: positionMap['altitude'] ?? 0.0, - accuracy: positionMap['accuracy'] ?? 0.0, - heading: positionMap['heading'] ?? 0.0, - floor: positionMap['floor'], - speed: positionMap['speed'] ?? 0.0, - speedAccuracy: positionMap['speed_accuracy'] ?? 0.0, - isMocked: positionMap['is_mocked'] ?? false, + latitude: positionMap['latitude'], + longitude: positionMap['longitude'], + timestamp: timestamp, + altitude: positionMap['altitude'] ?? 0.0, + accuracy: positionMap['accuracy'] ?? 0.0, + heading: positionMap['heading'] ?? 0.0, + floor: positionMap['floor'], + speed: positionMap['speed'] ?? 0.0, + speedAccuracy: positionMap['speed_accuracy'] ?? 0.0, + isMocked: positionMap['is_mocked'] ?? false, ); } /// Converts the [Position] instance into a [Map] instance that can be /// serialized to JSON. Map toJson() => { - 'longitude': longitude, - 'latitude': latitude, - 'timestamp': timestamp?.millisecondsSinceEpoch, - 'accuracy': accuracy, - 'altitude': altitude, - 'floor': floor, - 'heading': heading, - 'speed': speed, - 'speed_accuracy': speedAccuracy, - 'is_mocked': isMocked, - }; + 'longitude': longitude, + 'latitude': latitude, + 'timestamp': timestamp?.millisecondsSinceEpoch, + 'accuracy': accuracy, + 'altitude': altitude, + 'floor': floor, + 'heading': heading, + 'speed': speed, + 'speed_accuracy': speedAccuracy, + 'is_mocked': isMocked, + }; } From 6c787cf838afdacef9a81ca28d20dcc696fe67fe Mon Sep 17 00:00:00 2001 From: Sempakonka <47318358+Sempakonka@users.noreply.github.com> Date: Wed, 18 Nov 2020 11:55:06 +0100 Subject: [PATCH 04/26] nmea message clients both for gps and gnss added. Added nmea message functionality to example app --- geolocator/android/build.gradle | 2 +- .../baseflow/geolocator/NmeaStreamImpl.java | 37 ++++------ .../location/FusedLocationClient.java | 7 -- .../location/GeolocationManager.java | 26 ++++--- .../location/GnssNmeaMessageClient.java | 72 +++++++++++++++++++ .../location/GpsNmeaMessageClient.java | 71 ++++++++++++++++++ .../geolocator/location/LocationClient.java | 1 - .../location/LocationManagerClient.java | 19 +---- .../location/NmeaMessageaClient.java | 9 +++ .../location/OnNmeaMessageListener.java | 18 ----- geolocator/example/lib/main.dart | 6 -- .../method_channel_geolocator.dart | 10 ++- .../lib/src/models/nmea_message.dart | 2 +- .../lib/src/models/position.dart | 1 - 14 files changed, 192 insertions(+), 89 deletions(-) create mode 100644 geolocator/android/src/main/java/com/baseflow/geolocator/location/GnssNmeaMessageClient.java create mode 100644 geolocator/android/src/main/java/com/baseflow/geolocator/location/GpsNmeaMessageClient.java create mode 100644 geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaMessageaClient.java delete mode 100644 geolocator/android/src/main/java/com/baseflow/geolocator/location/OnNmeaMessageListener.java diff --git a/geolocator/android/build.gradle b/geolocator/android/build.gradle index 5365b734..b7b2d7fb 100644 --- a/geolocator/android/build.gradle +++ b/geolocator/android/build.gradle @@ -22,7 +22,7 @@ rootProject.allprojects { apply plugin: 'com.android.library' android { - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { minSdkVersion 16 diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java b/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java index 3db1c680..b330980d 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java @@ -2,15 +2,11 @@ import android.app.Activity; import android.content.Context; -import android.location.Location; import android.util.Log; -import android.util.Pair; import androidx.annotation.Nullable; import com.baseflow.geolocator.errors.ErrorCodes; import com.baseflow.geolocator.location.GeolocationManager; -import com.baseflow.geolocator.location.LocationClient; -import com.baseflow.geolocator.location.LocationMapper; -import com.baseflow.geolocator.location.LocationOptions; +import com.baseflow.geolocator.location.NmeaMessageaClient; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; @@ -25,7 +21,7 @@ class NmeaStreamImpl implements EventChannel.StreamHandler { @Nullable private EventChannel channel; @Nullable private Context context; @Nullable private Activity activity; - @Nullable private LocationClient locationClient; + @Nullable private NmeaMessageaClient nmeaMessageaClient; public NmeaStreamImpl(GeolocationManager geolocationManager) { this.geolocationManager = geolocationManager; @@ -72,39 +68,36 @@ void stopListening() { @Override public void onListen(Object arguments, EventChannel.EventSink events) { - @SuppressWarnings("unchecked") - Map map = (Map) arguments; - System.out.println("onListen..."); - boolean forceLocationManager = true; - LocationOptions locationOptions = null; - - this.locationClient = - geolocationManager.createLocationClient( - this.context, forceLocationManager, locationOptions); + this.nmeaMessageaClient = geolocationManager.createNmeaClient(context); geolocationManager.startNmeaUpdates( context, activity, - this.locationClient, - (String n, long l) -> events.success(toMap(n,l)), + nmeaMessageaClient, + (String n, long l) -> { + events.success(toMap(n,l)); + }, (ErrorCodes errorCodes) -> events.error(errorCodes.toString(), errorCodes.toDescription(), null)); } public static Map toMap(String n, Long l) { + if (n == null || l == null){ + return null; + } Map Nmea = new HashMap<>(); - Nmea.put(n, l); - System.out.println(Nmea.values().toString() + " NMEA VALUES"); + Nmea.put("timestamp", l); + Nmea.put("message", n); return Nmea; } @Override public void onCancel(Object arguments) { - if (this.locationClient != null) { - geolocationManager.stopPositionUpdates(this.locationClient); - } + // if (this.nmeaMessageaClient != null) { + // geolocationManager.stopPositionUpdates(this.nmeaMessageaClient); + // } } } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/FusedLocationClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/FusedLocationClient.java index 66271136..84b8fbd8 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/FusedLocationClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/FusedLocationClient.java @@ -189,13 +189,6 @@ public void stopPositionUpdates() { fusedLocationProviderClient.removeLocationUpdates(locationCallback); } - @Override - public void startNmeaUpdates( - NmeaChangedCallback nmeaChangedCallback, - ErrorCallback errorCallback) { - - } - private static LocationRequest buildLocationRequest(@Nullable LocationOptions options) { LocationRequest locationRequest = new LocationRequest(); diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java index 5505eb1a..1d6ba561 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java @@ -3,7 +3,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.location.OnNmeaMessageListener; +import android.os.Build.VERSION_CODES; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -25,6 +25,7 @@ public class GeolocationManager implements ActivityResultListener { private final PermissionManager permissionManager; private final List locationClients; + public GeolocationManager(@NonNull PermissionManager permissionManager) { this.permissionManager = permissionManager; this.locationClients = new ArrayList<>(); @@ -73,19 +74,26 @@ public void startPositionUpdates( errorCallback); } - public void startNmeaUpdates(Context context, - Activity activity, - LocationClient locationClient, - NmeaChangedCallback nmeaChangedCallback, - ErrorCallback errorCallback - ) { + public NmeaMessageaClient createNmeaClient(Context context){ + if (android.os.Build.VERSION.SDK_INT >= VERSION_CODES.N){ + GnssNmeaMessageClient client = new GnssNmeaMessageClient(context); + System.out.println("created gnss"); + return client; + } else{ + GpsNmeaMessageClient client = new GpsNmeaMessageClient(context); + System.out.println("created gps"); + return client; + } + } - this.locationClients.add(locationClient); + + public void startNmeaUpdates(Context context, Activity activity, NmeaMessageaClient client, + NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback) { handlePermissions( context, activity, - () -> locationClient.startNmeaUpdates(nmeaChangedCallback, errorCallback), + () -> client.startNmeaUpdates(nmeaChangedCallback, errorCallback), errorCallback); } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GnssNmeaMessageClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GnssNmeaMessageClient.java new file mode 100644 index 00000000..8d2faf9c --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GnssNmeaMessageClient.java @@ -0,0 +1,72 @@ +package com.baseflow.geolocator.location; + +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.Build.VERSION_CODES; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import com.baseflow.geolocator.errors.ErrorCallback; + + +@RequiresApi(api = VERSION_CODES.N) +public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationListener, NmeaMessageaClient { + + private final LocationManager locationManager; + @Nullable + private NmeaChangedCallback nmeaChangedCallback; + @Nullable + private ErrorCallback errorCallback; + + + public GnssNmeaMessageClient( + @NonNull Context context) { + this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10000f, this); + this.locationManager.addNmeaListener(this, null); + System.out.println("gnss nmea client initialized"); + } + + public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback) { + + this.nmeaChangedCallback = nmeaChangedCallback; + this.errorCallback = errorCallback; + } + + + @Override + public void onNmeaMessage(String s, long l) { + System.out.println("got nmea message"); + + if (this.nmeaChangedCallback != null){ + this.nmeaChangedCallback.onNmeaMessage(s, l); + } + } + + + @Override + public void onLocationChanged(@NonNull Location location) { + + } + + @Override + public void onStatusChanged(String s, int i, Bundle bundle) { + + } + + @Override + public void onProviderEnabled(String s) { + + } + + @Override + public void onProviderDisabled(String s) { + + } +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GpsNmeaMessageClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GpsNmeaMessageClient.java new file mode 100644 index 00000000..c489d330 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GpsNmeaMessageClient.java @@ -0,0 +1,71 @@ +package com.baseflow.geolocator.location; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.location.GpsStatus; +import android.location.GpsStatus.Listener; +import android.location.GpsStatus.NmeaListener; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.location.OnNmeaMessageListener; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.baseflow.geolocator.errors.ErrorCallback; + +@SuppressLint("NewApi") +public class GpsNmeaMessageClient implements LocationListener, GpsStatus.NmeaListener, + GpsStatus.Listener, NmeaMessageaClient { + + LocationManager locationManager; + @Nullable + private NmeaChangedCallback nmeaChangedCallback; + @Nullable + private ErrorCallback errorCallback; + + + public GpsNmeaMessageClient( + @NonNull Context context) { + this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10000f, this); + locationManager.addNmeaListener(this); + locationManager.addGpsStatusListener(this); + System.out.println("gps nmea client initialized"); + } + + public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback) { + + this.nmeaChangedCallback = nmeaChangedCallback; + this.errorCallback = errorCallback; + } + + @Override + public void onLocationChanged(@NonNull Location location) { + System.out.println("Location changed"); + } + + @Override + public void onProviderEnabled(String s) { + System.out.println("on provider enabled"); + } + + @Override + public void onProviderDisabled(String s) { + System.out.println("provider disabled"); + } + + @Override + public void onNmeaReceived(long l, String s) { + System.out.println("nmaerecieved"); + if (this.nmeaChangedCallback != null) { + this.nmeaChangedCallback.onNmeaMessage(s, l); + } + } + + @Override + public void onGpsStatusChanged(int i) { + System.out.println("gps status changed"); + } +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationClient.java index 13bda06b..8b9b6ca1 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationClient.java @@ -19,5 +19,4 @@ void startPositionUpdates( void stopPositionUpdates(); - void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback); } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java index 6597ede1..d6a10e9f 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/LocationManagerClient.java @@ -29,7 +29,7 @@ @SuppressLint("NewApi") -class LocationManagerClient implements LocationClient, LocationListener, OnNmeaMessageListener{ +class LocationManagerClient implements LocationClient, LocationListener{ private static final long TWO_MINUTES = 120000; private final LocationManager locationManager; @@ -47,7 +47,6 @@ public LocationManagerClient( @NonNull Context context, @Nullable LocationOptions locationOptions) { this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); this.locationOptions = locationOptions; - this.locationManager.addNmeaListener(this); } @@ -134,12 +133,6 @@ public void stopPositionUpdates() { this.locationManager.removeUpdates(this); } - @Override - public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback) { - - this.nmeaChangedCallback = nmeaChangedCallback; - this.errorCallback = errorCallback; - } @Override public synchronized void onLocationChanged(Location location) { @@ -274,12 +267,4 @@ private static float accuracyToFloat(LocationAccuracy accuracy) { return 100; } } - - @Override - public void onNmeaMessage(String s, long l) { - - if (this.nmeaChangedCallback != null){ - this.nmeaChangedCallback.onNmeaMessage(s, l); - } - } -} +} \ No newline at end of file diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaMessageaClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaMessageaClient.java new file mode 100644 index 00000000..7c416ed1 --- /dev/null +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaMessageaClient.java @@ -0,0 +1,9 @@ +package com.baseflow.geolocator.location; + +import com.baseflow.geolocator.errors.ErrorCallback; + +public interface NmeaMessageaClient { + + void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, + ErrorCallback errorCallback); +} diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/OnNmeaMessageListener.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/OnNmeaMessageListener.java deleted file mode 100644 index 833c06b6..00000000 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/OnNmeaMessageListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package android.location; - -/** - * Used for receiving NMEA sentences from the GNSS. - * NMEA 0183 is a standard for communicating with marine electronic devices - * and is a common method for receiving data from a GNSS, typically over a serial port. - * See NMEA 0183 for more details. - * You can implement this interface and call {@link LocationManager#addNmeaListener} - * to receive NMEA data from the GNSS engine. - */ -public interface OnNmeaMessageListener { - /** - * Called when an NMEA message is received. - * @param message NMEA message - * @param timestamp milliseconds since January 1, 1970. - */ - void onNmeaMessage(String message, long timestamp); -} \ No newline at end of file diff --git a/geolocator/example/lib/main.dart b/geolocator/example/lib/main.dart index cc8e06a1..84012ed7 100644 --- a/geolocator/example/lib/main.dart +++ b/geolocator/example/lib/main.dart @@ -75,7 +75,6 @@ class _GeolocatorWidgetState extends State { _positionItems.add(_PositionItem( _PositionItemType.position, value.toString())) }); - setState( () {}, ); @@ -180,11 +179,6 @@ class _GeolocatorWidgetState extends State { } } -enum _PositionItemType { - permission, - position, -} - class _PositionItem { _PositionItem(this.type, this.displayValue); 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 7cab0e24..ddf94897 100644 --- a/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart +++ b/geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart @@ -181,12 +181,12 @@ class MethodChannelGeolocator extends GeolocatorPlatform { }, ); + print(_positionStream.last); return _positionStream; } @override Stream getNmeaMessageStream() { - print("lala"); if (_nmeaMessageStream != null) { return _nmeaMessageStream; @@ -195,10 +195,8 @@ class MethodChannelGeolocator extends GeolocatorPlatform { var nmeaStream = nmeaChannel.receiveBroadcastStream(); _nmeaMessageStream = nmeaStream - .map((dynamic element) { - print("stream binnen"); - return NmeaMessage.fromMap(element.cast()); - }) + .map((dynamic element) => + NmeaMessage.fromMap(element.cast())) .handleError( (error) { _nmeaMessageStream = null; @@ -209,7 +207,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform { throw error; }, ); - print("Huts"); + print(_nmeaMessageStream.last); return _nmeaMessageStream; } diff --git a/geolocator_platform_interface/lib/src/models/nmea_message.dart b/geolocator_platform_interface/lib/src/models/nmea_message.dart index d23ee1c8..a7b59dc9 100644 --- a/geolocator_platform_interface/lib/src/models/nmea_message.dart +++ b/geolocator_platform_interface/lib/src/models/nmea_message.dart @@ -20,7 +20,7 @@ class NmeaMessage { if (message == null) { return null; } - print("using from map..."); + print("using from nmea message map method..."); final Map nmeaMessageMap = message; diff --git a/geolocator_platform_interface/lib/src/models/position.dart b/geolocator_platform_interface/lib/src/models/position.dart index 25ea2fc5..1405f6c3 100644 --- a/geolocator_platform_interface/lib/src/models/position.dart +++ b/geolocator_platform_interface/lib/src/models/position.dart @@ -115,7 +115,6 @@ class Position { if (message == null) { return null; } - print("using from map..."); final Map positionMap = message; From dfce8133bd36663b209c499cb5f7ce129e580d33 Mon Sep 17 00:00:00 2001 From: Sempakonka <47318358+Sempakonka@users.noreply.github.com> Date: Tue, 24 Nov 2020 09:21:22 +0100 Subject: [PATCH 05/26] nmea message clients both for gps and gnss added. Added nmea message functionality to example app --- .../baseflow/geolocator/GeolocatorPlugin.java | 22 +++--- .../baseflow/geolocator/NmeaStreamImpl.java | 52 +++++++------- ...ndlerImpl.java => PositionStreamImpl.java} | 7 +- .../location/GeolocationManager.java | 27 ++++--- .../location/GnssNmeaMessageClient.java | 41 ++++++++--- .../location/GpsNmeaMessageClient.java | 46 ++++++------ .../location/NmeaChangedCallback.java | 3 +- .../location/NmeaMessageaClient.java | 2 + .../app/src/main/res/values/styles.xml | 2 +- geolocator/example/lib/main.dart | 72 ++++++++++++++++--- geolocator/lib/geolocator.dart | 27 ++++++- geolocator/test/geolocator_test.dart | 48 ++++--------- .../src/geolocator_platform_interface.dart | 3 +- .../method_channel_geolocator.dart | 4 +- .../lib/src/models/nmea_message.dart | 22 ++---- .../lib/src/models/position.dart | 45 ++++++------ 16 files changed, 250 insertions(+), 173 deletions(-) rename geolocator/android/src/main/java/com/baseflow/geolocator/{StreamHandlerImpl.java => PositionStreamImpl.java} (93%) diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java b/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java index 84070e0c..9b1e70b0 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java @@ -21,13 +21,17 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { @Nullable private MethodCallHandlerImpl methodCallHandler; - @Nullable private StreamHandlerImpl streamHandler; + @Nullable + private PositionStreamImpl streamHandler; - @NonNull private NmeaStreamImpl nmeaStream; + @Nullable + private NmeaStreamImpl nmeaStream; - @Nullable private Registrar pluginRegistrar; + @Nullable + private Registrar pluginRegistrar; - @Nullable private ActivityPluginBinding pluginBinding; + @Nullable + private ActivityPluginBinding pluginBinding; public GeolocatorPlugin() { @@ -55,7 +59,7 @@ public static void registerWith(Registrar registrar) { methodCallHandler.startListening(registrar.context(), registrar.messenger()); methodCallHandler.setActivity(registrar.activity()); - StreamHandlerImpl streamHandler = new StreamHandlerImpl(geolocatorPlugin.geolocationManager); + PositionStreamImpl streamHandler = new PositionStreamImpl(geolocatorPlugin.geolocationManager); streamHandler.startListening(registrar.context(), registrar.messenger()); streamHandler.setActivity(registrar.activity()); @@ -69,7 +73,7 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin methodCallHandler = new MethodCallHandlerImpl(this.permissionManager, this.geolocationManager); methodCallHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - streamHandler = new StreamHandlerImpl(this.geolocationManager); + streamHandler = new PositionStreamImpl(this.geolocationManager); streamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); nmeaStream = new NmeaStreamImpl(this.geolocationManager); @@ -89,7 +93,7 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { streamHandler = null; } - if (nmeaStream != null){ + if (nmeaStream != null) { nmeaStream.stopListening(); nmeaStream = null; } @@ -104,7 +108,7 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { streamHandler.setActivity(binding.getActivity()); } - if (nmeaStream != null){ + if (nmeaStream != null) { nmeaStream.setActivity(binding.getActivity()); } @@ -131,7 +135,7 @@ public void onDetachedFromActivity() { streamHandler.setActivity(null); } - if (nmeaStream != null){ + if (nmeaStream != null) { nmeaStream.setActivity(null); } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java b/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java index b330980d..94e740a3 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/NmeaStreamImpl.java @@ -9,23 +9,39 @@ import com.baseflow.geolocator.location.NmeaMessageaClient; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; - import java.util.HashMap; import java.util.Map; class NmeaStreamImpl implements EventChannel.StreamHandler { + private static final String TAG = "NmeaStreamImpl"; private final GeolocationManager geolocationManager; - @Nullable private EventChannel channel; - @Nullable private Context context; - @Nullable private Activity activity; - @Nullable private NmeaMessageaClient nmeaMessageaClient; + @Nullable + private EventChannel channel; + @Nullable + private Context context; + @Nullable + private Activity activity; + @Nullable + private NmeaMessageaClient nmeaMessageaClient; public NmeaStreamImpl(GeolocationManager geolocationManager) { this.geolocationManager = geolocationManager; - System.out.println("Called"); + } + + public static Map toMap(String n, Long l) { + if (n == null || l == null) { + return null; + } + + Map Nmea = new HashMap<>(); + + Nmea.put("timestamp", l); + Nmea.put("message", n); + + return Nmea; } void setActivity(@Nullable Activity activity) { @@ -44,7 +60,6 @@ void startListening(Context context, BinaryMessenger messenger) { Log.w(TAG, "Setting a event call handler before the last was disposed."); stopListening(); } - System.out.println("Start listening"); channel = new EventChannel(messenger, "flutter.baseflow.com/nmea_updates"); channel.setStreamHandler(this); @@ -75,29 +90,16 @@ public void onListen(Object arguments, EventChannel.EventSink events) { context, activity, nmeaMessageaClient, - (String n, long l) -> { - events.success(toMap(n,l)); - }, + (String n, long l) -> events.success(toMap(n, l)), (ErrorCodes errorCodes) -> events.error(errorCodes.toString(), errorCodes.toDescription(), null)); } - public static Map toMap(String n, Long l) { - if (n == null || l == null){ - return null; - } - Map Nmea = new HashMap<>(); - - Nmea.put("timestamp", l); - Nmea.put("message", n); - - return Nmea; - } - @Override public void onCancel(Object arguments) { - // if (this.nmeaMessageaClient != null) { - // geolocationManager.stopPositionUpdates(this.nmeaMessageaClient); - // } + if (this.nmeaMessageaClient != null) { + geolocationManager.stopNmeaUpdates(this.nmeaMessageaClient); + } } + } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java b/geolocator/android/src/main/java/com/baseflow/geolocator/PositionStreamImpl.java similarity index 93% rename from geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java rename to geolocator/android/src/main/java/com/baseflow/geolocator/PositionStreamImpl.java index 6e84f410..e8845518 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/PositionStreamImpl.java @@ -15,8 +15,9 @@ import java.util.Map; -class StreamHandlerImpl implements EventChannel.StreamHandler { - private static final String TAG = "StreamHandlerImpl"; +class PositionStreamImpl implements EventChannel.StreamHandler { + + private static final String TAG = "PositionStreamImpl"; private final GeolocationManager geolocationManager; @@ -25,7 +26,7 @@ class StreamHandlerImpl implements EventChannel.StreamHandler { @Nullable private Activity activity; @Nullable private LocationClient locationClient; - public StreamHandlerImpl(GeolocationManager geolocationManager) { + public PositionStreamImpl(GeolocationManager geolocationManager) { this.geolocationManager = geolocationManager; } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java index 1d6ba561..14648f48 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GeolocationManager.java @@ -14,7 +14,6 @@ import com.baseflow.geolocator.permission.PermissionManager; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; -; import io.flutter.plugin.common.PluginRegistry.ActivityResultListener; import java.util.ArrayList; import java.util.List; @@ -74,16 +73,9 @@ public void startPositionUpdates( errorCallback); } - public NmeaMessageaClient createNmeaClient(Context context){ - if (android.os.Build.VERSION.SDK_INT >= VERSION_CODES.N){ - GnssNmeaMessageClient client = new GnssNmeaMessageClient(context); - System.out.println("created gnss"); - return client; - } else{ - GpsNmeaMessageClient client = new GpsNmeaMessageClient(context); - System.out.println("created gps"); - return client; - } + public void stopPositionUpdates(@NonNull LocationClient locationClient) { + locationClients.remove(locationClient); + locationClient.stopPositionUpdates(); } @@ -97,11 +89,14 @@ public void startNmeaUpdates(Context context, Activity activity, NmeaMessageaCli errorCallback); } - public void stopPositionUpdates(@NonNull LocationClient locationClient) { - locationClients.remove(locationClient); - locationClient.stopPositionUpdates(); + public void stopNmeaUpdates(NmeaMessageaClient client) { + client.stopNmeaUpdates(); } + public NmeaMessageaClient createNmeaClient(Context context) { + return android.os.Build.VERSION.SDK_INT >= VERSION_CODES.N ? new GnssNmeaMessageClient(context) + : new GpsNmeaMessageClient(context); + } public LocationClient createLocationClient( Context context, @@ -111,7 +106,9 @@ public LocationClient createLocationClient( return new LocationManagerClient(context, locationOptions); } - return new LocationManagerClient(context, locationOptions); + return isGooglePlayServicesAvailable(context) + ? new FusedLocationClient(context, locationOptions) + : new LocationManagerClient(context, locationOptions); } private boolean isGooglePlayServicesAvailable(Context context) { diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GnssNmeaMessageClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GnssNmeaMessageClient.java index 8d2faf9c..d162b239 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GnssNmeaMessageClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GnssNmeaMessageClient.java @@ -6,45 +6,55 @@ import android.location.LocationListener; import android.location.LocationManager; import android.location.OnNmeaMessageListener; -import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.os.Looper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.errors.ErrorCodes; -@RequiresApi(api = VERSION_CODES.N) -public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationListener, NmeaMessageaClient { +@SuppressLint("NewApi") +public class GnssNmeaMessageClient implements OnNmeaMessageListener, LocationListener, + NmeaMessageaClient { - private final LocationManager locationManager; + 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); - this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10000f, this); - this.locationManager.addNmeaListener(this, null); - System.out.println("gnss nmea client initialized"); } public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback) { + this.locationManager.addNmeaListener(this, null); + this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, this, + Looper.getMainLooper()); this.nmeaChangedCallback = nmeaChangedCallback; this.errorCallback = errorCallback; + this.isListening = true; + } + + @Override + public void stopNmeaUpdates() { + this.isListening = false; + this.locationManager.removeUpdates(this); } @Override public void onNmeaMessage(String s, long l) { - System.out.println("got nmea message"); - if (this.nmeaChangedCallback != null){ + if (this.nmeaChangedCallback != null) { this.nmeaChangedCallback.onNmeaMessage(s, l); } } @@ -52,7 +62,6 @@ public void onNmeaMessage(String s, long l) { @Override public void onLocationChanged(@NonNull Location location) { - } @Override @@ -60,6 +69,7 @@ public void onStatusChanged(String s, int i, Bundle bundle) { } + @Override public void onProviderEnabled(String s) { @@ -67,6 +77,15 @@ public void onProviderEnabled(String s) { @Override public void onProviderDisabled(String s) { + if (s.equals(locationManager.GPS_PROVIDER)) { + if (isListening) { + this.locationManager.removeUpdates(this); + } + if (this.errorCallback != null) { + errorCallback.onError(ErrorCodes.locationServicesDisabled); + } + + } } } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GpsNmeaMessageClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GpsNmeaMessageClient.java index c489d330..7e7b81e7 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/GpsNmeaMessageClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/GpsNmeaMessageClient.java @@ -1,71 +1,77 @@ package com.baseflow.geolocator.location; -import android.annotation.SuppressLint; import android.content.Context; import android.location.GpsStatus; -import android.location.GpsStatus.Listener; -import android.location.GpsStatus.NmeaListener; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; -import android.location.OnNmeaMessageListener; -import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.baseflow.geolocator.errors.ErrorCallback; +import com.baseflow.geolocator.errors.ErrorCodes; + -@SuppressLint("NewApi") public class GpsNmeaMessageClient implements LocationListener, GpsStatus.NmeaListener, - GpsStatus.Listener, NmeaMessageaClient { + NmeaMessageaClient { LocationManager locationManager; @Nullable private NmeaChangedCallback nmeaChangedCallback; + @Nullable private ErrorCallback errorCallback; + private boolean isListening = false; + public GpsNmeaMessageClient( @NonNull Context context) { this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10000f, this); - locationManager.addNmeaListener(this); - locationManager.addGpsStatusListener(this); - System.out.println("gps nmea client initialized"); } public void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback) { + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10000f, this); + locationManager.addNmeaListener(this); this.nmeaChangedCallback = nmeaChangedCallback; this.errorCallback = errorCallback; + this.isListening = true; + } + + @Override + public void stopNmeaUpdates() { + this.isListening = false; + this.locationManager.removeUpdates(this); } @Override public void onLocationChanged(@NonNull Location location) { - System.out.println("Location changed"); } @Override public void onProviderEnabled(String s) { - System.out.println("on provider enabled"); + } @Override public void onProviderDisabled(String s) { - System.out.println("provider disabled"); + if (s.equals(locationManager.GPS_PROVIDER)) { + if (isListening) { + this.locationManager.removeUpdates(this); + } + + if (this.errorCallback != null) { + errorCallback.onError(ErrorCodes.locationServicesDisabled); + } + + } } @Override public void onNmeaReceived(long l, String s) { - System.out.println("nmaerecieved"); if (this.nmeaChangedCallback != null) { this.nmeaChangedCallback.onNmeaMessage(s, l); } } - - @Override - public void onGpsStatusChanged(int i) { - System.out.println("gps status changed"); - } } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaChangedCallback.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaChangedCallback.java index 38fdeb84..378a9e47 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaChangedCallback.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaChangedCallback.java @@ -3,5 +3,6 @@ @FunctionalInterface public interface NmeaChangedCallback { - void onNmeaMessage(String message, long timeStamp); + + void onNmeaMessage(String message, long timeStamp); } diff --git a/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaMessageaClient.java b/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaMessageaClient.java index 7c416ed1..fb671064 100644 --- a/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaMessageaClient.java +++ b/geolocator/android/src/main/java/com/baseflow/geolocator/location/NmeaMessageaClient.java @@ -6,4 +6,6 @@ public interface NmeaMessageaClient { void startNmeaUpdates(NmeaChangedCallback nmeaChangedCallback, ErrorCallback errorCallback); + + void stopNmeaUpdates(); } diff --git a/geolocator/example/android/app/src/main/res/values/styles.xml b/geolocator/example/android/app/src/main/res/values/styles.xml index 1f83a33f..322503e4 100644 --- a/geolocator/example/android/app/src/main/res/values/styles.xml +++ b/geolocator/example/android/app/src/main/res/values/styles.xml @@ -10,7 +10,7 @@ This theme determines the color of the Android Window while your Flutter UI initializes, as well as behind your Flutter UI while its running. - + This Theme is only used starting with V2 of Flutter's Android embedding. -->