defaultPositionStreamSource method

Stream<Position?> defaultPositionStreamSource({
  1. RequestPermissionCallback? requestPermissionCallback = Geolocator.requestPermission,
})

Create a position stream which is used as default value of CurrentLocationLayer.positionStream.

Implementation

Stream<Position?> defaultPositionStreamSource({
  RequestPermissionCallback? requestPermissionCallback =
      Geolocator.requestPermission,
}) {
  final cancelFunctions = <AsyncCallback>[];
  final streamController = StreamController<Position?>.broadcast();
  streamController
    ..onListen = () async {
      try {
        var permission = await Geolocator.checkPermission();
        if (permission == LocationPermission.denied &&
            requestPermissionCallback != null) {
          streamController.sink
              .addError(const lm.PermissionRequestingException());
          permission = await requestPermissionCallback();
        }
        switch (permission) {
          case LocationPermission.denied:
          case LocationPermission.deniedForever:
            if (streamController.isClosed) {
              break;
            }
            streamController.sink
                .addError(const lm.PermissionDeniedException());
            await streamController.close();
          case LocationPermission.whileInUse:
          case LocationPermission.always:
            try {
              final serviceEnabled =
                  await Geolocator.isLocationServiceEnabled();
              if (streamController.isClosed) {
                break;
              }
              if (!serviceEnabled) {
                streamController.sink
                    .addError(const ServiceDisabledException());
              }
            } on Exception catch (_) {}
            try {
              // The concept of location service doesn't exist on the web
              // platform
              if (!kIsWeb) {
                final subscription = Geolocator.getServiceStatusStream()
                    .listen((serviceStatus) {
                  if (serviceStatus == ServiceStatus.enabled) {
                    streamController.sink.add(null);
                  } else {
                    streamController.sink
                        .addError(const ServiceDisabledException());
                  }
                });
                cancelFunctions.add(subscription.cancel);
              }
            } on Exception catch (_) {}
            try {
              // getLastKnownPosition is not supported on the web platform
              if (!kIsWeb) {
                final lastKnown = await Geolocator.getLastKnownPosition();
                if (streamController.isClosed) {
                  break;
                }
                if (lastKnown != null) {
                  streamController.sink.add(lastKnown);
                }
              }
            } on Exception catch (_) {}
            try {
              final serviceEnabled =
                  await Geolocator.isLocationServiceEnabled();
              if (serviceEnabled) {
                final position = await Geolocator.getCurrentPosition();
                if (streamController.isClosed) {
                  break;
                }
                streamController.sink.add(position);
              }
            } on Exception catch (_) {}
            final subscription =
                Geolocator.getPositionStream().listen((position) {
              streamController.sink.add(position);
            });
            cancelFunctions.add(subscription.cancel);
          case LocationPermission.unableToDetermine:
            break;
        }
      } on PermissionDefinitionsNotFoundException {
        streamController.sink.addError(const IncorrectSetupException());
      }
    }
    ..onCancel = () async {
      await Future.wait(cancelFunctions.map((callback) => callback()));
      await streamController.close();
    };
  return streamController.stream;
}