Skip to content

Commit 3b129a6

Browse files
misaochanneslihanturan
authored andcommitted
Fix security exception (Nearby places not loading after permissions granted) (commons-app#1440)
* Update changelog.md * Versioning for v2.7.0 * Add logging to onPermissionsRequestResult * Request location updates onStatusChanged * Copy onResume() actions into onPermissionsRequestResult * Added getLastKnownLocation method and hooked it up to refreshView * Remove unnecessary calls, add more logging * Add check to prevent NPE * Check that curLatLng exists before getting Mapbox instance * Moar logging * Make curLatLang clearer * Not a good hack - put curLatLang into the bundle separately * Add TODO * Rename variables for clarity * Check for Network Provider as well, tidy up getLKL() * Add Javadocs * Remove unnecessary method in onStatusChanged * Add checkGPS comment * Remove unnecessary logs * Add TODO * Call bundle.clear() before inserting CurLatLng
1 parent 9a3b6fc commit 3b129a6

File tree

4 files changed

+58
-16
lines changed

4 files changed

+58
-16
lines changed

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,23 @@ public boolean isPermissionExplanationRequired(Activity activity) {
7979
Manifest.permission.ACCESS_FINE_LOCATION);
8080
}
8181

82+
/**
83+
* Gets the last known location in cases where there wasn't time to register a listener
84+
* (e.g. when Location permission just granted)
85+
* @return last known LatLng
86+
*/
87+
public LatLng getLKL() {
88+
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
89+
Location lastKL = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
90+
if (lastKL == null) {
91+
lastKL = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
92+
}
93+
return LatLng.from(lastKL);
94+
} else {
95+
return null;
96+
}
97+
}
98+
8299
public LatLng getLastLocation() {
83100
if (lastLocation == null) {
84101
return null;
@@ -249,6 +266,7 @@ public void onProviderDisabled(String provider) {
249266
public enum LocationChangeType{
250267
LOCATION_SIGNIFICANTLY_CHANGED, //Went out of borders of nearby markers
251268
LOCATION_SLIGHTLY_CHANGED, //User might be walking or driving
252-
LOCATION_NOT_CHANGED
269+
LOCATION_NOT_CHANGED,
270+
PERMISSION_JUST_GRANTED
253271
}
254272
}

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

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,12 @@
1313

1414
import android.support.v4.app.FragmentTransaction;
1515
import android.support.v7.app.AlertDialog;
16-
import android.util.Log;
1716
import android.view.Menu;
1817
import android.view.MenuInflater;
1918
import android.view.MenuItem;
2019
import android.view.View;
2120
import android.widget.LinearLayout;
2221
import android.widget.ProgressBar;
23-
import android.widget.Toast;
2422

2523
import com.google.gson.Gson;
2624
import com.google.gson.GsonBuilder;
@@ -81,6 +79,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
8179

8280
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
8381
private BroadcastReceiver broadcastReceiver;
82+
private LatLng lastKnownLocation;
8483

8584
@Override
8685
protected void onCreate(Bundle savedInstanceState) {
@@ -158,7 +157,11 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
158157
switch (requestCode) {
159158
case LOCATION_REQUEST: {
160159
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
161-
refreshView(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED);
160+
Timber.d("Location permission granted, refreshing view");
161+
//Still need to check if GPS is enabled
162+
checkGps();
163+
lastKnownLocation = locationManager.getLKL();
164+
refreshView(LocationServiceManager.LocationChangeType.PERMISSION_JUST_GRANTED);
162165
} else {
163166
//If permission not granted, go to page that says Nearby Places cannot be displayed
164167
hideProgressBar();
@@ -347,21 +350,33 @@ private void refreshView(LocationServiceManager.LocationChangeType locationChang
347350
}
348351
curLatLang = lastLocation;
349352

353+
if (locationChangeType.equals(LocationServiceManager.LocationChangeType.PERMISSION_JUST_GRANTED)) {
354+
curLatLang = lastKnownLocation;
355+
}
356+
350357
if (curLatLang == null) {
351358
Timber.d("Skipping update of nearby places as location is unavailable");
352359
return;
353360
}
354361

355-
if (locationChangeType
356-
.equals(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)) {
362+
if (locationChangeType.equals(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)
363+
|| locationChangeType.equals(LocationServiceManager.LocationChangeType.PERMISSION_JUST_GRANTED)) {
357364
progressBar.setVisibility(View.VISIBLE);
365+
366+
//TODO: This hack inserts curLatLng before populatePlaces is called (see #1440). Ideally a proper fix should be found
367+
Gson gson = new GsonBuilder()
368+
.registerTypeAdapter(Uri.class, new UriSerializer())
369+
.create();
370+
String gsonCurLatLng = gson.toJson(curLatLang);
371+
bundle.clear();
372+
bundle.putString("CurLatLng", gsonCurLatLng);
373+
358374
placesDisposable = Observable.fromCallable(() -> nearbyController
359375
.loadAttractionsFromLocation(curLatLang))
360376
.subscribeOn(Schedulers.io())
361377
.observeOn(AndroidSchedulers.mainThread())
362378
.subscribe(this::populatePlaces);
363-
} else if (locationChangeType
364-
.equals(LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED)) {
379+
} else if (locationChangeType.equals(LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED)) {
365380
Gson gson = new GsonBuilder()
366381
.registerTypeAdapter(Uri.class, new UriSerializer())
367382
.create();
@@ -384,21 +399,22 @@ private void populatePlaces(NearbyController.NearbyPlacesInfo nearbyPlacesInfo)
384399
if (placeList.size() == 0) {
385400
ViewUtil.showSnackbar(findViewById(R.id.container), R.string.no_nearby);
386401
}
387-
388-
bundle.clear();
402+
389403
bundle.putString("PlaceList", gsonPlaceList);
390-
bundle.putString("CurLatLng", gsonCurLatLng);
404+
//bundle.putString("CurLatLng", gsonCurLatLng);
391405
bundle.putString("BoundaryCoord", gsonBoundaryCoordinates);
392406

393407
// First time to init fragments
394408
if (nearbyMapFragment == null) {
409+
Timber.d("Init map fragment for the first time");
395410
lockNearbyView(true);
396411
setMapFragment();
397412
setListFragment();
398413
hideProgressBar();
399414
lockNearbyView(false);
400415
} else {
401416
// There are fragments, just update the map and list
417+
Timber.d("Map fragment already exists, just update the map and list");
402418
updateMapFragment(false);
403419
updateListFragment();
404420
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
8282
}
8383

8484
public void updateNearbyListSignificantly() {
85-
adapterFactory.updateAdapterData(getPlaceListFromBundle(bundleForUpdates),
86-
(RVRendererAdapter<Place>) recyclerView.getAdapter());
85+
try {
86+
adapterFactory.updateAdapterData(getPlaceListFromBundle(bundleForUpdates), (RVRendererAdapter<Place>) recyclerView.getAdapter());
87+
} catch (NullPointerException e) {
88+
Timber.e("Null pointer exception from calling recyclerView.getAdapter()");
89+
}
8790
}
8891

8992
private List<Place> getPlaceListFromBundle(Bundle bundle) {

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ public NearbyMapFragment() {
126126
@Override
127127
public void onCreate(Bundle savedInstanceState) {
128128
super.onCreate(savedInstanceState);
129+
Timber.d("Nearby map fragment created");
129130

130131
controller = new ContributionController(this);
131132
directUpload = new DirectUpload(this, controller);
@@ -151,17 +152,21 @@ public void onCreate(Bundle savedInstanceState) {
151152
getActivity());
152153
boundaryCoordinates = gson.fromJson(gsonBoundaryCoordinates, gsonBoundaryCoordinatesType);
153154
}
154-
Mapbox.getInstance(getActivity(),
155-
getString(R.string.mapbox_commons_app_token));
156-
MapboxTelemetry.getInstance().setTelemetryEnabled(false);
155+
if (curLatLng != null) {
156+
Mapbox.getInstance(getActivity(),
157+
getString(R.string.mapbox_commons_app_token));
158+
MapboxTelemetry.getInstance().setTelemetryEnabled(false);
159+
}
157160
setRetainInstance(true);
158161
}
159162

160163
@Override
161164
public View onCreateView(LayoutInflater inflater, ViewGroup container,
162165
Bundle savedInstanceState) {
163166

167+
Timber.d("onCreateView called");
164168
if (curLatLng != null) {
169+
Timber.d("curLatLng found, setting up map view...");
165170
setupMapView(savedInstanceState);
166171
}
167172

0 commit comments

Comments
 (0)