Skip to content
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

Make Geolocation plugin work if Google Play Services are not enabled #2240

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.SystemClock;

import androidx.core.location.LocationManagerCompat;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.location.FusedLocationProviderClient;
Expand All @@ -14,6 +18,33 @@
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.Priority;

class LocationUpdateListener implements LocationListener {

private final LocationResultCallback callback;

public LocationUpdateListener(LocationResultCallback callback) {

this.callback = callback;
}

@Override
public void onLocationChanged(Location location) {
this.callback.success(location);
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}

@Override
public void onProviderEnabled(String provider) {
}

@Override
public void onProviderDisabled(String provider) {
}
}

public class Geolocation {

private FusedLocationProviderClient fusedLocationClient;
Expand All @@ -30,68 +61,117 @@ public Boolean isLocationServicesEnabled() {
return LocationManagerCompat.isLocationEnabled(lm);
}

@SuppressWarnings("MissingPermission")
public void sendLocation(boolean enableHighAccuracy, final LocationResultCallback resultCallback) {
int resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
if (resultCode == ConnectionResult.SUCCESS) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
private int getPriority(boolean enableHighAccuracy) {
boolean networkEnabled = false;
if (enableHighAccuracy) {
return Priority.PRIORITY_HIGH_ACCURACY;
}
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
networkEnabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
return networkEnabled ? Priority.PRIORITY_BALANCED_POWER_ACCURACY : Priority.PRIORITY_LOW_POWER;
}

private boolean hasPlayServices() {
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
}

if (this.isLocationServicesEnabled()) {
boolean networkEnabled = false;
/**
* If the play services are disabled, the location manager will be queryied to indicate what providers are available.
* Typical providers are `passive`, `network`, `fused` and `gps`
*
* This method selects the best appropriate
*/
private String getPreferredProvider(boolean enableHighAccuracy) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
var providers = lm.getProviders(true);
if(enableHighAccuracy) {
if(providers.contains("gps")){
return "gps";
}
if(providers.contains("fused")){
return "fused";
}
if(providers.contains("network")){
return "network";
}
}else{
if(providers.contains("network")){
return "network";
}
if(providers.contains("fused")){
return "fused";
}
if(providers.contains("gps")){
return "gps";
}
}
if(providers.contains("passive")){
return "passive";
}

try {
networkEnabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {}
return null;
}
@SuppressWarnings("MissingPermission")
public void sendLocation(boolean enableHighAccuracy, final LocationResultCallback resultCallback) {
if (!this.isLocationServicesEnabled()) {
resultCallback.error("location disabled");
return;
}

int lowPriority = networkEnabled ? Priority.PRIORITY_BALANCED_POWER_ACCURACY : Priority.PRIORITY_LOW_POWER;
int priority = enableHighAccuracy ? Priority.PRIORITY_HIGH_ACCURACY : lowPriority;
if (hasPlayServices()) {

LocationServices
LocationServices
.getFusedLocationProviderClient(context)
.getCurrentLocation(priority, null)
.getCurrentLocation(getPriority(enableHighAccuracy), null)
.addOnFailureListener(e -> resultCallback.error(e.getMessage()))
.addOnSuccessListener(
location -> {
if (location == null) {
resultCallback.error("location unavailable");
} else {
resultCallback.success(location);
location -> {
if (location == null) {
resultCallback.error("location unavailable");
} else {
resultCallback.success(location);
}
}
}
);
} else {
resultCallback.error("location disabled");
}
} else {
resultCallback.error("Google Play Services not available");
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

var provider = getPreferredProvider(enableHighAccuracy);
if (provider == null) {
resultCallback.error("Location unavaible: no providers defined. Note: Google Play Services are not available as well");
return;
}
lm.requestLocationUpdates(provider, 1000, 10, new LocationUpdateListener(resultCallback));
}


}

@SuppressWarnings("MissingPermission")
public void requestLocationUpdates(boolean enableHighAccuracy, int timeout, final LocationResultCallback resultCallback) {
int resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
if (resultCode == ConnectionResult.SUCCESS) {
clearLocationUpdates();
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);

LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (this.isLocationServicesEnabled()) {
boolean networkEnabled = false;

try {
networkEnabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {}
if (!this.isLocationServicesEnabled()) {
resultCallback.error("location disabled");
return;
}

LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

int lowPriority = networkEnabled ? Priority.PRIORITY_BALANCED_POWER_ACCURACY : Priority.PRIORITY_LOW_POWER;
int priority = enableHighAccuracy ? Priority.PRIORITY_HIGH_ACCURACY : lowPriority;
if (hasPlayServices()) {
clearLocationUpdates();
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);

LocationRequest locationRequest = new LocationRequest.Builder(10000)
LocationRequest locationRequest = new LocationRequest.Builder(10000)
.setMaxUpdateDelayMillis(timeout)
.setMinUpdateIntervalMillis(5000)
.setPriority(priority)
.setPriority(getPriority(enableHighAccuracy))
.build();

locationCallback =
locationCallback =
new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
Expand All @@ -104,12 +184,15 @@ public void onLocationResult(LocationResult locationResult) {
}
};

fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null);
} else {
resultCallback.error("location disabled");
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null);
} else {
resultCallback.error("Google Play Services not available");
var provider = getPreferredProvider(enableHighAccuracy);
if (provider == null) {
resultCallback.error("Location unavaible: no providers defined. Note: Google Play Services are not available as well");
return;
}
lm.requestLocationUpdates(provider, 1000, 10, new LocationUpdateListener(resultCallback));

}
}

Expand All @@ -130,8 +213,8 @@ public Location getLastLocation(int maximumAge) {
long locationAge = SystemClock.elapsedRealtimeNanos() - tmpLoc.getElapsedRealtimeNanos();
long maximumAgeNanoSec = maximumAge * 1000000L;
if (
locationAge <= maximumAgeNanoSec &&
(lastLoc == null || lastLoc.getElapsedRealtimeNanos() > tmpLoc.getElapsedRealtimeNanos())
locationAge <= maximumAgeNanoSec &&
(lastLoc == null || lastLoc.getElapsedRealtimeNanos() > tmpLoc.getElapsedRealtimeNanos())
) {
lastLoc = tmpLoc;
}
Expand Down