import 'dart:async'; import 'dart:math'; import 'package:gps/utils/environment.dart'; import 'package:location/location.dart'; import 'package:wakelock/wakelock.dart'; class GpsUtils { _Stream s; GpsUtils() : s = Environment.hasRealGps ? _RealGpsStream() : _FakeGpsStream(49.4833, 8.4667, Duration(milliseconds: 100)); Stream get stream => s.getStream(); } mixin _Stream { Stream getStream(); } class _RealGpsStream implements _Stream { // Really, really ugly // - Location package should have been encapsulated // - Permissions do not belong here Stream getStream() { final Location location = Location(); location.serviceEnabled().then((_serviceEnabled) => { if (!_serviceEnabled) {location.requestService()} }); location.hasPermission().then((_permissionGranted) => { if (_permissionGranted == PermissionStatus.denied) {location.requestPermission()} }); location.changeSettings( accuracy: LocationAccuracy.high, interval: 100, distanceFilter: 0.0); Wakelock.enable(); return location.onLocationChanged; } } class _FakeGpsStream implements _Stream { double lat; double lon; Duration dur; _FakeGpsStream(this.lat, this.lon, [this.dur = const Duration(seconds: 1)]); /// Generator which creates GPS coordinates around the given location. Stream getStream() async* { Map gpsPoint = { 'accuracy': 20.0, 'altitude': 100.0, 'speed': 1.0, 'speed_accuracy': 1.0, 'isMock': 1, 'verticalAccuracy': 20.0, 'headingAccuracy': 1.0, 'elapsedRealtimeNanos': 1000.0, 'elapsedRealtimeUncertaintyNanos': 2000.0, 'satelliteNumber': 0, 'provider': "dummy" }; double degree = 0.0; while (true) { await Future.delayed(dur); gpsPoint['time'] = DateTime.now().millisecondsSinceEpoch + 0.0; double rad = degree * pi / 180; gpsPoint['latitude'] = lat + cos(rad); gpsPoint['longitude'] = lon + sin(rad); gpsPoint['heading'] = degree; gpsPoint['altitude'] = degree; degree = (degree + 1) % 360; yield LocationData.fromMap(gpsPoint); } } }