Skip to content

Commit

Permalink
fix: crash on app start when permission is denied (#304)
Browse files Browse the repository at this point in the history
* fix: crash on app start when permission is denied

* fix: callbacks invoked multiple times
  • Loading branch information
g4rb4g3 committed Jul 10, 2024
1 parent d7487cf commit 768a769
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.android.gms.common.GoogleApiAvailability;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;

public class GeolocationModule extends ReactContextBaseJavaModule {
Expand Down Expand Up @@ -120,7 +121,7 @@ public void getCurrentPosition(

requestAuthorization(args -> mLocationManager.getCurrentLocationData(options, success, error), error);
} catch (SecurityException e) {
throwLocationPermissionMissing(e);
emitLocationPermissionMissing(e);
}
}

Expand All @@ -139,10 +140,10 @@ public void startObserving(ReadableMap options) {
}

requestAuthorization(args -> mLocationManager.startObserving(options), args -> {
throw new SecurityException(args.toString());
emitLocationPermissionMissing(new SecurityException(Arrays.toString(args)));
});
} catch (SecurityException e) {
throwLocationPermissionMissing(e);
emitLocationPermissionMissing(e);
}
}

Expand All @@ -159,11 +160,13 @@ public void stopObserving() {
/**
* Provides a clearer exception message than the default one.
*/
private static void throwLocationPermissionMissing(SecurityException e) {
throw new SecurityException(
"Looks like the app doesn't have the permission to access location.\n" +
"Add the following line to your app's AndroidManifest.xml:\n" +
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />", e);
private void emitLocationPermissionMissing(SecurityException e) {
String message =
"Looks like the app doesn't have the permission to access location.\n" +
"Add the following line to your app's AndroidManifest.xml:\n" +
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />\n" +
e.getMessage();
mLocationManager.emitError(PositionError.PERMISSION_DENIED, message);
}

private static class Configuration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
import android.annotation.SuppressLint;
import android.app.Activity;
import android.location.Location;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.content.Context;
import android.location.LocationManager;

import androidx.annotation.RequiresApi;
import androidx.annotation.NonNull;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.SystemClock;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.google.android.gms.location.FusedLocationProviderClient;
Expand All @@ -23,13 +23,7 @@
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.Priority;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.tasks.OnSuccessListener;

import java.util.function.Consumer;
import java.util.function.Function;

@SuppressLint("MissingPermission")
public class PlayServicesLocationManager extends BaseLocationManager {
Expand Down Expand Up @@ -157,28 +151,58 @@ private boolean isAnyProviderAvailable() {
return locationManager != null && (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER));
}

private LocationCallback createSingleLocationCallback(Callback success, Callback error){
private LocationCallback createSingleLocationCallback(Callback success, Callback error) {
final CallbackHolder callbackHolder = new CallbackHolder(success, error);

return new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
error.invoke(PositionError.buildError(PositionError.POSITION_UNAVAILABLE, "No location provided (FusedLocationProvider/lastLocation)."));
public void onLocationResult(@NonNull LocationResult locationResult) {
Location location = locationResult.getLastLocation();

if (location == null) {
callbackHolder.error(PositionError.buildError(PositionError.POSITION_UNAVAILABLE, "No location provided (FusedLocationProvider/lastLocation)."));
return;
}

Location location = locationResult.getLastLocation();
success.invoke(locationToMap(location));
callbackHolder.success(location);

mFusedLocationClient.removeLocationUpdates(mSingleLocationCallback);
mSingleLocationCallback = null;
}

@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
public void onLocationAvailability(@NonNull LocationAvailability locationAvailability) {
if (!locationAvailability.isLocationAvailable()) {
error.invoke(PositionError.buildError(PositionError.POSITION_UNAVAILABLE, "Location not available (FusedLocationProvider/lastLocation)."));
callbackHolder.error(PositionError.buildError(PositionError.POSITION_UNAVAILABLE, "Location not available (FusedLocationProvider/lastLocation)."));
}
}
};
}

private static class CallbackHolder {
Callback success;
Callback error;
public CallbackHolder(Callback success, Callback error) {
this.success = success;
this.error = error;
}

public void error(WritableMap cause) {
if (this.error == null) {
Log.e(this.getClass().getSimpleName(), "tried to invoke null error callback -> " + cause.toString());
return;
}
this.error.invoke(cause);
this.error = null;
}

public void success(Location location) {
if (this.success == null) {
Log.e(this.getClass().getSimpleName(), "tried to invoke null success callback");
return;
}
this.success.invoke(locationToMap(location));
this.success = null;
}
}
}

0 comments on commit 768a769

Please sign in to comment.