Skip to content

Commit

Permalink
[Android] Enhancement-561/satelliteCount and satellitesUsedInFix (#1364)
Browse files Browse the repository at this point in the history
* Added satelliteCount and satellitesUsedInFix to Android

* changed the text of the Changelog

* Created a AndroidPosition object with Android specific parameters.

* fixed test

* cleanup

* Update CHANGELOG.md

* Update pubspec.yaml

* Update geolocator_android/android/src/main/java/com/baseflow/geolocator/location/NmeaClient.java

Co-authored-by: Maurits van Beusekom <maurits@baseflow.com>

* Update geolocator_android/lib/src/types/android_position.dart

Co-authored-by: Maurits van Beusekom <maurits@baseflow.com>

* Update geolocator_android/lib/src/types/android_position.dart

Co-authored-by: Maurits van Beusekom <maurits@baseflow.com>

* Update geolocator_android/lib/src/types/android_position.dart

Co-authored-by: Maurits van Beusekom <maurits@baseflow.com>

* updated formatting

* dart format

* Update geolocator.dart

* Update position.dart

* reverted unused changes

---------

Co-authored-by: Maurits van Beusekom <maurits@baseflow.com>
  • Loading branch information
TimHoogstrate and mvanbeusekom authored Jan 22, 2024
1 parent 50b4d0f commit 85f4f95
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 7 deletions.
5 changes: 5 additions & 0 deletions geolocator_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 4.5.0

* Creates `AndroidPosition`, a child class of `Position` with Android specific properties.
* Adds the `satelliteCount` and `satellitesUsedInFix` to `AndroidPosition`.

## 4.4.1

* Fixes a bug where `getPositionStream` caused an `java.lang.IllegalStateException: passive location requests must have an explicit minimum update interval` because `minUpdateIntervalMillis` property in location request was set to -1 by default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ public static Map<String, Object> toHashMap(Location location) {

if (location.hasAltitude()) position.put("altitude", location.getAltitude());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && location.hasVerticalAccuracy())
position.put("altitude_accuracy", location.getVerticalAccuracyMeters());
position.put("altitude_accuracy", location.getVerticalAccuracyMeters());
if (location.hasAccuracy()) position.put("accuracy", (double) location.getAccuracy());
if (location.hasBearing()) position.put("heading", (double) location.getBearing());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && location.hasBearingAccuracy())
position.put("heading_accuracy", location.getBearingAccuracyDegrees());
position.put("heading_accuracy", location.getBearingAccuracyDegrees());
if (location.hasSpeed()) position.put("speed", (double) location.getSpeed());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && location.hasSpeedAccuracy())
position.put("speed_accuracy", (double) location.getSpeedAccuracyMetersPerSecond());
Expand All @@ -35,6 +35,16 @@ public static Map<String, Object> toHashMap(Location location) {
Double mslAltitude = location.getExtras().getDouble(NmeaClient.NMEA_ALTITUDE_EXTRA);
position.put("altitude", mslAltitude);
}
if (location.getExtras().containsKey(NmeaClient.GNSS_SATELLITE_COUNT_EXTRA)) {
Double mslSatelliteCount =
location.getExtras().getDouble(NmeaClient.GNSS_SATELLITE_COUNT_EXTRA);
position.put("gnss_satellite_count", mslSatelliteCount);
}
if (location.getExtras().containsKey(NmeaClient.GNSS_SATELLITES_USED_IN_FIX_EXTRA)) {
Double mslSatellitesUsedInFix =
location.getExtras().getDouble(NmeaClient.GNSS_SATELLITES_USED_IN_FIX_EXTRA);
position.put("gnss_satellites_used_in_fix", mslSatellitesUsedInFix);
}
}
return position;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.location.GnssStatus;
import android.location.Location;
import android.location.LocationManager;
import android.location.OnNmeaMessageListener;
Expand All @@ -17,15 +18,21 @@
public class NmeaClient {

public static final String NMEA_ALTITUDE_EXTRA = "geolocator_mslAltitude";
public static final String GNSS_SATELLITE_COUNT_EXTRA = "geolocator_mslSatelliteCount";
public static final String GNSS_SATELLITES_USED_IN_FIX_EXTRA = "geolocator_mslSatellitesUsedInFix";

private final Context context;
private final LocationManager locationManager;
@Nullable private final LocationOptions locationOptions;

@TargetApi(Build.VERSION_CODES.N)
private OnNmeaMessageListener nmeaMessageListener;
@TargetApi(Build.VERSION_CODES.N)
private GnssStatus.Callback gnssCallback;

private String lastNmeaMessage;
private double gnss_satellite_count;
private double gnss_satellites_used_in_fix;
@Nullable private Calendar lastNmeaMessageTime;
private boolean listenerAdded = false;

Expand All @@ -42,6 +49,19 @@ public NmeaClient(@NonNull Context context, @Nullable LocationOptions locationOp
lastNmeaMessageTime = Calendar.getInstance();
}
};

gnssCallback = new GnssStatus.Callback() {
@Override
public void onSatelliteStatusChanged(@NonNull GnssStatus status) {
gnss_satellite_count = status.getSatelliteCount();
gnss_satellites_used_in_fix = 0;
for (int i = 0; i < gnss_satellite_count; ++i) {
if (status.usedInFix(i)) {
++gnss_satellites_used_in_fix;
}
}
}
};
}
}

Expand All @@ -54,6 +74,7 @@ public void start() {
if (locationOptions != null && locationOptions.isUseMSLAltitude()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && locationManager != null) {
locationManager.addNmeaListener(nmeaMessageListener, null);
locationManager.registerGnssStatusCallback(gnssCallback, null);
listenerAdded = true;
}
}
Expand All @@ -63,6 +84,7 @@ public void stop() {
if (locationOptions != null && locationOptions.isUseMSLAltitude()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && locationManager != null) {
locationManager.removeNmeaListener(nmeaMessageListener);
locationManager.unregisterGnssStatusCallback(gnssCallback);
listenerAdded = false;
}
}
Expand All @@ -74,6 +96,12 @@ public void enrichExtrasWithNmea(@Nullable Location location) {
return;
}

if (location.getExtras() == null) {
location.setExtras(Bundle.EMPTY);
}
location.getExtras().putDouble(GNSS_SATELLITE_COUNT_EXTRA, gnss_satellite_count);
location.getExtras().putDouble(GNSS_SATELLITES_USED_IN_FIX_EXTRA, gnss_satellites_used_in_fix);

if (lastNmeaMessage != null && locationOptions != null && listenerAdded) {

Calendar expiryDate = Calendar.getInstance();
Expand Down
1 change: 1 addition & 0 deletions geolocator_android/lib/geolocator_android.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ export 'package:geolocator_platform_interface/geolocator_platform_interface.dart

export 'src/geolocator_android.dart';
export 'src/types/android_settings.dart' show AndroidSettings;
export 'src/types/android_position.dart' show AndroidPosition;
export 'src/types/foreground_settings.dart'
show AndroidResource, ForegroundNotificationConfig;
7 changes: 4 additions & 3 deletions geolocator_android/lib/src/geolocator_android.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:geolocator_android/geolocator_android.dart';
import 'package:geolocator_platform_interface/geolocator_platform_interface.dart';
import 'package:uuid/uuid.dart';

Expand Down Expand Up @@ -83,7 +84,7 @@ class GeolocatorAndroid extends GeolocatorPlatform {
final positionMap =
await _methodChannel.invokeMethod('getLastKnownPosition', parameters);

return positionMap != null ? Position.fromMap(positionMap) : null;
return positionMap != null ? AndroidPosition.fromMap(positionMap) : null;
} on PlatformException catch (e) {
final error = _handlePlatformException(e);

Expand Down Expand Up @@ -123,7 +124,7 @@ class GeolocatorAndroid extends GeolocatorPlatform {
}

final positionMap = await positionFuture;
return Position.fromMap(positionMap);
return AndroidPosition.fromMap(positionMap);
} on TimeoutException {
final parameters = <String, dynamic>{
'requestId': requestId,
Expand Down Expand Up @@ -191,7 +192,7 @@ class GeolocatorAndroid extends GeolocatorPlatform {

_positionStream = positionStream
.map<Position>((dynamic element) =>
Position.fromMap(element.cast<String, dynamic>()))
AndroidPosition.fromMap(element.cast<String, dynamic>()))
.handleError(
(error) {
if (error is PlatformException) {
Expand Down
98 changes: 98 additions & 0 deletions geolocator_android/lib/src/types/android_position.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import 'package:geolocator_platform_interface/geolocator_platform_interface.dart';
// ignore: depend_on_referenced_packages
import 'package:meta/meta.dart';

/// Contains additional location information only available on Android platforms.
@immutable
class AndroidPosition extends Position {
/// Constructs an instance with the given values for testing. [AndroidPosition]
/// instances constructed this way won't actually reflect any real information
/// from the platform, just whatever was passed in at construction time.
const AndroidPosition({
required this.satelliteCount,
required this.satellitesUsedInFix,
required longitude,
required latitude,
required timestamp,
required accuracy,
required altitude,
required altitudeAccuracy,
required heading,
required headingAccuracy,
required speed,
required speedAccuracy,
int? floor,
isMocked = false,
}) : super(
longitude: longitude,
latitude: latitude,
timestamp: timestamp,
accuracy: accuracy,
altitude: 0.0,
altitudeAccuracy: 0.0,
heading: 0.0,
headingAccuracy: 0.0,
speed: 0.0,
speedAccuracy: 0.0);

/// If available it returns the number of GNSS satellites.
///
/// If the number of satellites is not available it returns the default value: 0.0.
final double satelliteCount;

/// If available it returns the number of GNSS satellites used in fix.
///
/// If the number of satellites used in fix is not available it returns the default value: 0.0.
final double satellitesUsedInFix;

@override
bool operator ==(Object other) {
var areEqual = other is AndroidPosition &&
other.satelliteCount == satelliteCount &&
other.satellitesUsedInFix == satellitesUsedInFix;
return areEqual;
}

@override
String toString() {
return 'Latitude: $latitude, Longitude: $longitude, Satellite count: $satelliteCount, Satellites used in fix: $satellitesUsedInFix';
}

@override
int get hashCode => satelliteCount.hashCode ^ satellitesUsedInFix.hashCode;

/// Converts the supplied [Map] to an instance of the [AndroidPosition] class.
static AndroidPosition fromMap(dynamic message) {
final Map<dynamic, dynamic> positionMap = message;

return AndroidPosition(
satelliteCount: positionMap['gnss_satellite_count'] ?? 0.0,
satellitesUsedInFix: positionMap['gnss_satellites_used_in_fix'] ?? 0.0,
latitude: positionMap['latitude'],
longitude: positionMap['longitude'],
timestamp: DateTime.fromMillisecondsSinceEpoch(
positionMap['timestamp'].toInt(),
isUtc: true),
altitude: positionMap['altitude'] ?? 0.0,
altitudeAccuracy: positionMap['altitude_accuracy'] ?? 0.0,
accuracy: positionMap['accuracy'] ?? 0.0,
heading: positionMap['heading'] ?? 0.0,
headingAccuracy: positionMap['heading_accuracy'] ?? 0.0,
floor: positionMap['floor'],
speed: positionMap['speed'] ?? 0.0,
speedAccuracy: positionMap['speed_accuracy'] ?? 0.0,
isMocked: positionMap['is_mocked'] ?? false,
);
}

/// Converts the [AndroidPosition] instance into a [Map] instance that can be
/// serialized to JSON.
@override
Map<String, dynamic> toJson() {
return super.toJson()
..addAll({
'gnss_satellite_count': satelliteCount,
'gnss_satellites_used_in_fix': satellitesUsedInFix,
});
}
}
2 changes: 1 addition & 1 deletion geolocator_android/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: geolocator_android
description: Geolocation plugin for Flutter. This plugin provides the Android implementation for the geolocator.
repository: https://github.com/baseflow/flutter-geolocator/tree/main/geolocator_android
issue_tracker: https://github.com/baseflow/flutter-geolocator/issues?q=is%3Aissue+is%3Aopen
version: 4.4.1
version: 4.5.0

environment:
sdk: ">=2.15.0 <4.0.0"
Expand Down
4 changes: 3 additions & 1 deletion geolocator_android/test/geolocator_android_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'package:geolocator_android/geolocator_android.dart';
import 'event_channel_mock.dart';
import 'method_channel_mock.dart';

Position get mockPosition => Position(
Position get mockPosition => AndroidPosition(
latitude: 52.561270,
longitude: 5.639382,
timestamp: DateTime.fromMillisecondsSinceEpoch(
Expand All @@ -18,6 +18,8 @@ Position get mockPosition => Position(
),
altitude: 3000.0,
altitudeAccuracy: 0.0,
satelliteCount: 2.0,
satellitesUsedInFix: 2.0,
accuracy: 0.0,
heading: 0.0,
headingAccuracy: 0.0,
Expand Down

0 comments on commit 85f4f95

Please sign in to comment.