Skip to content

Commit

Permalink
FIX: Ensure permission denied in geolocation.getCurrentPosition rejec…
Browse files Browse the repository at this point in the history
…ts the Promise

fixes facebook#22535

Moves the permission request logic on Android M and above to Native side to mimic IOS behavior.

Changelog:
----------

[Android] [Fixed] - Ensure permission denied in geolocation.getCurrentPosition rejects the promise

Test Plan:
----------

Verified via my test project which requests location via Geolocation service. If the permission request
is denied by the user the promise is rejected as well.

https://github.com/Jyrno42/rn-geoloctest
  • Loading branch information
Jyrno42 committed Feb 8, 2019
1 parent af41a53 commit 5bdd6a0
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 21 deletions.
27 changes: 6 additions & 21 deletions Libraries/Geolocation/Geolocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,27 +82,12 @@ const Geolocation = {
typeof geo_success === 'function',
'Must provide a valid geo_success callback.',
);
let hasPermission = true;
// Supports Android's new permission model. For Android older devices,
// it's always on.
if (Platform.OS === 'android' && Platform.Version >= 23) {
hasPermission = await PermissionsAndroid.check(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
);
if (!hasPermission) {
const status = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
);
hasPermission = status === PermissionsAndroid.RESULTS.GRANTED;
}
}
if (hasPermission) {
RCTLocationObserver.getCurrentPosition(
geo_options || {},
geo_success,
geo_error || logError,
);
}
// Permission checks/requests are done on the native side
RCTLocationObserver.getCurrentPosition(
geo_options || {},
geo_success,
geo_error || logError,
);
},

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ rn_android_library(
react_native_target("java/com/facebook/react/common:common"),
react_native_target("java/com/facebook/react/module/annotations:annotations"),
react_native_target("java/com/facebook/react/modules/core:core"),
react_native_target("java/com/facebook/react/modules/permissions:permissions"),
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package com.facebook.react.modules.location;

import android.annotation.SuppressLint;
import android.Manifest;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
Expand All @@ -19,6 +20,7 @@
import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.PromiseImpl;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
Expand All @@ -28,6 +30,7 @@
import com.facebook.react.common.SystemClock;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
import com.facebook.react.modules.permissions.PermissionsModule;
import javax.annotation.Nullable;

/**
Expand Down Expand Up @@ -115,6 +118,59 @@ private static LocationOptions fromReactMap(ReadableMap map) {
*/
@ReactMethod
public void getCurrentPosition(
final ReadableMap options,
final Callback success,
final Callback error) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final PermissionsModule perms = getReactApplicationContext().getNativeModule(PermissionsModule.class);

final Callback onPermissionGranted = new Callback() {
@Override
public void invoke(Object... args) {
String result = (String) args[0];
if (result == "granted") {
loadCurrentPosition(options, success, error);
} else {
error.invoke(PositionError.buildError(PositionError.PERMISSION_DENIED, "Location permission was not granted."));
}
}
};

final Callback onPermissionDenied = new Callback() {
@Override
public void invoke(Object... args) {
error.invoke(PositionError.buildError(PositionError.PERMISSION_DENIED, "Failed to request location permission."));
}
};

Callback onPermissionCheckFailed = new Callback() {
@Override
public void invoke(Object... args) {
error.invoke(PositionError.buildError(PositionError.PERMISSION_DENIED, "Failed to check location permission."));
}
};

Callback onPermissionChecked = new Callback() {
@Override
public void invoke(Object... args) {
boolean hasPermission = (boolean) args[0];

if (!hasPermission) {
perms.requestPermission(Manifest.permission.ACCESS_FINE_LOCATION, new PromiseImpl(onPermissionGranted, onPermissionDenied));
} else {
loadCurrentPosition(options, success, error);
}
}
};

perms.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, new PromiseImpl(onPermissionChecked, onPermissionCheckFailed));
return;
}

loadCurrentPosition(options, success, error);
}

private void loadCurrentPosition(
ReadableMap options,
final Callback success,
Callback error) {
Expand Down

0 comments on commit 5bdd6a0

Please sign in to comment.