Skip to content

Commit d891b8f

Browse files
Vivek Maskaramisaochan
authored andcommitted
Fix security exception crash while accessing network location provider (#1498)
* Fix security exception crash while accessing network location provider * Added java docs
1 parent 93b0db9 commit d891b8f

File tree

2 files changed

+61
-11
lines changed

2 files changed

+61
-11
lines changed

app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.free.nrw.commons.location;
22

33
import android.Manifest;
4+
import android.annotation.SuppressLint;
45
import android.app.Activity;
56
import android.content.Context;
67
import android.content.pm.PackageManager;
@@ -10,9 +11,10 @@
1011
import android.os.Bundle;
1112
import android.support.v4.app.ActivityCompat;
1213
import android.support.v4.content.ContextCompat;
13-
import android.util.Log;
1414

15+
import java.util.HashSet;
1516
import java.util.List;
17+
import java.util.Set;
1618
import java.util.concurrent.CopyOnWriteArrayList;
1719

1820
import timber.log.Timber;
@@ -29,6 +31,7 @@ public class LocationServiceManager implements LocationListener {
2931
private Location lastLocation;
3032
private final List<LocationUpdateListener> locationListeners = new CopyOnWriteArrayList<>();
3133
private boolean isLocationManagerRegistered = false;
34+
private Set<Activity> locationExplanationDisplayed = new HashSet<>();
3235

3336
/**
3437
* Constructs a new instance of LocationServiceManager.
@@ -51,7 +54,6 @@ public boolean isProviderEnabled() {
5154

5255
/**
5356
* Returns whether the location permission is granted.
54-
*
5557
* @return true if the location permission is granted
5658
*/
5759
public boolean isLocationPermissionGranted() {
@@ -73,19 +75,33 @@ public void requestPermissions(Activity activity) {
7375
LOCATION_REQUEST);
7476
}
7577

78+
/**
79+
* The permission explanation dialog box is now displayed just once for a particular activity. We are subscribing
80+
* to updates from multiple providers so its important to show the dialog just once. Otherwise it will be displayed
81+
* once for every provider, which in our case currently is 2.
82+
* @param activity
83+
* @return
84+
*/
7685
public boolean isPermissionExplanationRequired(Activity activity) {
77-
return !activity.isFinishing() &&
78-
ActivityCompat.shouldShowRequestPermissionRationale(activity,
79-
Manifest.permission.ACCESS_FINE_LOCATION);
86+
if (activity.isFinishing()) {
87+
return false;
88+
}
89+
boolean showRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION);
90+
if (showRequestPermissionRationale && !locationExplanationDisplayed.contains(activity)) {
91+
locationExplanationDisplayed.add(activity);
92+
return true;
93+
}
94+
return false;
8095
}
8196

8297
/**
8398
* Gets the last known location in cases where there wasn't time to register a listener
8499
* (e.g. when Location permission just granted)
85100
* @return last known LatLng
86101
*/
102+
@SuppressLint("MissingPermission")
87103
public LatLng getLKL() {
88-
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
104+
if (isLocationPermissionGranted()) {
89105
Location lastKL = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
90106
if (lastKL == null) {
91107
lastKL = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
@@ -107,9 +123,10 @@ public LatLng getLastLocation() {
107123
* Registers a LocationManager to listen for current location.
108124
*/
109125
public void registerLocationManager() {
110-
if (!isLocationManagerRegistered)
126+
if (!isLocationManagerRegistered) {
111127
isLocationManagerRegistered = requestLocationUpdatesFromProvider(LocationManager.NETWORK_PROVIDER)
112128
&& requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER);
129+
}
113130
}
114131

115132
/**
@@ -142,7 +159,7 @@ private boolean requestLocationUpdatesFromProvider(String locationProvider) {
142159
* @return LOCATION_SIGNIFICANTLY_CHANGED if location changed significantly
143160
* LOCATION_SLIGHTLY_CHANGED if location changed slightly
144161
*/
145-
protected LocationChangeType isBetterLocation(Location location, Location currentBestLocation) {
162+
private LocationChangeType isBetterLocation(Location location, Location currentBestLocation) {
146163

147164
if (currentBestLocation == null) {
148165
// A new location is always better than no location

app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
322322
protected void onStart() {
323323
super.onStart();
324324
locationManager.addLocationListener(this);
325-
locationManager.registerLocationManager();
325+
registerLocationUpdates();
326326
}
327327

328328
@Override
@@ -400,7 +400,7 @@ private void refreshView(LocationServiceManager.LocationChangeType locationChang
400400
return;
401401
}
402402

403-
locationManager.registerLocationManager();
403+
registerLocationUpdates();
404404
LatLng lastLocation = locationManager.getLastLocation();
405405

406406
if (curLatLng != null && curLatLng.equals(lastLocation)) { //refresh view only if location has changed
@@ -450,6 +450,39 @@ private void refreshView(LocationServiceManager.LocationChangeType locationChang
450450
}
451451
}
452452

453+
/**
454+
* This method first checks if the location permissions has been granted and then register the location manager for updates.
455+
*/
456+
private void registerLocationUpdates() {
457+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
458+
if (locationManager.isLocationPermissionGranted()) {
459+
locationManager.registerLocationManager();
460+
} else {
461+
// Should we show an explanation?
462+
if (locationManager.isPermissionExplanationRequired(this)) {
463+
new AlertDialog.Builder(this)
464+
.setMessage(getString(R.string.location_permission_rationale_nearby))
465+
.setPositiveButton("OK", (dialog, which) -> {
466+
requestLocationPermissions();
467+
dialog.dismiss();
468+
})
469+
.setNegativeButton("Cancel", (dialog, id) -> {
470+
showLocationPermissionDeniedErrorDialog();
471+
dialog.cancel();
472+
})
473+
.create()
474+
.show();
475+
476+
} else {
477+
// No explanation needed, we can request the permission.
478+
requestLocationPermissions();
479+
}
480+
}
481+
} else {
482+
locationManager.registerLocationManager();
483+
}
484+
}
485+
453486
private void populatePlaces(NearbyController.NearbyPlacesInfo nearbyPlacesInfo) {
454487
List<Place> placeList = nearbyPlacesInfo.placeList;
455488
LatLng[] boundaryCoordinates = nearbyPlacesInfo.boundaryCoordinates;
@@ -530,7 +563,7 @@ private void lockNearbyView(boolean lock) {
530563
locationManager.removeLocationListener(this);
531564
} else {
532565
lockNearbyView = false;
533-
locationManager.registerLocationManager();
566+
registerLocationUpdates();
534567
locationManager.addLocationListener(this);
535568
}
536569
}

0 commit comments

Comments
 (0)