diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java
index 6f95581b5..4d68500ca 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java
@@ -5,22 +5,10 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.DataSetObserver;
-import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentTransaction;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.CursorLoader;
-import androidx.loader.content.Loader;
-import androidx.cursoradapter.widget.CursorAdapter;
-import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -28,6 +16,16 @@ import android.widget.Adapter;
import android.widget.CheckBox;
import android.widget.Toast;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.cursoradapter.widget.CursorAdapter;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.CursorLoader;
+import androidx.loader.content.Loader;
+
import java.util.ArrayList;
import javax.inject.Inject;
@@ -57,6 +55,7 @@ import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.upload.UploadService;
import fr.free.nrw.commons.utils.ConfigUtils;
import fr.free.nrw.commons.utils.DialogUtil;
+import fr.free.nrw.commons.utils.PermissionUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -66,7 +65,7 @@ import timber.log.Timber;
import static fr.free.nrw.commons.contributions.ContributionDao.Table.ALL_FIELDS;
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI;
-import static fr.free.nrw.commons.location.LocationServiceManager.LOCATION_REQUEST;
+import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION;
import static fr.free.nrw.commons.settings.Prefs.UPLOADS_SHOWING;
import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween;
@@ -351,35 +350,6 @@ public class ContributionsFragment
}
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- Timber.d("onRequestPermissionsResult");
- switch (requestCode) {
- case LOCATION_REQUEST: {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- Timber.d("Location permission granted, refreshing view");
- // No need to display permission request button anymore
- locationManager.registerLocationManager();
- } else {
- if (store.getBoolean("displayLocationPermissionForCardView", true)) {
- // Still ask for permission
- DialogUtil.showAlertDialog(getActivity(),
- getString(R.string.nearby_card_permission_title),
- getString(R.string.nearby_card_permission_explanation),
- this::displayYouWontSeeNearbyMessage,
- this::enableLocationPermission,
- checkBoxView,
- false);
- }
- }
- }
- break;
-
- default:
- // This is needed to allow the request codes from the Fragments to be routed appropriately
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- }
- }
/**
* Replace whatever is in the current contributionsFragmentContainer view with
* mediaDetailPagerFragment, and preserve previous state in back stack.
@@ -496,7 +466,7 @@ public class ContributionsFragment
if (store.getBoolean("displayNearbyCardView", true)) {
- checkGPS();
+ checkPermissionsAndShowNearbyCardView();
if (nearbyNotificationCardView.cardViewVisibilityState == NearbyNotificationCardView.CardViewVisibilityState.READY) {
nearbyNotificationCardView.setVisibility(View.VISIBLE);
}
@@ -509,77 +479,39 @@ public class ContributionsFragment
fetchCampaigns();
}
- /**
- * Check GPS to decide displaying request permission button or not.
- */
- private void checkGPS() {
- if (!locationManager.isProviderEnabled()) {
- Timber.d("GPS is not enabled");
- nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.ENABLE_GPS;
- if (store.getBoolean("displayLocationPermissionForCardView", true)) {
- DialogUtil.showAlertDialog(getActivity(),
- getString(R.string.nearby_card_permission_title),
- getString(R.string.nearby_card_permission_explanation),
- this::displayYouWontSeeNearbyMessage,
- this::enableGPS,
- checkBoxView,
- false);
- }
- } else {
- Timber.d("GPS is enabled");
- checkLocationPermission();
+ private void checkPermissionsAndShowNearbyCardView() {
+ if (PermissionUtils.hasPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
+ onLocationPermissionGranted();
+ } else if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
+ && store.getBoolean("displayLocationPermissionForCardView", true)
+ && (((MainActivity) getActivity()).viewPager.getCurrentItem() == CONTRIBUTIONS_TAB_POSITION)) {
+ nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.ENABLE_LOCATION_PERMISSION;
+ showNearbyCardPermissionRationale();
}
}
- private void checkLocationPermission() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (locationManager.isLocationPermissionGranted(requireContext())) {
- nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.NO_PERMISSION_NEEDED;
- locationManager.registerLocationManager();
- } else {
- nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.ENABLE_LOCATION_PERMISSION;
- // If user didn't selected Don't ask again
- if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
- && store.getBoolean("displayLocationPermissionForCardView", true)) {
- DialogUtil.showAlertDialog(getActivity(),
- getString(R.string.nearby_card_permission_title),
- getString(R.string.nearby_card_permission_explanation),
- this::displayYouWontSeeNearbyMessage,
- this::enableLocationPermission,
- checkBoxView,
- false);
- }
- }
- } else {
- // If device is under Marshmallow, we already checked for GPS
- nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.NO_PERMISSION_NEEDED;
- locationManager.registerLocationManager();
- }
+ private void requestLocationPermission() {
+ PermissionUtils.checkPermissionsAndPerformAction(getActivity(),
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ this::onLocationPermissionGranted,
+ this::displayYouWontSeeNearbyMessage,
+ -1,
+ -1);
}
- private void enableLocationPermission() {
- if (!getActivity().isFinishing()) {
- ((MainActivity) getActivity()).locationManager.requestPermissions(getActivity());
- }
+ private void onLocationPermissionGranted() {
+ nearbyNotificationCardView.permissionType = NearbyNotificationCardView.PermissionType.NO_PERMISSION_NEEDED;
+ locationManager.registerLocationManager();
}
- private void enableGPS() {
- new AlertDialog.Builder(getActivity())
- .setMessage(R.string.gps_disabled)
- .setCancelable(false)
- .setPositiveButton(R.string.enable_gps,
- (dialog, id) -> {
- Intent callGPSSettingIntent = new Intent(
- android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
- Timber.d("Loaded settings page");
- ((MainActivity) getActivity()).startActivityForResult(callGPSSettingIntent, 1);
- })
- .setNegativeButton(R.string.menu_cancel_upload, (dialog, id) -> {
- dialog.cancel();
- displayYouWontSeeNearbyMessage();
- })
- .create()
- .show();
+ private void showNearbyCardPermissionRationale() {
+ DialogUtil.showAlertDialog(getActivity(),
+ getString(R.string.nearby_card_permission_title),
+ getString(R.string.nearby_card_permission_explanation),
+ this::displayYouWontSeeNearbyMessage,
+ this::requestLocationPermission,
+ checkBoxView,
+ false);
}
private void displayYouWontSeeNearbyMessage() {
@@ -589,7 +521,6 @@ public class ContributionsFragment
private void updateClosestNearbyCardViewInfo() {
curLatLng = locationManager.getLastLocation();
-
compositeDisposable.add(Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curLatLng, curLatLng, true, false)) // thanks to boolean, it will only return closest result
.subscribeOn(Schedulers.io())
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java b/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java
index e7312edb8..698057935 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java
@@ -45,7 +45,6 @@ import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;
import static android.content.ContentResolver.requestSync;
-import static fr.free.nrw.commons.location.LocationServiceManager.LOCATION_REQUEST;
public class MainActivity extends AuthenticatedActivity implements FragmentManager.OnBackStackChangedListener {
@@ -68,8 +67,8 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
public boolean isAuthCookieAcquired = false;
public ContributionsActivityPagerAdapter contributionsActivityPagerAdapter;
- public final int CONTRIBUTIONS_TAB_POSITION = 0;
- public final int NEARBY_TAB_POSITION = 1;
+ public static final int CONTRIBUTIONS_TAB_POSITION = 0;
+ public static final int NEARBY_TAB_POSITION = 1;
public boolean isContributionsFragmentVisible = true; // False means nearby fragment is visible
private Menu menu;
@@ -361,12 +360,6 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
}
}
- private boolean deviceHasCamera() {
- PackageManager pm = getPackageManager();
- return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) ||
- pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
- }
-
public class ContributionsActivityPagerAdapter extends FragmentPagerAdapter {
FragmentManager fragmentManager;
private boolean isContributionsListFragment = true; // to know what to put in first tab, Contributions of Media Details
@@ -450,15 +443,6 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
return "android:switcher:" + viewId + ":" + index;
}
- /**
- * In first tab we can have ContributionsFragment or Media details fragment. This method
- * is responsible to update related boolean
- * @param isContributionsListFragment true when contribution fragment should be visible, false
- * means user clicked to MediaDetails
- */
- private void updateContributionFragmentTabContent(boolean isContributionsListFragment) {
- this.isContributionsListFragment = isContributionsListFragment;
- }
}
@Override
@@ -468,27 +452,6 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
controller.handleActivityResult(this, requestCode, resultCode, data);
}
- @Override
- public void onRequestPermissionsResult(int requestCode,
- String[] permissions, int[] grantResults) {
- if (requestCode == LOCATION_REQUEST) {
- // If request is cancelled, the result arrays are empty.
- if (grantResults.length > 0
- && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- Timber.d("Location permission given");
- ((ContributionsFragment)contributionsActivityPagerAdapter
- .getItem(0)).locationManager.registerLocationManager();
- } else {
- // If nearby fragment is visible and location permission is not given, send user back to contrib fragment
- if (!isContributionsFragmentVisible) {
- viewPager.setCurrentItem(CONTRIBUTIONS_TAB_POSITION);
-
- // TODO: If contrib fragment is visible and location permission is not given, display permission request button
- }
- }
- }
- }
-
@Override
protected void onResume() {
super.onResume();
diff --git a/app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java b/app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java
index 68b7c742d..8e6705ecb 100644
--- a/app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java
+++ b/app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java
@@ -1,19 +1,12 @@
package fr.free.nrw.commons.location;
-import android.Manifest;
-import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
-
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -44,78 +37,6 @@ public class LocationServiceManager implements LocationListener {
this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
}
- /**
- * Returns the current status of the location provider.
- *
- * @return true if the location provider is enabled
- */
- public boolean isProviderEnabled() {
- return (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER));
- }
-
- /**
- * Returns whether the location permission is granted.
- * @return true if the location permission is granted
- */
- public boolean isLocationPermissionGranted(@NonNull Context context) {
- return ContextCompat.checkSelfPermission(context,
- Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
- }
-
- /**
- * Requests the location permission to be granted.
- *
- * @param activity the activity
- */
- public void requestPermissions(Activity activity) {
- if (activity.isFinishing()) {
- return;
- }
- ActivityCompat.requestPermissions(activity,
- new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
- LOCATION_REQUEST);
- }
-
- /**
- * The permission explanation dialog box is now displayed just once for a particular activity. We are subscribing
- * to updates from multiple providers so its important to show the dialog just once. Otherwise it will be displayed
- * once for every provider, which in our case currently is 2.
- * @param activity
- * @return
- */
- public boolean isPermissionExplanationRequired(Activity activity) {
- if (activity.isFinishing()) {
- return false;
- }
- boolean showRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION);
- if (showRequestPermissionRationale && !locationExplanationDisplayed.contains(activity)) {
- locationExplanationDisplayed.add(activity);
- return true;
- }
- return false;
- }
-
- /**
- * Gets the last known location in cases where there wasn't time to register a listener
- * (e.g. when Location permission just granted)
- * @return last known LatLng
- */
- @SuppressLint("MissingPermission")
- public LatLng getLKL(@NonNull Context context) {
- if (isLocationPermissionGranted(context)) {
- Location lastKL = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
- if (lastKL == null) {
- lastKL = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
- }
- if (lastKL == null) {
- return null;
- }
- return LatLng.from(lastKL);
- } else {
- return null;
- }
- }
-
public LatLng getLastLocation() {
if (lastLocation == null) {
return null;
diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java
index 100ca733b..062f7da90 100644
--- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java
@@ -1,20 +1,11 @@
package fr.free.nrw.commons.nearby;
+import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.os.Build;
import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.constraintlayout.widget.ConstraintLayout;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
-import com.google.android.material.snackbar.Snackbar;
-
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentTransaction;
-import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -22,12 +13,19 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.snackbar.Snackbar;
import com.google.gson.Gson;
import java.util.List;
import javax.inject.Inject;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
@@ -38,6 +36,7 @@ import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.location.LocationUpdateListener;
import fr.free.nrw.commons.utils.FragmentUtils;
import fr.free.nrw.commons.utils.NetworkUtils;
+import fr.free.nrw.commons.utils.PermissionUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import fr.free.nrw.commons.wikidata.WikidataEditListener;
import io.reactivex.Observable;
@@ -45,6 +44,8 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;
+import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION;
+import static fr.free.nrw.commons.contributions.MainActivity.NEARBY_TAB_POSITION;
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED;
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED;
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.MAP_UPDATED;
@@ -193,8 +194,8 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
- public void onStateChanged(View bottomSheet, int newState) {
- prepareViewsForSheetPosition(newState);
+ public void onStateChanged(View bottomSheet, int unusedNewState) {
+ prepareViewsForSheetPosition();
}
@Override
@@ -210,9 +211,8 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
/**
* Sets camera position, zoom level according to sheet positions
- * @param bottomSheetState expanded, collapsed or hidden
*/
- public void prepareViewsForSheetPosition(int bottomSheetState) {
+ private void prepareViewsForSheetPosition() {
// TODO
}
@@ -246,7 +246,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
*
* @param locationChangeType defines if location changed significantly or slightly
*/
- public void refreshView(LocationServiceManager.LocationChangeType locationChangeType) {
+ private void refreshView(LocationServiceManager.LocationChangeType locationChangeType) {
Timber.d("Refreshing nearby places");
if (lockNearbyView) {
return;
@@ -324,7 +324,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
* button. It populates places for custom location.
* @param customLatLng Custom area which we will search around
*/
- public void refreshViewForCustomLocation(LatLng customLatLng, boolean refreshForCurrentLocation) {
+ void refreshViewForCustomLocation(LatLng customLatLng, boolean refreshForCurrentLocation) {
if (customLatLng == null) {
// If null, return
return;
@@ -568,130 +568,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
* This method first checks if the location permissions has been granted and then register the location manager for updates.
*/
private void registerLocationUpdates() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (locationManager.isLocationPermissionGranted(requireContext())) {
- locationManager.registerLocationManager();
- } else {
- // Should we show an explanation?
- if (locationManager.isPermissionExplanationRequired(getActivity())) {
- new AlertDialog.Builder(getActivity())
- .setMessage(getString(R.string.location_permission_rationale_nearby))
- .setPositiveButton(android.R.string.ok, (dialog, which) -> {
- requestLocationPermissions();
- dialog.dismiss();
- })
- .setNegativeButton(android.R.string.cancel, (dialog, id) -> {
- showLocationPermissionDeniedErrorDialog();
- dialog.cancel();
- })
- .create()
- .show();
-
- } else {
- // No explanation needed, we can request the permission.
- requestLocationPermissions();
- }
- }
- } else {
- locationManager.registerLocationManager();
- }
- }
-
- /**
- * Requests location permission if activity is not null
- */
- private void requestLocationPermissions() {
- if (!getActivity().isFinishing()) {
- locationManager.requestPermissions(getActivity());
- }
- }
-
- /**
- * Will warn user if location is denied
- */
- private void showLocationPermissionDeniedErrorDialog() {
- new AlertDialog.Builder(getActivity())
- .setMessage(R.string.nearby_needs_permissions)
- .setCancelable(false)
- .setPositiveButton(R.string.give_permission, (dialog, which) -> {
- //will ask for the location permission again
- checkGps();
- })
- .setNegativeButton(R.string.cancel, (dialog, which) -> {
- //dismiss dialog and send user to contributions tab instead
- dialog.cancel();
- ((MainActivity)getActivity()).viewPager.setCurrentItem(((MainActivity)getActivity()).CONTRIBUTIONS_TAB_POSITION);
- })
- .create()
- .show();
- }
-
- /**
- * Checks device GPS permission first for all API levels
- */
- private void checkGps() {
- Timber.d("checking GPS");
- if (!locationManager.isProviderEnabled()) {
- Timber.d("GPS is not enabled");
- new AlertDialog.Builder(getActivity())
- .setMessage(R.string.gps_disabled)
- .setCancelable(false)
- .setPositiveButton(R.string.enable_gps,
- (dialog, id) -> {
- Intent callGPSSettingIntent = new Intent(
- android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
- Timber.d("Loaded settings page");
- startActivityForResult(callGPSSettingIntent, 1);
- })
- .setNegativeButton(R.string.menu_cancel_upload, (dialog, id) -> {
- showLocationPermissionDeniedErrorDialog();
- dialog.cancel();
- })
- .create()
- .show();
- } else {
- Timber.d("GPS is enabled");
- checkLocationPermission();
- }
- }
-
- /**
- * This method ideally should be called from inside of CheckGPS method. If device GPS is enabled
- * then we need to control app specific permissions for >=M devices. For other devices, enabled
- * GPS is enough for nearby, so directly call refresh view.
- */
- private void checkLocationPermission() {
- Timber.d("Checking location permission");
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (locationManager.isLocationPermissionGranted(requireContext())) {
- refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
- } else {
- // Should we show an explanation?
- if (locationManager.isPermissionExplanationRequired(getActivity())) {
- // Show an explanation to the user *asynchronously* -- don't block
- // this thread waiting for the user's response! After the user
- // sees the explanation, try again to request the permission.
- new AlertDialog.Builder(getActivity())
- .setMessage(getString(R.string.location_permission_rationale_nearby))
- .setPositiveButton(android.R.string.ok, (dialog, which) -> {
- requestLocationPermissions();
- dialog.dismiss();
- })
- .setNegativeButton(android.R.string.cancel, (dialog, id) -> {
- showLocationPermissionDeniedErrorDialog();
- dialog.cancel();
- })
- .create()
- .show();
-
- } else {
- // No explanation needed, we can request the permission.
- requestLocationPermissions();
- }
- }
- } else {
- refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
- }
+ locationManager.registerLocationManager();
}
private void showErrorMessage(String message) {
@@ -748,8 +625,12 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
public void onResume() {
super.onResume();
// Resume the fragment if exist
- resumeFragment();
+ if (((MainActivity) getActivity()).viewPager.getCurrentItem() == NEARBY_TAB_POSITION) {
+ checkPermissionsAndPerformAction(this::resumeFragment);
+ } else {
+ resumeFragment();
}
+ }
/**
* Perform nearby operations on nearby tab selected
@@ -758,8 +639,16 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
public void onTabSelected(boolean onOrientationChanged) {
Timber.d("On nearby tab selected");
this.onOrientationChanged = onOrientationChanged;
- performNearbyOperations();
+ checkPermissionsAndPerformAction(this::performNearbyOperations);
+ }
+ private void checkPermissionsAndPerformAction(Runnable runnable) {
+ PermissionUtils.checkPermissionsAndPerformAction(getActivity(),
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ runnable,
+ () -> ((MainActivity) getActivity()).viewPager.setCurrentItem(CONTRIBUTIONS_TAB_POSITION),
+ R.string.location_permission_title,
+ R.string.location_permission_rationale_nearby);
}
/**
@@ -769,8 +658,8 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
locationManager.addLocationListener(this);
registerLocationUpdates();
lockNearbyView = false;
- checkGps();
addNetworkBroadcastReceiver();
+ refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
}
@Override
diff --git a/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java
index c4268790c..8d258256a 100644
--- a/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java
+++ b/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java
@@ -5,17 +5,17 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.Settings;
-import androidx.annotation.StringRes;
-import androidx.core.content.ContextCompat;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
+
import com.karumi.dexter.Dexter;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionDeniedResponse;
import com.karumi.dexter.listener.PermissionGrantedResponse;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.single.BasePermissionListener;
+
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R;
@@ -27,7 +27,7 @@ public class PermissionUtils {
It open the app settings from where the user can manually give us the required permission.
* @param activity
*/
- public static void askUserToManuallyEnablePermissionFromSettings(Activity activity) {
+ private static void askUserToManuallyEnablePermissionFromSettings(Activity activity) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
@@ -50,6 +50,9 @@ public class PermissionUtils {
* Checks for a particular permission and runs the runnable to perform an action when the permission is granted
* Also, it shows a rationale if needed
*
+ * rationaleTitle and rationaleMessage can be invalid @StringRes. If the value is -1 then no permission rationale
+ * will be displayed and permission would be requested
+ *
* Sample usage:
*
* PermissionUtils.checkPermissionsAndPerformAction(activity,
@@ -58,12 +61,20 @@ public class PermissionUtils {
* R.string.storage_permission_title,
* R.string.write_storage_permission_rationale);
*
+ * If you don't want the permission rationale to be shown then use:
+ *
+ * PermissionUtils.checkPermissionsAndPerformAction(activity,
+ * Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ * () -> initiateCameraUpload(activity),
+ * - 1, -1);
+ *
+ *
*
* @param activity activity requesting permissions
* @param permission the permission being requests
* @param onPermissionGranted the runnable to be executed when the permission is granted
- * @param rationaleTitle rationale title to be displayed when permission was denied
- * @param rationaleMessage rationale message to be displayed when permission was denied
+ * @param rationaleTitle rationale title to be displayed when permission was denied. It can be an invalid @StringRes
+ * @param rationaleMessage rationale message to be displayed when permission was denied. It can be an invalid @StringRes
*/
public static void checkPermissionsAndPerformAction(Activity activity, String permission,
Runnable onPermissionGranted, @StringRes int rationaleTitle,
@@ -93,7 +104,6 @@ public class PermissionUtils {
* @param rationaleTitle rationale title to be displayed when permission was denied
* @param rationaleMessage rationale message to be displayed when permission was denied
*/
-
public static void checkPermissionsAndPerformAction(Activity activity, String permission,
Runnable onPermissionGranted, Runnable onPermissionDenied, @StringRes int rationaleTitle,
@StringRes int rationaleMessage) {
@@ -120,6 +130,10 @@ public class PermissionUtils {
@Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission,
PermissionToken token) {
+ if (rationaleTitle == -1 && rationaleMessage == -1) {
+ token.continuePermissionRequest();
+ return;
+ }
DialogUtil.showAlertDialog(activity, activity.getString(rationaleTitle),
activity.getString(rationaleMessage),
activity.getString(android.R.string.ok),
@@ -129,4 +143,5 @@ public class PermissionUtils {
})
.check();
}
+
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 276f9e2c1..b460f358e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -166,6 +166,7 @@
Requesting Storage Permission
Required permission: Read external storage. App cannot access your gallery without this.
Required permission: Write external storage. App cannot access your camera/gallery without this.
+ Requesting Location Permission
Optional permission: Get current location for category suggestions
OK
Nearby Places