From ff8a3f95b88f01592d46962fedf82307af5c3365 Mon Sep 17 00:00:00 2001 From: androidseb Date: Sat, 6 Jan 2024 13:29:37 +0100 Subject: [PATCH 1/5] First iteration --- .../baseflow/geolocator/GeolocatorPlugin.java | 21 +++++++++- .../geolocator/StreamHandlerImpl.java | 6 ++- .../lib/src/geolocator_android.dart | 38 ++++++++++++++++--- .../lib/src/types/android_settings.dart | 4 ++ 4 files changed, 60 insertions(+), 9 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 9d16cdede..3b3dcd01d 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 @@ -31,6 +31,8 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { @Nullable private MethodCallHandlerImpl methodCallHandler; @Nullable private StreamHandlerImpl streamHandler; + @Nullable private StreamHandlerImpl streamHandler2; + private final ServiceConnection serviceConnection = new ServiceConnection() { @@ -68,9 +70,12 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin this.permissionManager, this.geolocationManager, this.locationAccuracyManager); methodCallHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - streamHandler = new StreamHandlerImpl(this.permissionManager); + streamHandler = new StreamHandlerImpl(this.permissionManager, "flutter.baseflow.com/geolocator_updates_android"); streamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); + streamHandler2 = new StreamHandlerImpl(this.permissionManager, "flutter.baseflow.com/geolocator_updates_android2"); + streamHandler2.startListening( + flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); locationServiceHandler = new LocationServiceHandlerImpl(); locationServiceHandler.setContext(flutterPluginBinding.getApplicationContext()); @@ -98,6 +103,9 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { if (streamHandler != null) { streamHandler.setActivity(binding.getActivity()); } + if (streamHandler2 != null) { + streamHandler2.setActivity(binding.getActivity()); + } if (foregroundLocationService != null) { foregroundLocationService.setActivity(pluginBinding.getActivity()); } @@ -123,6 +131,9 @@ public void onDetachedFromActivity() { if (streamHandler != null) { streamHandler.setActivity(null); } + if (streamHandler2 != null) { + streamHandler2.setActivity(null); + } if (foregroundLocationService != null) { foregroundLocationService.setActivity(null); } @@ -167,6 +178,9 @@ private void initialize(GeolocatorLocationService service) { if (streamHandler != null) { streamHandler.setForegroundLocationService(service); } + if (streamHandler2 != null) { + streamHandler2.setForegroundLocationService(service); + } } private void dispose() { @@ -181,6 +195,11 @@ private void dispose() { streamHandler.setForegroundLocationService(null); streamHandler = null; } + if (streamHandler2 != null) { + streamHandler2.stopListening(); + streamHandler2.setForegroundLocationService(null); + streamHandler2 = null; + } if (locationServiceHandler != null) { locationServiceHandler.setContext(null); locationServiceHandler.stopListening(); diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java index 2c0a983dd..142f27ca5 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java @@ -25,6 +25,7 @@ class StreamHandlerImpl implements EventChannel.StreamHandler { private static final String TAG = "FlutterGeolocator"; private final PermissionManager permissionManager; + private final String eventChannelIdentifier; @Nullable private EventChannel channel; @Nullable private Context context; @@ -33,8 +34,9 @@ class StreamHandlerImpl implements EventChannel.StreamHandler { @Nullable private GeolocationManager geolocationManager; @Nullable private LocationClient locationClient; - public StreamHandlerImpl(PermissionManager permissionManager) { + public StreamHandlerImpl(PermissionManager permissionManager, String eventChannelIdentifier) { this.permissionManager = permissionManager; + this.eventChannelIdentifier = eventChannelIdentifier; geolocationManager = new GeolocationManager(); } @@ -65,7 +67,7 @@ void startListening(Context context, BinaryMessenger messenger) { stopListening(); } - channel = new EventChannel(messenger, "flutter.baseflow.com/geolocator_updates_android"); + channel = new EventChannel(messenger, eventChannelIdentifier); channel.setStreamHandler(this); this.context = context; } diff --git a/geolocator_android/lib/src/geolocator_android.dart b/geolocator_android/lib/src/geolocator_android.dart index 8ebad88b9..ff73f295f 100644 --- a/geolocator_android/lib/src/geolocator_android.dart +++ b/geolocator_android/lib/src/geolocator_android.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flutter/services.dart'; +import 'package:geolocator_android/src/types/android_settings.dart'; import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; import 'package:uuid/uuid.dart'; @@ -15,6 +16,11 @@ class GeolocatorAndroid extends GeolocatorPlatform { static const _eventChannel = EventChannel('flutter.baseflow.com/geolocator_updates_android'); + /// The secondary event channel used to receive [Position] updates from the + /// native platform. + static const _eventChannel2 = + EventChannel('flutter.baseflow.com/geolocator_updates_android2'); + /// The event channel used to receive [LocationServiceStatus] updates from the /// native platform. static const _serviceStatusEventChannel = @@ -32,6 +38,7 @@ class GeolocatorAndroid extends GeolocatorPlatform { bool forcedLocationManager = false; Stream? _positionStream; + Stream? _positionStream2; Stream? _serviceStatusStream; final Uuid _uuid = const Uuid(); @@ -165,10 +172,20 @@ class GeolocatorAndroid extends GeolocatorPlatform { Stream getPositionStream({ LocationSettings? locationSettings, }) { - if (_positionStream != null) { - return _positionStream!; + final bool useSecondaryStream = locationSettings is AndroidSettings + ? locationSettings.useSecondaryStream + : false; + if (useSecondaryStream) { + if (_positionStream2 != null) { + return _positionStream2!; + } + } else { + if (_positionStream != null) { + return _positionStream!; + } } - var originalStream = _eventChannel.receiveBroadcastStream( + var originalStream = (useSecondaryStream ? _eventChannel2 : _eventChannel) + .receiveBroadcastStream( locationSettings?.toJson(), ); var positionStream = _wrapStream(originalStream); @@ -179,7 +196,11 @@ class GeolocatorAndroid extends GeolocatorPlatform { positionStream = positionStream.timeout( timeLimit, onTimeout: (s) { - _positionStream = null; + if (useSecondaryStream) { + _positionStream2 = null; + } else { + _positionStream = null; + } s.addError(TimeoutException( 'Time limit reached while waiting for position update.', timeLimit, @@ -189,7 +210,7 @@ class GeolocatorAndroid extends GeolocatorPlatform { ); } - _positionStream = positionStream + final Stream tmpStream = positionStream .map((dynamic element) => Position.fromMap(element.cast())) .handleError( @@ -200,7 +221,12 @@ class GeolocatorAndroid extends GeolocatorPlatform { throw error; }, ); - return _positionStream!; + if (useSecondaryStream) { + _positionStream2 = tmpStream; + } else { + _positionStream = tmpStream; + } + return tmpStream; } Stream _wrapStream(Stream incoming) { diff --git a/geolocator_android/lib/src/types/android_settings.dart b/geolocator_android/lib/src/types/android_settings.dart index fea5dfb01..08ee978ce 100644 --- a/geolocator_android/lib/src/types/android_settings.dart +++ b/geolocator_android/lib/src/types/android_settings.dart @@ -17,6 +17,7 @@ class AndroidSettings extends LocationSettings { Duration? timeLimit, this.foregroundNotificationConfig, this.useMSLAltitude = false, + this.useSecondaryStream = false, }) : super( accuracy: accuracy, distanceFilter: distanceFilter, @@ -74,6 +75,8 @@ class AndroidSettings extends LocationSettings { /// Defaults to false final bool useMSLAltitude; + final bool useSecondaryStream; + @override Map toJson() { return super.toJson() @@ -82,6 +85,7 @@ class AndroidSettings extends LocationSettings { 'timeInterval': intervalDuration?.inMilliseconds, 'foregroundNotificationConfig': foregroundNotificationConfig?.toJson(), 'useMSLAltitude': useMSLAltitude, + 'useSecondaryStream': useSecondaryStream, }); } } From e75565acb46ab2b086060fbb1e78b563970e3fc4 Mon Sep 17 00:00:00 2001 From: androidseb Date: Sat, 6 Jan 2024 14:44:45 +0100 Subject: [PATCH 2/5] Improved implementation to determine behavior based on the notification config --- .../baseflow/geolocator/GeolocatorPlugin.java | 30 ++++++++----------- .../geolocator/StreamHandlerImpl.java | 9 +++--- .../lib/src/geolocator_android.dart | 26 ++++++++-------- .../lib/src/types/android_settings.dart | 4 --- 4 files changed, 30 insertions(+), 39 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 3b3dcd01d..6f790d4c3 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 @@ -31,7 +31,7 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware { @Nullable private MethodCallHandlerImpl methodCallHandler; @Nullable private StreamHandlerImpl streamHandler; - @Nullable private StreamHandlerImpl streamHandler2; + @Nullable private StreamHandlerImpl streamHandlerFGN; private final ServiceConnection serviceConnection = new ServiceConnection() { @@ -73,8 +73,8 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin streamHandler = new StreamHandlerImpl(this.permissionManager, "flutter.baseflow.com/geolocator_updates_android"); streamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - streamHandler2 = new StreamHandlerImpl(this.permissionManager, "flutter.baseflow.com/geolocator_updates_android2"); - streamHandler2.startListening( + streamHandlerFGN = new StreamHandlerImpl(this.permissionManager, "flutter.baseflow.com/geolocator_updates_android_fgn"); + streamHandlerFGN.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); locationServiceHandler = new LocationServiceHandlerImpl(); @@ -103,8 +103,8 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { if (streamHandler != null) { streamHandler.setActivity(binding.getActivity()); } - if (streamHandler2 != null) { - streamHandler2.setActivity(binding.getActivity()); + if (streamHandlerFGN != null) { + streamHandlerFGN.setActivity(binding.getActivity()); } if (foregroundLocationService != null) { foregroundLocationService.setActivity(pluginBinding.getActivity()); @@ -131,8 +131,8 @@ public void onDetachedFromActivity() { if (streamHandler != null) { streamHandler.setActivity(null); } - if (streamHandler2 != null) { - streamHandler2.setActivity(null); + if (streamHandlerFGN != null) { + streamHandlerFGN.setActivity(null); } if (foregroundLocationService != null) { foregroundLocationService.setActivity(null); @@ -175,11 +175,8 @@ private void initialize(GeolocatorLocationService service) { foregroundLocationService = service; foregroundLocationService.flutterEngineConnected(); - if (streamHandler != null) { - streamHandler.setForegroundLocationService(service); - } - if (streamHandler2 != null) { - streamHandler2.setForegroundLocationService(service); + if (streamHandlerFGN != null) { + streamHandlerFGN.setForegroundLocationService(service); } } @@ -192,13 +189,12 @@ private void dispose() { } if (streamHandler != null) { streamHandler.stopListening(); - streamHandler.setForegroundLocationService(null); streamHandler = null; } - if (streamHandler2 != null) { - streamHandler2.stopListening(); - streamHandler2.setForegroundLocationService(null); - streamHandler2 = null; + if (streamHandlerFGN != null) { + streamHandlerFGN.stopListening(); + streamHandlerFGN.setForegroundLocationService(null); + streamHandlerFGN = null; } if (locationServiceHandler != null) { locationServiceHandler.setContext(null); diff --git a/geolocator_android/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java b/geolocator_android/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java index 142f27ca5..697d93dad 100644 --- a/geolocator_android/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java +++ b/geolocator_android/android/src/main/java/com/baseflow/geolocator/StreamHandlerImpl.java @@ -107,11 +107,6 @@ public void onListen(Object arguments, EventChannel.EventSink events) { return; } - if (foregroundLocationService == null) { - Log.e(TAG, "Location background service has not started correctly"); - return; - } - @SuppressWarnings("unchecked") Map map = (Map) arguments; boolean forceLocationManager = false; @@ -127,6 +122,10 @@ public void onListen(Object arguments, EventChannel.EventSink events) { (Map) map.get("foregroundNotificationConfig")); } if (foregroundNotificationOptions != null) { + if (foregroundLocationService == null) { + Log.e(TAG, "Location background service has not started correctly"); + return; + } Log.e(TAG, "Geolocator position updates started using Android foreground service"); foregroundLocationService.startLocationService(forceLocationManager, locationOptions, events); foregroundLocationService.enableBackgroundMode(foregroundNotificationOptions); diff --git a/geolocator_android/lib/src/geolocator_android.dart b/geolocator_android/lib/src/geolocator_android.dart index ff73f295f..c9fc6ee1b 100644 --- a/geolocator_android/lib/src/geolocator_android.dart +++ b/geolocator_android/lib/src/geolocator_android.dart @@ -18,8 +18,8 @@ class GeolocatorAndroid extends GeolocatorPlatform { /// The secondary event channel used to receive [Position] updates from the /// native platform. - static const _eventChannel2 = - EventChannel('flutter.baseflow.com/geolocator_updates_android2'); + static const _eventChannelFGN = + EventChannel('flutter.baseflow.com/geolocator_updates_android_fgn'); /// The event channel used to receive [LocationServiceStatus] updates from the /// native platform. @@ -38,7 +38,7 @@ class GeolocatorAndroid extends GeolocatorPlatform { bool forcedLocationManager = false; Stream? _positionStream; - Stream? _positionStream2; + Stream? _positionStreamFGN; Stream? _serviceStatusStream; final Uuid _uuid = const Uuid(); @@ -172,19 +172,19 @@ class GeolocatorAndroid extends GeolocatorPlatform { Stream getPositionStream({ LocationSettings? locationSettings, }) { - final bool useSecondaryStream = locationSettings is AndroidSettings - ? locationSettings.useSecondaryStream + final bool useForegroundNotification = locationSettings is AndroidSettings + ? locationSettings.foregroundNotificationConfig != null : false; - if (useSecondaryStream) { - if (_positionStream2 != null) { - return _positionStream2!; + if (useForegroundNotification) { + if (_positionStreamFGN != null) { + return _positionStreamFGN!; } } else { if (_positionStream != null) { return _positionStream!; } } - var originalStream = (useSecondaryStream ? _eventChannel2 : _eventChannel) + var originalStream = (useForegroundNotification ? _eventChannelFGN : _eventChannel) .receiveBroadcastStream( locationSettings?.toJson(), ); @@ -196,8 +196,8 @@ class GeolocatorAndroid extends GeolocatorPlatform { positionStream = positionStream.timeout( timeLimit, onTimeout: (s) { - if (useSecondaryStream) { - _positionStream2 = null; + if (useForegroundNotification) { + _positionStreamFGN = null; } else { _positionStream = null; } @@ -221,8 +221,8 @@ class GeolocatorAndroid extends GeolocatorPlatform { throw error; }, ); - if (useSecondaryStream) { - _positionStream2 = tmpStream; + if (useForegroundNotification) { + _positionStreamFGN = tmpStream; } else { _positionStream = tmpStream; } diff --git a/geolocator_android/lib/src/types/android_settings.dart b/geolocator_android/lib/src/types/android_settings.dart index 08ee978ce..fea5dfb01 100644 --- a/geolocator_android/lib/src/types/android_settings.dart +++ b/geolocator_android/lib/src/types/android_settings.dart @@ -17,7 +17,6 @@ class AndroidSettings extends LocationSettings { Duration? timeLimit, this.foregroundNotificationConfig, this.useMSLAltitude = false, - this.useSecondaryStream = false, }) : super( accuracy: accuracy, distanceFilter: distanceFilter, @@ -75,8 +74,6 @@ class AndroidSettings extends LocationSettings { /// Defaults to false final bool useMSLAltitude; - final bool useSecondaryStream; - @override Map toJson() { return super.toJson() @@ -85,7 +82,6 @@ class AndroidSettings extends LocationSettings { 'timeInterval': intervalDuration?.inMilliseconds, 'foregroundNotificationConfig': foregroundNotificationConfig?.toJson(), 'useMSLAltitude': useMSLAltitude, - 'useSecondaryStream': useSecondaryStream, }); } } From 0427dd358d303e08df08d1783f0bd8fd564ad7a2 Mon Sep 17 00:00:00 2001 From: androidseb Date: Sat, 6 Jan 2024 16:04:55 +0100 Subject: [PATCH 3/5] Fixed incorrect stream cancel handling for _positionStreamFGN --- .../lib/src/geolocator_android.dart | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/geolocator_android/lib/src/geolocator_android.dart b/geolocator_android/lib/src/geolocator_android.dart index c9fc6ee1b..96c3847c4 100644 --- a/geolocator_android/lib/src/geolocator_android.dart +++ b/geolocator_android/lib/src/geolocator_android.dart @@ -184,11 +184,12 @@ class GeolocatorAndroid extends GeolocatorPlatform { return _positionStream!; } } - var originalStream = (useForegroundNotification ? _eventChannelFGN : _eventChannel) - .receiveBroadcastStream( + var originalStream = + (useForegroundNotification ? _eventChannelFGN : _eventChannel) + .receiveBroadcastStream( locationSettings?.toJson(), ); - var positionStream = _wrapStream(originalStream); + var positionStream = _wrapStream(originalStream, useForegroundNotification); var timeLimit = locationSettings?.timeLimit; @@ -229,10 +230,17 @@ class GeolocatorAndroid extends GeolocatorPlatform { return tmpStream; } - Stream _wrapStream(Stream incoming) { + Stream _wrapStream( + Stream incoming, + bool useForegroundNotification, + ) { return incoming.asBroadcastStream(onCancel: (subscription) { subscription.cancel(); - _positionStream = null; + if (useForegroundNotification) { + _positionStreamFGN = null; + } else { + _positionStream = null; + } }); } From 47e7be2462d209dad8e97bb732963d1cf37e7515 Mon Sep 17 00:00:00 2001 From: androidseb Date: Tue, 26 Mar 2024 22:48:30 +0100 Subject: [PATCH 4/5] Fixed compile error --- .../src/main/java/com/baseflow/geolocator/GeolocatorPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 546f2b515..456efe295 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 @@ -73,7 +73,7 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin streamHandler = new StreamHandlerImpl(this.permissionManager, this.geolocationManager, "flutter.baseflow.com/geolocator_updates_android"); streamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); - streamHandlerFGN = new StreamHandlerImpl(this.permissionManager, "flutter.baseflow.com/geolocator_updates_android_fgn"); + streamHandlerFGN = new StreamHandlerImpl(this.permissionManager, this.geolocationManager, "flutter.baseflow.com/geolocator_updates_android_fgn"); streamHandlerFGN.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); From bf1cd25feffe761842e2202cf7b27f55442c6738 Mon Sep 17 00:00:00 2001 From: androidseb Date: Tue, 26 Mar 2024 23:01:03 +0100 Subject: [PATCH 5/5] Fixed linter warning --- geolocator_android/lib/src/geolocator_android.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/geolocator_android/lib/src/geolocator_android.dart b/geolocator_android/lib/src/geolocator_android.dart index 6f1845026..2400884d8 100644 --- a/geolocator_android/lib/src/geolocator_android.dart +++ b/geolocator_android/lib/src/geolocator_android.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/services.dart'; -import 'package:geolocator_android/src/types/android_settings.dart'; import 'package:geolocator_android/geolocator_android.dart'; import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; import 'package:uuid/uuid.dart';