-
-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Low location Precision due to removal of GoogleLocationEngine
?
#446
Comments
Has there been a solution to the problem since then? |
Based on the release notes https://github.com/maplibre/maplibre-native/releases/tag/android-v10.0.0 I created following patch which again include GMS location services. I think that solves the issue. Closing for now. diff --git a/node_modules/@maplibre/maplibre-react-native/android/rctmln/build.gradle b/node_modules/@maplibre/maplibre-react-native/android/rctmln/build.gradle
index 7ea3e1d..e8dae6c 100644
--- a/node_modules/@maplibre/maplibre-react-native/android/rctmln/build.gradle
+++ b/node_modules/@maplibre/maplibre-react-native/android/rctmln/build.gradle
@@ -37,6 +37,7 @@ dependencies {
implementation "org.maplibre.gl:android-sdk-turf:6.0.1"
// Dependencies
+ implementation "com.google.android.gms:play-services-location:21.0.1"
implementation "androidx.vectordrawable:vectordrawable:1.1.0"
implementation "androidx.annotation:annotation:1.7.0"
implementation "androidx.appcompat:appcompat:1.6.1"
diff --git a/node_modules/@maplibre/maplibre-react-native/android/rctmln/src/main/java/com/maplibre/rctmln/location/LocationManager.java b/node_modules/@maplibre/maplibre-react-native/android/rctmln/src/main/java/com/maplibre/rctmln/location/LocationManager.java
index bc5c444..738373e 100644
--- a/node_modules/@maplibre/maplibre-react-native/android/rctmln/src/main/java/com/maplibre/rctmln/location/LocationManager.java
+++ b/node_modules/@maplibre/maplibre-react-native/android/rctmln/src/main/java/com/maplibre/rctmln/location/LocationManager.java
@@ -12,6 +12,11 @@ import org.maplibre.android.location.engine.LocationEngineCallback;
import com.mapbox.android.core.location.LocationEngineListener;
import com.mapbox.android.core.location.LocationEnginePriority;
*/
+import org.maplibre.android.location.engine.LocationEngineProxy;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GoogleApiAvailability;
+import com.maplibre.rctmln.location.engine.GoogleLocationEngineImpl;
import org.maplibre.android.location.engine.LocationEngineDefault;
import org.maplibre.android.location.engine.LocationEngineRequest;
@@ -63,7 +68,13 @@ public class LocationManager implements LocationEngineCallback<LocationEngineRes
}
private void buildEngineRequest() {
- locationEngine = LocationEngineDefault.INSTANCE.getDefaultLocationEngine(this.context.getApplicationContext());
+ if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS) {
+ locationEngine = new LocationEngineProxy<>(new GoogleLocationEngineImpl(context.getApplicationContext()));
+ Log.d(LOG_TAG, "Google Location Engine created successfully.");
+ } else {
+ locationEngine = LocationEngineDefault.INSTANCE.getDefaultLocationEngine(this.context.getApplicationContext());
+ Log.d(LOG_TAG, "Default Location Engine created successfully.");
+ }
locationEngineRequest = new LocationEngineRequest.Builder(DEFAULT_INTERVAL_MILLIS)
.setFastestInterval(DEFAULT_FASTEST_INTERVAL_MILLIS)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
diff --git a/node_modules/@maplibre/maplibre-react-native/android/rctmln/src/main/java/com/maplibre/rctmln/location/engine/GoogleLocationEngineImpl.java b/node_modules/@maplibre/maplibre-react-native/android/rctmln/src/main/java/com/maplibre/rctmln/location/engine/GoogleLocationEngineImpl.java
new file mode 100644
index 0000000..55ba244
--- /dev/null
+++ b/node_modules/@maplibre/maplibre-react-native/android/rctmln/src/main/java/com/maplibre/rctmln/location/engine/GoogleLocationEngineImpl.java
@@ -0,0 +1,151 @@
+package com.maplibre.rctmln.location.engine;
+
+import android.annotation.SuppressLint;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.location.Location;
+import android.os.Looper;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.google.android.gms.location.FusedLocationProviderClient;
+import com.google.android.gms.location.LocationCallback;
+import com.google.android.gms.location.LocationRequest;
+import com.google.android.gms.location.LocationResult;
+import com.google.android.gms.location.LocationServices;
+import com.google.android.gms.location.Priority;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+
+import org.maplibre.android.location.engine.LocationEngineCallback;
+import org.maplibre.android.location.engine.LocationEngineImpl;
+import org.maplibre.android.location.engine.LocationEngineRequest;
+import org.maplibre.android.location.engine.LocationEngineResult;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Wraps implementation of Fused Location Provider
+ */
+public class GoogleLocationEngineImpl implements LocationEngineImpl<LocationCallback> {
+ private final FusedLocationProviderClient fusedLocationProviderClient;
+
+ @VisibleForTesting
+ GoogleLocationEngineImpl(FusedLocationProviderClient fusedLocationProviderClient) {
+ this.fusedLocationProviderClient = fusedLocationProviderClient;
+ }
+
+ public GoogleLocationEngineImpl(@NonNull Context context) {
+ this.fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
+ }
+
+ @NonNull
+ @Override
+ public LocationCallback createListener(LocationEngineCallback<LocationEngineResult> callback) {
+ return new GoogleLocationEngineCallbackTransport(callback);
+ }
+
+ @SuppressLint("MissingPermission")
+ @Override
+ public void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback)
+ throws SecurityException {
+ GoogleLastLocationEngineCallbackTransport transport =
+ new GoogleLastLocationEngineCallbackTransport(callback);
+ fusedLocationProviderClient.getLastLocation().addOnSuccessListener(transport).addOnFailureListener(transport);
+ }
+
+ @SuppressLint("MissingPermission")
+ @Override
+ public void requestLocationUpdates(@NonNull LocationEngineRequest request,
+ @NonNull LocationCallback listener,
+ @Nullable Looper looper) throws SecurityException {
+ fusedLocationProviderClient.requestLocationUpdates(toGMSLocationRequest(request), listener, looper);
+ }
+
+ @SuppressLint("MissingPermission")
+ @Override
+ public void requestLocationUpdates(@NonNull LocationEngineRequest request,
+ @NonNull PendingIntent pendingIntent) throws SecurityException {
+ fusedLocationProviderClient.requestLocationUpdates(toGMSLocationRequest(request), pendingIntent);
+ }
+
+ @Override
+ public void removeLocationUpdates(@NonNull LocationCallback listener) {
+ if (listener != null) {
+ fusedLocationProviderClient.removeLocationUpdates(listener);
+ }
+ }
+
+ @Override
+ public void removeLocationUpdates(PendingIntent pendingIntent) {
+ if (pendingIntent != null) {
+ fusedLocationProviderClient.removeLocationUpdates(pendingIntent);
+ }
+ }
+
+ private static LocationRequest toGMSLocationRequest(LocationEngineRequest request) {
+ LocationRequest.Builder builder = new LocationRequest.Builder(request.getInterval());
+ builder.setMinUpdateIntervalMillis(request.getFastestInterval());
+ builder.setMinUpdateDistanceMeters(request.getDisplacement());
+ builder.setMaxUpdateDelayMillis(request.getMaxWaitTime());
+ builder.setPriority(toGMSLocationPriority(request.getPriority()));
+ return builder.build();
+ }
+
+ private static int toGMSLocationPriority(int enginePriority) {
+ switch (enginePriority) {
+ case LocationEngineRequest.PRIORITY_HIGH_ACCURACY:
+ return Priority.PRIORITY_HIGH_ACCURACY;
+ case LocationEngineRequest.PRIORITY_BALANCED_POWER_ACCURACY:
+ return Priority.PRIORITY_BALANCED_POWER_ACCURACY;
+ case LocationEngineRequest.PRIORITY_LOW_POWER:
+ return Priority.PRIORITY_LOW_POWER;
+ case LocationEngineRequest.PRIORITY_NO_POWER:
+ default:
+ return Priority.PRIORITY_PASSIVE;
+ }
+ }
+
+ private static final class GoogleLocationEngineCallbackTransport extends LocationCallback {
+ private final LocationEngineCallback<LocationEngineResult> callback;
+
+ GoogleLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void onLocationResult(LocationResult locationResult) {
+ super.onLocationResult(locationResult);
+ List<Location> locations = locationResult.getLocations();
+ if (!locations.isEmpty()) {
+ callback.onSuccess(LocationEngineResult.create(locations));
+ } else {
+ callback.onFailure(new Exception("Unavailable location"));
+ }
+ }
+ }
+
+ @VisibleForTesting
+ static final class GoogleLastLocationEngineCallbackTransport
+ implements OnSuccessListener<Location>, OnFailureListener {
+ private final LocationEngineCallback<LocationEngineResult> callback;
+
+ GoogleLastLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void onSuccess(Location location) {
+ callback.onSuccess(location != null ? LocationEngineResult.create(location) :
+ LocationEngineResult.create(Collections.<Location>emptyList()));
+ }
+
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ callback.onFailure(e);
+ }
+ }
+}
\ No newline at end of file
|
@RobertSasak, Can you explain this in more detail? Was this related to this:
Was |
Correct. I have come to the same assumption. Without Google Location Service a device use only a GPS which takes longer time, requires direct vision to sky and use more battery. Proprietary Google Location Service combines also Wifi, mobile network and GPS. However I could not reliably verify it as I think it is depending on device and GPS conditions. |
@RobertSasak did the low precision ever occur again with your fix? I've a report on Android 13, where the location jumps, while it smoothly moves on Android 14. |
After a fix I provided there were no more reports from users. |
Did the initial report state, which Android version was used? Would be super helpful to know. If this fixes the problem for us too, I'm thinking we should allow a clean way to choose the location provider. |
Most of the user complains were from Android 34 which is Android 14. Few were also from 31 and 33. That would confirm also your findings. I agree it would be nice to be able to provide custom Location Provider. |
GoogleLocationEngine
?
It's reported to us, that in Flight Mode under Android 13 there is no new location at all in our app. Meanwhile it works on Google Maps on the same device and in our app under Android 14. Of course all of this can also be device specific. Will try patch package and report the result. Thanks for your swift responses! |
The Patch also fixed our problem, thanks @RobertSasak. Basically navigation based on user location reported by MapLibre was not useable on Android 13 with a Samsung S20. Also no location was reported at all in flight-mode while it was available in Google Maps. Weirdly we weren't able to reproduce on any other devices with Android 14/13/12. Will have to find a way to support both engines. |
Motivation
After upgrading maplibre-react-native to version 10.x I notice that on Android phone the location precision decrease. It is bit hard to debug but blue location circle is bigger.
Question
Can this be related to removing of Google Location Services com.google.android.gms ?
https://github.com/maplibre/maplibre-native/releases/tag/android-v10.0.0
If so is there a way of again using Google Location Services?
The text was updated successfully, but these errors were encountered: