Skip to content

Commit 9187204

Browse files
authored
Merge pull request #250 from dpa99c/android_permission_types
fix(android): respect requested location accuracy on Android 12+
2 parents e831e0d + 73719d9 commit 9187204

File tree

2 files changed

+54
-21
lines changed

2 files changed

+54
-21
lines changed

src/android/Geolocation.java

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,46 @@ Licensed to the Apache Software Foundation (ASF) under one
2323
import android.os.Build;
2424

2525
import org.apache.cordova.CallbackContext;
26-
import org.apache.cordova.CordovaArgs;
2726
import org.apache.cordova.CordovaPlugin;
2827
import org.apache.cordova.PermissionHelper;
2928
import org.apache.cordova.PluginResult;
3029
import org.apache.cordova.LOG;
3130
import org.json.JSONArray;
3231
import org.json.JSONException;
3332

34-
import javax.security.auth.callback.Callback;
3533

3634
public class Geolocation extends CordovaPlugin {
3735

3836
String TAG = "GeolocationPlugin";
3937
CallbackContext context;
4038

41-
String [] permissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION };
39+
40+
String [] highAccuracyPermissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION };
41+
String [] lowAccuracyPermissions = { Manifest.permission.ACCESS_COARSE_LOCATION };
42+
String [] permissionsToRequest;
43+
String[] permissionsToCheck;
4244

4345

4446
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
4547
LOG.d(TAG, "We are entering execute");
4648
context = callbackContext;
4749
if(action.equals("getPermission"))
4850
{
49-
if(hasPermisssion())
51+
boolean highAccuracy = args.getBoolean(0);
52+
permissionsToCheck = highAccuracy ? highAccuracyPermissions : lowAccuracyPermissions;
53+
54+
// Always request both FINE & COARSE permissions on API <= 31 due to bug in WebView that manifests on these versions
55+
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1269362
56+
permissionsToRequest = Build.VERSION.SDK_INT <= 31 ? highAccuracyPermissions : permissionsToCheck;
57+
58+
if(hasPermisssion(permissionsToCheck))
5059
{
51-
PluginResult r = new PluginResult(PluginResult.Status.OK);
60+
PluginResult r = new PluginResult(PluginResult.Status.OK, Build.VERSION.SDK_INT);
5261
context.sendPluginResult(r);
5362
return true;
5463
}
5564
else {
56-
PermissionHelper.requestPermissions(this, 0, permissions);
65+
PermissionHelper.requestPermissions(this, 0, permissionsToRequest);
5766
}
5867
return true;
5968
}
@@ -67,8 +76,10 @@ public void onRequestPermissionResult(int requestCode, String[] permissions,
6776
PluginResult result;
6877
//This is important if we're using Cordova without using Cordova, but we have the geolocation plugin installed
6978
if(context != null) {
70-
for (int r : grantResults) {
71-
if (r == PackageManager.PERMISSION_DENIED) {
79+
for (int i=0; i<grantResults.length; i++) {
80+
int r = grantResults[i];
81+
String p = permissions[i];
82+
if (r == PackageManager.PERMISSION_DENIED && arrayContains(permissionsToCheck, p)) {
7283
LOG.d(TAG, "Permission Denied!");
7384
result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
7485
context.sendPluginResult(result);
@@ -81,7 +92,7 @@ public void onRequestPermissionResult(int requestCode, String[] permissions,
8192
}
8293
}
8394

84-
public boolean hasPermisssion() {
95+
public boolean hasPermisssion(String[] permissions) {
8596
for(String p : permissions)
8697
{
8798
if(!PermissionHelper.hasPermission(this, p))
@@ -99,9 +110,23 @@ public boolean hasPermisssion() {
99110

100111
public void requestPermissions(int requestCode)
101112
{
102-
PermissionHelper.requestPermissions(this, requestCode, permissions);
113+
PermissionHelper.requestPermissions(this, requestCode, permissionsToRequest);
103114
}
104115

116+
//https://stackoverflow.com/a/12635769/777265
117+
private <T> boolean arrayContains(final T[] array, final T v) {
118+
if (v == null) {
119+
for (final T e : array)
120+
if (e == null)
121+
return true;
122+
}
123+
else {
124+
for (final T e : array)
125+
if (e == v || v.equals(e))
126+
return true;
127+
}
105128

129+
return false;
130+
}
106131

107132
}

www/android/geolocation.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ var pluginToNativeWatchMap = {};
2929

3030
module.exports = {
3131
getCurrentPosition: function (success, error, args) {
32-
var win = function () {
32+
var win = function (deviceApiLevel) {
33+
// Workaround for bug specific to API 31 where requesting `enableHighAccuracy: false` results in TIMEOUT error.
34+
if (deviceApiLevel === 31) {
35+
if (typeof args === 'undefined') args = {};
36+
args.enableHighAccuracy = true;
37+
}
3338
var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); // eslint-disable-line no-undef
3439
geo.getCurrentPosition(success, error, args);
3540
};
@@ -38,13 +43,19 @@ module.exports = {
3843
error(new PositionError(PositionError.PERMISSION_DENIED, 'Illegal Access'));
3944
}
4045
};
41-
exec(win, fail, 'Geolocation', 'getPermission', []);
46+
var enableHighAccuracy = typeof args === 'object' && !!args.enableHighAccuracy;
47+
exec(win, fail, 'Geolocation', 'getPermission', [enableHighAccuracy]);
4248
},
4349

4450
watchPosition: function (success, error, args) {
4551
var pluginWatchId = utils.createUUID();
4652

47-
var win = function () {
53+
var win = function (deviceApiLevel) {
54+
// Workaround for bug specific to API 31 where requesting `enableHighAccuracy: false` results in TIMEOUT error.
55+
if (deviceApiLevel === 31) {
56+
if (typeof args === 'undefined') args = {};
57+
args.enableHighAccuracy = true;
58+
}
4859
var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); // eslint-disable-line no-undef
4960
pluginToNativeWatchMap[pluginWatchId] = geo.watchPosition(success, error, args);
5061
};
@@ -54,18 +65,15 @@ module.exports = {
5465
error(new PositionError(PositionError.PERMISSION_DENIED, 'Illegal Access'));
5566
}
5667
};
57-
exec(win, fail, 'Geolocation', 'getPermission', []);
68+
var enableHighAccuracy = typeof args === 'object' && !!args.enableHighAccuracy;
69+
exec(win, fail, 'Geolocation', 'getPermission', [enableHighAccuracy]);
5870

5971
return pluginWatchId;
6072
},
6173

6274
clearWatch: function (pluginWatchId) {
63-
var win = function () {
64-
var nativeWatchId = pluginToNativeWatchMap[pluginWatchId];
65-
var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); // eslint-disable-line no-undef
66-
geo.clearWatch(nativeWatchId);
67-
};
68-
69-
exec(win, null, 'Geolocation', 'getPermission', []);
75+
var nativeWatchId = pluginToNativeWatchMap[pluginWatchId];
76+
var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); // eslint-disable-line no-undef
77+
geo.clearWatch(nativeWatchId);
7078
}
7179
};

0 commit comments

Comments
 (0)