Skip to content

Commit 8b683ba

Browse files
authored
Merge pull request #738 from Baseflow/callback_locationservice_platform_interface
Callback locationservice platform interface
2 parents eb30d03 + ab1e11f commit 8b683ba

File tree

8 files changed

+153
-2
lines changed

8 files changed

+153
-2
lines changed

geolocator_platform_interface/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.1.0
2+
3+
- Added the possibility to start a stream which will return an event when Location Services are manually enabled/disabled
4+
15
## 2.0.2
26

37
- Added definition of the `ActivityMissingException`.
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export 'location_accuracy.dart';
22
export 'location_permission.dart';
3+
export 'location_service.dart';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/// Describes the current state of the location service on the native platform.
2+
enum ServiceStatus {
3+
/// Indicates that the location service on the native platform is enabled.
4+
disabled,
5+
6+
/// Indicates that the location service on the native platform is enabled.
7+
enabled,
8+
}

geolocator_platform_interface/lib/src/geolocator_platform_interface.dart

+8
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ abstract class GeolocatorPlatform extends PlatformInterface {
107107
throw UnimplementedError('getCurrentPosition() has not been implemented.');
108108
}
109109

110+
/// Fires when the Location Service is manually disabled or enabled f.e.
111+
/// when Location Service in Settings is disabled, a event will be fired which
112+
/// returns a [LocationServiceStatus].
113+
Stream<ServiceStatus> getServiceStatusStream() {
114+
throw UnimplementedError(
115+
'getServiceStatusStream() has not been implemented.');
116+
}
117+
110118
/// Fires whenever the location changes inside the bounds of the
111119
/// [desiredAccuracy].
112120
///

geolocator_platform_interface/lib/src/implementations/method_channel_geolocator.dart

+27
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
2121
static const _eventChannel =
2222
EventChannel('flutter.baseflow.com/geolocator_updates');
2323

24+
/// The event channel used to receive [LocationServiceStatus] updates from the
25+
/// native platform.
26+
static const _serviceStatusEventChannel =
27+
EventChannel('flutter.baseflow.com/geolocator_service_updates');
28+
2429
/// On Android devices you can set [forceAndroidLocationManager]
2530
/// to true to force the plugin to use the [LocationManager] to determine the
2631
/// position instead of the [FusedLocationProviderClient]. On iOS this is
2732
/// ignored.
2833
bool forceAndroidLocationManager = false;
2934

3035
Stream<Position>? _positionStream;
36+
Stream<ServiceStatus>? _serviceStatusStream;
3137

3238
@override
3339
Future<LocationPermission> checkPermission() async {
@@ -121,6 +127,27 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
121127
}
122128
}
123129

130+
@override
131+
Stream<ServiceStatus> getServiceStatusStream() {
132+
if (_serviceStatusStream != null) {
133+
return _serviceStatusStream!;
134+
}
135+
var serviceStatusStream =
136+
_serviceStatusEventChannel.receiveBroadcastStream();
137+
138+
_serviceStatusStream = serviceStatusStream
139+
.map((dynamic element) => ServiceStatus.values[element as int])
140+
.handleError((error) {
141+
_serviceStatusStream = null;
142+
if (error is PlatformException) {
143+
_handlePlatformException(error);
144+
}
145+
throw error;
146+
});
147+
148+
return _serviceStatusStream!;
149+
}
150+
124151
@override
125152
Stream<Position> getPositionStream({
126153
LocationAccuracy desiredAccuracy = LocationAccuracy.best,

geolocator_platform_interface/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: A common platform interface for the geolocator plugin.
33
homepage: https://github.com/baseflow/flutter-geolocator
44
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
55
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
6-
version: 2.0.2
6+
version: 2.1.0
77

88
dependencies:
99
flutter:

geolocator_platform_interface/test/geolocator_platform_interface_test.dart

+14
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,20 @@ void main() {
101101
);
102102
});
103103

104+
test(
105+
// ignore: lines_longer_than_80_chars
106+
'Default implementation of getServiceStatusStream should throw unimplemented error',
107+
() {
108+
// Arrange
109+
final geolocatorPlatform = ExtendsGeolocatorPlatform();
110+
111+
// Act & Assert
112+
expect(
113+
geolocatorPlatform.getServiceStatusStream,
114+
throwsUnimplementedError,
115+
);
116+
});
117+
104118
test(
105119
// ignore: lines_longer_than_80_chars
106120
'Default implementation of getPositionStream should throw unimplemented error',

geolocator_platform_interface/test/src/implementations/method_channel_geolocator_test.dart

+90-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
55
import 'package:flutter_test/flutter_test.dart';
66
import 'package:geolocator_platform_interface/geolocator_platform_interface.dart';
77
import 'package:geolocator_platform_interface/src/implementations/method_channel_geolocator.dart';
8-
8+
import 'package:geolocator_platform_interface/src/enums/location_service.dart';
99
import 'event_channel_mock.dart';
1010
import 'method_channel_mock.dart';
1111

@@ -556,6 +556,95 @@ void main() {
556556
});
557557
});
558558

559+
group(
560+
// ignore: lines_longer_than_80_chars
561+
'getServiceStream: When requesting a stream of location service status updates',
562+
() {
563+
group(
564+
'And requesting for location service status updates multiple times',
565+
() {
566+
test('Should return the same stream', () {
567+
final methodChannelGeolocator = MethodChannelGeolocator();
568+
final firstStream =
569+
methodChannelGeolocator.getServiceStatusStream();
570+
final secondstream =
571+
methodChannelGeolocator.getServiceStatusStream();
572+
573+
expect(
574+
identical(firstStream, secondstream),
575+
true,
576+
);
577+
});
578+
});
579+
});
580+
581+
test(
582+
// ignore: lines_longer_than_80_chars
583+
'Should receive a stream with location service updates if permissions are granted',
584+
() async {
585+
// Arrange
586+
final streamController = StreamController<int>.broadcast();
587+
EventChannelMock(
588+
channelName: 'flutter.baseflow.com/geolocator_service_updates',
589+
stream: streamController.stream);
590+
591+
// Act
592+
final locationServiceStream =
593+
MethodChannelGeolocator().getServiceStatusStream();
594+
final streamQueue = StreamQueue(locationServiceStream);
595+
596+
// Emit test events
597+
streamController.add(0); // disabled value in native enum
598+
streamController.add(1); // enabled value in native enum
599+
600+
//Assert
601+
expect(await streamQueue.next, ServiceStatus.disabled);
602+
expect(await streamQueue.next, ServiceStatus.enabled);
603+
604+
// Clean up
605+
await streamQueue.cancel();
606+
await streamController.close();
607+
});
608+
609+
test(
610+
// ignore: lines_longer_than_80_chars
611+
'Should receive an exception if android activity is missing',
612+
() async {
613+
// Arrange
614+
final streamController =
615+
StreamController<PlatformException>.broadcast();
616+
EventChannelMock(
617+
channelName: 'flutter.baseflow.com/geolocator_service_updates',
618+
stream: streamController.stream,
619+
);
620+
621+
// Act
622+
final positionStream =
623+
MethodChannelGeolocator().getServiceStatusStream();
624+
final streamQueue = StreamQueue(positionStream);
625+
626+
// Emit test error
627+
streamController.addError(PlatformException(
628+
code: 'ACTIVITY_MISSING',
629+
message: 'Activity missing',
630+
details: null));
631+
632+
// Assert
633+
expect(
634+
streamQueue.next,
635+
throwsA(
636+
isA<ActivityMissingException>().having(
637+
(e) => e.message,
638+
'message',
639+
'Activity missing',
640+
),
641+
));
642+
643+
// Clean up
644+
streamQueue.cancel();
645+
streamController.close();
646+
});
647+
559648
test(
560649
// ignore: lines_longer_than_80_chars
561650
'Should receive a stream with position updates if permissions are granted',

0 commit comments

Comments
 (0)