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 1601f3b3..456efe29 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 streamHandlerFGN; + 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, this.geolocationManager); + streamHandler = new StreamHandlerImpl(this.permissionManager, this.geolocationManager, "flutter.baseflow.com/geolocator_updates_android"); streamHandler.startListening( flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); + streamHandlerFGN = new StreamHandlerImpl(this.permissionManager, this.geolocationManager, "flutter.baseflow.com/geolocator_updates_android_fgn"); + streamHandlerFGN.startListening( + flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); locationServiceHandler = new LocationServiceHandlerImpl(); locationServiceHandler.setContext(flutterPluginBinding.getApplicationContext()); @@ -97,6 +102,9 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { if (streamHandler != null) { streamHandler.setActivity(binding.getActivity()); } + if (streamHandlerFGN != null) { + streamHandlerFGN.setActivity(binding.getActivity()); + } if (foregroundLocationService != null) { foregroundLocationService.setActivity(pluginBinding.getActivity()); } @@ -122,6 +130,9 @@ public void onDetachedFromActivity() { if (streamHandler != null) { streamHandler.setActivity(null); } + if (streamHandlerFGN != null) { + streamHandlerFGN.setActivity(null); + } if (foregroundLocationService != null) { foregroundLocationService.setActivity(null); } @@ -164,8 +175,8 @@ private void initialize(GeolocatorLocationService service) { foregroundLocationService.setGeolocationManager(geolocationManager); foregroundLocationService.flutterEngineConnected(); - if (streamHandler != null) { - streamHandler.setForegroundLocationService(service); + if (streamHandlerFGN != null) { + streamHandlerFGN.setForegroundLocationService(service); } } @@ -178,9 +189,13 @@ private void dispose() { } if (streamHandler != null) { streamHandler.stopListening(); - streamHandler.setForegroundLocationService(null); streamHandler = null; } + if (streamHandlerFGN != null) { + streamHandlerFGN.stopListening(); + streamHandlerFGN.setForegroundLocationService(null); + streamHandlerFGN = 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 bf1d9f31..260700be 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,9 +34,10 @@ class StreamHandlerImpl implements EventChannel.StreamHandler { @Nullable private GeolocationManager geolocationManager; @Nullable private LocationClient locationClient; - public StreamHandlerImpl(PermissionManager permissionManager, GeolocationManager geolocationManager) { + public StreamHandlerImpl(PermissionManager permissionManager, GeolocationManager geolocationManager, String eventChannelIdentifier) { this.permissionManager = permissionManager; this.geolocationManager = geolocationManager; + this.eventChannelIdentifier = eventChannelIdentifier; } public void setForegroundLocationService( @@ -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; } @@ -105,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; @@ -125,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 04c1ced8..2400884d 100644 --- a/geolocator_android/lib/src/geolocator_android.dart +++ b/geolocator_android/lib/src/geolocator_android.dart @@ -16,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 _eventChannelFGN = + EventChannel('flutter.baseflow.com/geolocator_updates_android_fgn'); + /// The event channel used to receive [LocationServiceStatus] updates from the /// native platform. static const _serviceStatusEventChannel = @@ -33,6 +38,7 @@ class GeolocatorAndroid extends GeolocatorPlatform { bool forcedLocationManager = false; Stream? _positionStream; + Stream? _positionStreamFGN; Stream? _serviceStatusStream; final Uuid _uuid = const Uuid(); @@ -166,13 +172,24 @@ class GeolocatorAndroid extends GeolocatorPlatform { Stream getPositionStream({ LocationSettings? locationSettings, }) { - if (_positionStream != null) { - return _positionStream!; + final bool useForegroundNotification = locationSettings is AndroidSettings + ? locationSettings.foregroundNotificationConfig != null + : false; + if (useForegroundNotification) { + if (_positionStreamFGN != null) { + return _positionStreamFGN!; + } + } else { + if (_positionStream != null) { + return _positionStream!; + } } - var originalStream = _eventChannel.receiveBroadcastStream( + var originalStream = + (useForegroundNotification ? _eventChannelFGN : _eventChannel) + .receiveBroadcastStream( locationSettings?.toJson(), ); - var positionStream = _wrapStream(originalStream); + var positionStream = _wrapStream(originalStream, useForegroundNotification); var timeLimit = locationSettings?.timeLimit; @@ -180,7 +197,11 @@ class GeolocatorAndroid extends GeolocatorPlatform { positionStream = positionStream.timeout( timeLimit, onTimeout: (s) { - _positionStream = null; + if (useForegroundNotification) { + _positionStreamFGN = null; + } else { + _positionStream = null; + } s.addError(TimeoutException( 'Time limit reached while waiting for position update.', timeLimit, @@ -190,7 +211,7 @@ class GeolocatorAndroid extends GeolocatorPlatform { ); } - _positionStream = positionStream + final Stream tmpStream = positionStream .map((dynamic element) => AndroidPosition.fromMap(element.cast())) .handleError( @@ -201,13 +222,25 @@ class GeolocatorAndroid extends GeolocatorPlatform { throw error; }, ); - return _positionStream!; + if (useForegroundNotification) { + _positionStreamFGN = tmpStream; + } else { + _positionStream = tmpStream; + } + 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; + } }); }