Skip to content

Commit 8971743

Browse files
maskaravivekneslihanturan
authored andcommitted
Fixes #2888: Use Dexter for requesting location permissions (#2925)
* Use dexter to ask for location permissions * Addressed code review comments
1 parent 6f9d69e commit 8971743

File tree

6 files changed

+93
-373
lines changed

6 files changed

+93
-373
lines changed

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java

+37-106
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,26 @@
55
import android.content.Context;
66
import android.content.Intent;
77
import android.content.ServiceConnection;
8-
import android.content.pm.PackageManager;
98
import android.database.Cursor;
109
import android.database.DataSetObserver;
11-
import android.os.Build;
1210
import android.os.Bundle;
1311
import android.os.IBinder;
12+
import android.view.LayoutInflater;
13+
import android.view.View;
14+
import android.view.ViewGroup;
15+
import android.widget.Adapter;
16+
import android.widget.CheckBox;
17+
import android.widget.Toast;
18+
1419
import androidx.annotation.NonNull;
1520
import androidx.annotation.Nullable;
21+
import androidx.cursoradapter.widget.CursorAdapter;
1622
import androidx.fragment.app.Fragment;
1723
import androidx.fragment.app.FragmentManager;
1824
import androidx.fragment.app.FragmentTransaction;
1925
import androidx.loader.app.LoaderManager;
2026
import androidx.loader.content.CursorLoader;
2127
import androidx.loader.content.Loader;
22-
import androidx.cursoradapter.widget.CursorAdapter;
23-
import androidx.appcompat.app.AlertDialog;
24-
import android.view.LayoutInflater;
25-
import android.view.View;
26-
import android.view.ViewGroup;
27-
import android.widget.Adapter;
28-
import android.widget.CheckBox;
29-
import android.widget.Toast;
3028

3129
import java.util.ArrayList;
3230

@@ -57,6 +55,7 @@
5755
import fr.free.nrw.commons.upload.UploadService;
5856
import fr.free.nrw.commons.utils.ConfigUtils;
5957
import fr.free.nrw.commons.utils.DialogUtil;
58+
import fr.free.nrw.commons.utils.PermissionUtils;
6059
import fr.free.nrw.commons.utils.ViewUtil;
6160
import io.reactivex.Observable;
6261
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -66,7 +65,7 @@
6665

6766
import static fr.free.nrw.commons.contributions.ContributionDao.Table.ALL_FIELDS;
6867
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI;
69-
import static fr.free.nrw.commons.location.LocationServiceManager.LOCATION_REQUEST;
68+
import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION;
7069
import static fr.free.nrw.commons.settings.Prefs.UPLOADS_SHOWING;
7170
import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween;
7271

@@ -351,35 +350,6 @@ public void onAuthCookieAcquired(Intent uploadServiceIntent) {
351350

352351
}
353352

354-
@Override
355-
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
356-
Timber.d("onRequestPermissionsResult");
357-
switch (requestCode) {
358-
case LOCATION_REQUEST: {
359-
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
360-
Timber.d("Location permission granted, refreshing view");
361-
// No need to display permission request button anymore
362-
locationManager.registerLocationManager();
363-
} else {
364-
if (store.getBoolean("displayLocationPermissionForCardView", true)) {
365-
// Still ask for permission
366-
DialogUtil.showAlertDialog(getActivity(),
367-
getString(R.string.nearby_card_permission_title),
368-
getString(R.string.nearby_card_permission_explanation),
369-
this::displayYouWontSeeNearbyMessage,
370-
this::enableLocationPermission,
371-
checkBoxView,
372-
false);
373-
}
374-
}
375-
}
376-
break;
377-
378-
default:
379-
// This is needed to allow the request codes from the Fragments to be routed appropriately
380-
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
381-
}
382-
}
383353
/**
384354
* Replace whatever is in the current contributionsFragmentContainer view with
385355
* mediaDetailPagerFragment, and preserve previous state in back stack.
@@ -496,7 +466,7 @@ public void onResume() {
496466

497467

498468
if (store.getBoolean("displayNearbyCardView", true)) {
499-
checkGPS();
469+
checkPermissionsAndShowNearbyCardView();
500470
if (nearbyNotificationCardView.cardViewVisibilityState == NearbyNotificationCardView.CardViewVisibilityState.READY) {
501471
nearbyNotificationCardView.setVisibility(View.VISIBLE);
502472
}
@@ -509,77 +479,39 @@ public void onResume() {
509479
fetchCampaigns();
510480
}
511481

512-
/**
513-
* Check GPS to decide displaying request permission button or not.
514-
*/
515-
private void checkGPS() {
516-
if (!locationManager.isProviderEnabled()) {
517-
Timber.d("GPS is not enabled");
518-
nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.ENABLE_GPS;
519-
if (store.getBoolean("displayLocationPermissionForCardView", true)) {
520-
DialogUtil.showAlertDialog(getActivity(),
521-
getString(R.string.nearby_card_permission_title),
522-
getString(R.string.nearby_card_permission_explanation),
523-
this::displayYouWontSeeNearbyMessage,
524-
this::enableGPS,
525-
checkBoxView,
526-
false);
527-
}
528-
} else {
529-
Timber.d("GPS is enabled");
530-
checkLocationPermission();
482+
private void checkPermissionsAndShowNearbyCardView() {
483+
if (PermissionUtils.hasPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
484+
onLocationPermissionGranted();
485+
} else if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
486+
&& store.getBoolean("displayLocationPermissionForCardView", true)
487+
&& (((MainActivity) getActivity()).viewPager.getCurrentItem() == CONTRIBUTIONS_TAB_POSITION)) {
488+
nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.ENABLE_LOCATION_PERMISSION;
489+
showNearbyCardPermissionRationale();
531490
}
532491
}
533492

534-
private void checkLocationPermission() {
535-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
536-
if (locationManager.isLocationPermissionGranted(requireContext())) {
537-
nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.NO_PERMISSION_NEEDED;
538-
locationManager.registerLocationManager();
539-
} else {
540-
nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.ENABLE_LOCATION_PERMISSION;
541-
// If user didn't selected Don't ask again
542-
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
543-
&& store.getBoolean("displayLocationPermissionForCardView", true)) {
544-
DialogUtil.showAlertDialog(getActivity(),
545-
getString(R.string.nearby_card_permission_title),
546-
getString(R.string.nearby_card_permission_explanation),
547-
this::displayYouWontSeeNearbyMessage,
548-
this::enableLocationPermission,
549-
checkBoxView,
550-
false);
551-
}
552-
}
553-
} else {
554-
// If device is under Marshmallow, we already checked for GPS
555-
nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.NO_PERMISSION_NEEDED;
556-
locationManager.registerLocationManager();
557-
}
493+
private void requestLocationPermission() {
494+
PermissionUtils.checkPermissionsAndPerformAction(getActivity(),
495+
Manifest.permission.ACCESS_FINE_LOCATION,
496+
this::onLocationPermissionGranted,
497+
this::displayYouWontSeeNearbyMessage,
498+
-1,
499+
-1);
558500
}
559501

560-
private void enableLocationPermission() {
561-
if (!getActivity().isFinishing()) {
562-
((MainActivity) getActivity()).locationManager.requestPermissions(getActivity());
563-
}
502+
private void onLocationPermissionGranted() {
503+
nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.NO_PERMISSION_NEEDED;
504+
locationManager.registerLocationManager();
564505
}
565506

566-
private void enableGPS() {
567-
new AlertDialog.Builder(getActivity())
568-
.setMessage(R.string.gps_disabled)
569-
.setCancelable(false)
570-
.setPositiveButton(R.string.enable_gps,
571-
(dialog, id) -> {
572-
Intent callGPSSettingIntent = new Intent(
573-
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
574-
Timber.d("Loaded settings page");
575-
((MainActivity) getActivity()).startActivityForResult(callGPSSettingIntent, 1);
576-
})
577-
.setNegativeButton(R.string.menu_cancel_upload, (dialog, id) -> {
578-
dialog.cancel();
579-
displayYouWontSeeNearbyMessage();
580-
})
581-
.create()
582-
.show();
507+
private void showNearbyCardPermissionRationale() {
508+
DialogUtil.showAlertDialog(getActivity(),
509+
getString(R.string.nearby_card_permission_title),
510+
getString(R.string.nearby_card_permission_explanation),
511+
this::displayYouWontSeeNearbyMessage,
512+
this::requestLocationPermission,
513+
checkBoxView,
514+
false);
583515
}
584516

585517
private void displayYouWontSeeNearbyMessage() {
@@ -589,7 +521,6 @@ private void displayYouWontSeeNearbyMessage() {
589521

590522
private void updateClosestNearbyCardViewInfo() {
591523
curLatLng = locationManager.getLastLocation();
592-
593524
compositeDisposable.add(Observable.fromCallable(() -> nearbyController
594525
.loadAttractionsFromLocation(curLatLng, curLatLng, true, false)) // thanks to boolean, it will only return closest result
595526
.subscribeOn(Schedulers.io())

app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java

+2-39
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import timber.log.Timber;
4646

4747
import static android.content.ContentResolver.requestSync;
48-
import static fr.free.nrw.commons.location.LocationServiceManager.LOCATION_REQUEST;
4948

5049
public class MainActivity extends AuthenticatedActivity implements FragmentManager.OnBackStackChangedListener {
5150

@@ -68,8 +67,8 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
6867
public boolean isAuthCookieAcquired = false;
6968

7069
public ContributionsActivityPagerAdapter contributionsActivityPagerAdapter;
71-
public final int CONTRIBUTIONS_TAB_POSITION = 0;
72-
public final int NEARBY_TAB_POSITION = 1;
70+
public static final int CONTRIBUTIONS_TAB_POSITION = 0;
71+
public static final int NEARBY_TAB_POSITION = 1;
7372

7473
public boolean isContributionsFragmentVisible = true; // False means nearby fragment is visible
7574
private Menu menu;
@@ -361,12 +360,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
361360
}
362361
}
363362

364-
private boolean deviceHasCamera() {
365-
PackageManager pm = getPackageManager();
366-
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) ||
367-
pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
368-
}
369-
370363
public class ContributionsActivityPagerAdapter extends FragmentPagerAdapter {
371364
FragmentManager fragmentManager;
372365
private boolean isContributionsListFragment = true; // to know what to put in first tab, Contributions of Media Details
@@ -450,15 +443,6 @@ public String makeFragmentName(int viewId, int index) {
450443
return "android:switcher:" + viewId + ":" + index;
451444
}
452445

453-
/**
454-
* In first tab we can have ContributionsFragment or Media details fragment. This method
455-
* is responsible to update related boolean
456-
* @param isContributionsListFragment true when contribution fragment should be visible, false
457-
* means user clicked to MediaDetails
458-
*/
459-
private void updateContributionFragmentTabContent(boolean isContributionsListFragment) {
460-
this.isContributionsListFragment = isContributionsListFragment;
461-
}
462446
}
463447

464448
@Override
@@ -468,27 +452,6 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
468452
controller.handleActivityResult(this, requestCode, resultCode, data);
469453
}
470454

471-
@Override
472-
public void onRequestPermissionsResult(int requestCode,
473-
String[] permissions, int[] grantResults) {
474-
if (requestCode == LOCATION_REQUEST) {
475-
// If request is cancelled, the result arrays are empty.
476-
if (grantResults.length > 0
477-
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
478-
Timber.d("Location permission given");
479-
((ContributionsFragment)contributionsActivityPagerAdapter
480-
.getItem(0)).locationManager.registerLocationManager();
481-
} else {
482-
// If nearby fragment is visible and location permission is not given, send user back to contrib fragment
483-
if (!isContributionsFragmentVisible) {
484-
viewPager.setCurrentItem(CONTRIBUTIONS_TAB_POSITION);
485-
486-
// TODO: If contrib fragment is visible and location permission is not given, display permission request button
487-
}
488-
}
489-
}
490-
}
491-
492455
@Override
493456
protected void onResume() {
494457
super.onResume();

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

-79
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
package fr.free.nrw.commons.location;
22

3-
import android.Manifest;
4-
import android.annotation.SuppressLint;
53
import android.app.Activity;
64
import android.content.Context;
7-
import android.content.pm.PackageManager;
85
import android.location.Location;
96
import android.location.LocationListener;
107
import android.location.LocationManager;
118
import android.os.Bundle;
129

13-
import androidx.annotation.NonNull;
14-
import androidx.core.app.ActivityCompat;
15-
import androidx.core.content.ContextCompat;
16-
1710
import java.util.HashSet;
1811
import java.util.List;
1912
import java.util.Set;
@@ -44,78 +37,6 @@ public LocationServiceManager(Context context) {
4437
this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
4538
}
4639

47-
/**
48-
* Returns the current status of the location provider.
49-
*
50-
* @return true if the location provider is enabled
51-
*/
52-
public boolean isProviderEnabled() {
53-
return (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER));
54-
}
55-
56-
/**
57-
* Returns whether the location permission is granted.
58-
* @return true if the location permission is granted
59-
*/
60-
public boolean isLocationPermissionGranted(@NonNull Context context) {
61-
return ContextCompat.checkSelfPermission(context,
62-
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
63-
}
64-
65-
/**
66-
* Requests the location permission to be granted.
67-
*
68-
* @param activity the activity
69-
*/
70-
public void requestPermissions(Activity activity) {
71-
if (activity.isFinishing()) {
72-
return;
73-
}
74-
ActivityCompat.requestPermissions(activity,
75-
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
76-
LOCATION_REQUEST);
77-
}
78-
79-
/**
80-
* The permission explanation dialog box is now displayed just once for a particular activity. We are subscribing
81-
* to updates from multiple providers so its important to show the dialog just once. Otherwise it will be displayed
82-
* once for every provider, which in our case currently is 2.
83-
* @param activity
84-
* @return
85-
*/
86-
public boolean isPermissionExplanationRequired(Activity activity) {
87-
if (activity.isFinishing()) {
88-
return false;
89-
}
90-
boolean showRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION);
91-
if (showRequestPermissionRationale && !locationExplanationDisplayed.contains(activity)) {
92-
locationExplanationDisplayed.add(activity);
93-
return true;
94-
}
95-
return false;
96-
}
97-
98-
/**
99-
* Gets the last known location in cases where there wasn't time to register a listener
100-
* (e.g. when Location permission just granted)
101-
* @return last known LatLng
102-
*/
103-
@SuppressLint("MissingPermission")
104-
public LatLng getLKL(@NonNull Context context) {
105-
if (isLocationPermissionGranted(context)) {
106-
Location lastKL = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
107-
if (lastKL == null) {
108-
lastKL = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
109-
}
110-
if (lastKL == null) {
111-
return null;
112-
}
113-
return LatLng.from(lastKL);
114-
} else {
115-
return null;
116-
}
117-
}
118-
11940
public LatLng getLastLocation() {
12041
if (lastLocation == null) {
12142
return null;

0 commit comments

Comments
 (0)