mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
* Resolved merged conflicts * Resolved merge conflicts and updated workflow * Updated Location Flow and merged conflicts * Update flow and merge conflicts * Fixed LocationPicker's location flow * Removed redundant code from LocationPermissionsHelper * Fixed Explore fragment crashing and incorrect behaviour * Updated LocationPicker Flow * Fixed Nearby not working as intended * Final update to location flow of all maps * Added the reqested changes and fixed bugs * Resolved requested change in in-app camera location flow * Fixed In-app camera location flow * Resolved conflicts in ContributionsListFragment * Updated java doc as requested * Resolved nearby card dialog not being shown * Optimised LocationPermissionsHelper javadoc * Made requested changes for preference check * Added javadoc and requested comment for later reference * Implemented requested code changes * Fixed failing test due to changes made during PR * Added string resource for ExploreMapFragment * Changed string resource for rationale dialog * Added standard location flow information in LocationPermissionsHelper * Added javadoc for doNotAskForLocationPermission * Removed unused import * Updated javadoc * Removed values-yue-hant * Fix some merge conflict errors * Fix minor errors due to mergre conflicts * Fix some refactor errors * Fixed minor bug due to merging conflicts * Delete app/src/main/res/values-yue-hant directory * Final changes to NearbyParentFragment * Fixes #5686 map coordinates set to image coords * Removed some redundant code from recenterMap * Removed one test whose method no longer exists * Removed unused method from contract of nearby * Removed redundant method from NearbyParentFragment * nearby: add a FIXME about the possibly redudant code --------- Co-authored-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
This commit is contained in:
parent
1f2e31d45b
commit
04f9ef4819
16 changed files with 421 additions and 297 deletions
|
|
@ -4,12 +4,14 @@ import static fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.
|
|||
import static fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.LAST_ZOOM;
|
||||
import static fr.free.nrw.commons.utils.MapUtils.ZOOM_LEVEL;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
|
|
@ -21,12 +23,14 @@ import android.view.animation.OvershootInterpolator;
|
|||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import fr.free.nrw.commons.CameraPosition;
|
||||
|
|
@ -39,9 +43,9 @@ import fr.free.nrw.commons.auth.csrf.CsrfTokenClient;
|
|||
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
|
||||
import fr.free.nrw.commons.coordinates.CoordinateEditHelper;
|
||||
import fr.free.nrw.commons.filepicker.Constants;
|
||||
import fr.free.nrw.commons.kvstore.BasicKvStore;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper.Dialog;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper.LocationPermissionCallback;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.theme.BaseActivity;
|
||||
|
|
@ -135,6 +139,7 @@ public class LocationPickerActivity extends BaseActivity implements
|
|||
@Named("default_preferences")
|
||||
public
|
||||
JsonKvStore applicationKvStore;
|
||||
BasicKvStore store;
|
||||
/**
|
||||
* isDarkTheme: for keeping a track of the device theme and modifying the map theme accordingly
|
||||
*/
|
||||
|
|
@ -145,6 +150,8 @@ public class LocationPickerActivity extends BaseActivity implements
|
|||
|
||||
@Inject
|
||||
LocationServiceManager locationManager;
|
||||
LocationPermissionsHelper locationPermissionsHelper;
|
||||
|
||||
@Inject
|
||||
SessionManager sessionManager;
|
||||
|
||||
|
|
@ -163,6 +170,7 @@ public class LocationPickerActivity extends BaseActivity implements
|
|||
|
||||
isDarkTheme = systemThemeUtils.isDeviceInNightMode();
|
||||
moveToCurrentLocation = false;
|
||||
store = new BasicKvStore(this, "LocationPermissions");
|
||||
|
||||
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
|
|
@ -482,19 +490,10 @@ public class LocationPickerActivity extends BaseActivity implements
|
|||
* Center the map at user's current location
|
||||
*/
|
||||
private void requestLocationPermissions() {
|
||||
LocationPermissionsHelper.Dialog locationAccessDialog = new Dialog(
|
||||
R.string.location_permission_title,
|
||||
R.string.upload_map_location_access
|
||||
);
|
||||
|
||||
LocationPermissionsHelper.Dialog locationOffDialog = new Dialog(
|
||||
R.string.ask_to_turn_location_on,
|
||||
R.string.upload_map_location_access
|
||||
);
|
||||
LocationPermissionsHelper locationPermissionsHelper = new LocationPermissionsHelper(
|
||||
locationPermissionsHelper = new LocationPermissionsHelper(
|
||||
this, locationManager, this);
|
||||
locationPermissionsHelper.handleLocationPermissions(locationAccessDialog,
|
||||
locationOffDialog);
|
||||
locationPermissionsHelper.requestForLocationAccess(R.string.location_permission_title,
|
||||
R.string.upload_map_location_access);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -505,7 +504,7 @@ public class LocationPickerActivity extends BaseActivity implements
|
|||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
onLocationPermissionGranted();
|
||||
} else {
|
||||
onLocationPermissionDenied("");
|
||||
onLocationPermissionDenied(getString(R.string.upload_map_location_access));
|
||||
}
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
|
@ -524,21 +523,50 @@ public class LocationPickerActivity extends BaseActivity implements
|
|||
|
||||
@Override
|
||||
public void onLocationPermissionDenied(String toastMessage) {
|
||||
//do nothing
|
||||
if (!ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
permission.ACCESS_FINE_LOCATION)) {
|
||||
if (!locationPermissionsHelper.checkLocationPermission(this)) {
|
||||
if (store.getBoolean("isPermissionDenied", false)) {
|
||||
// means user has denied location permission twice or checked the "Don't show again"
|
||||
locationPermissionsHelper.showAppSettingsDialog(this,
|
||||
R.string.upload_map_location_access);
|
||||
} else {
|
||||
Toast.makeText(getBaseContext(), toastMessage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
store.putBoolean("isPermissionDenied", true);
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getBaseContext(), toastMessage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationPermissionGranted() {
|
||||
if (moveToCurrentLocation || !(activity.equals("MediaActivity"))) {
|
||||
if (locationPermissionsHelper.isLocationAccessToAppsTurnedOn()) {
|
||||
locationManager.requestLocationUpdatesFromProvider(
|
||||
LocationManager.NETWORK_PROVIDER);
|
||||
locationManager.requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER);
|
||||
getLocation();
|
||||
} else {
|
||||
getLocation();
|
||||
locationPermissionsHelper.showLocationOffDialog(this,
|
||||
R.string.ask_to_turn_location_on_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets new location if locations services are on, else gets last location
|
||||
*/
|
||||
private void getLocation() {
|
||||
fr.free.nrw.commons.location.LatLng currLocation = locationManager.getLastLocation();
|
||||
if (currLocation != null) {
|
||||
GeoPoint currLocationGeopoint = new GeoPoint(currLocation.getLatitude(),
|
||||
currLocation.getLongitude());
|
||||
addLocationMarker(currLocationGeopoint);
|
||||
if (moveToCurrentLocation) {
|
||||
mapView.getController().setCenter(currLocationGeopoint);
|
||||
mapView.getController().animateTo(currLocationGeopoint);
|
||||
moveToCurrentLocation = false;
|
||||
}
|
||||
mapView.getController().setCenter(currLocationGeopoint);
|
||||
mapView.getController().animateTo(currLocationGeopoint);
|
||||
markerImage.setTranslationY(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public class BookmarkLocationsFragment extends DaggerFragment {
|
|||
contributionController.locationPermissionCallback.onLocationPermissionGranted();
|
||||
} else {
|
||||
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||
contributionController.handleShowRationaleFlowCameraLocation(getActivity());
|
||||
contributionController.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher);
|
||||
} else {
|
||||
contributionController.locationPermissionCallback.onLocationPermissionDenied(getActivity().getString(R.string.in_app_camera_location_permission_denied));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import fr.free.nrw.commons.filepicker.UploadableFile;
|
|||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper.Dialog;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper.LocationPermissionCallback;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.nearby.Place;
|
||||
|
|
@ -84,15 +83,6 @@ public class ContributionController {
|
|||
*/
|
||||
private void createDialogsAndHandleLocationPermissions(Activity activity,
|
||||
ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher) {
|
||||
LocationPermissionsHelper.Dialog locationAccessDialog = new Dialog(
|
||||
R.string.location_permission_title,
|
||||
R.string.in_app_camera_location_permission_rationale
|
||||
);
|
||||
|
||||
LocationPermissionsHelper.Dialog locationOffDialog = new Dialog(
|
||||
R.string.ask_to_turn_location_on,
|
||||
R.string.in_app_camera_needs_location
|
||||
);
|
||||
locationPermissionCallback = new LocationPermissionCallback() {
|
||||
@Override
|
||||
public void onLocationPermissionDenied(String toastMessage) {
|
||||
|
|
@ -106,7 +96,12 @@ public class ContributionController {
|
|||
|
||||
@Override
|
||||
public void onLocationPermissionGranted() {
|
||||
initiateCameraUpload(activity);
|
||||
if (!locationPermissionsHelper.isLocationAccessToAppsTurnedOn()) {
|
||||
showLocationOffDialog(activity, R.string.in_app_camera_needs_location,
|
||||
R.string.in_app_camera_location_unavailable);
|
||||
} else {
|
||||
initiateCameraUpload(activity);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -115,22 +110,46 @@ public class ContributionController {
|
|||
if (inAppCameraLocationPermissionLauncher != null) {
|
||||
inAppCameraLocationPermissionLauncher.launch(
|
||||
new String[]{permission.ACCESS_FINE_LOCATION});
|
||||
} else {
|
||||
locationPermissionsHelper.handleLocationPermissions(locationAccessDialog,
|
||||
locationOffDialog);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void handleShowRationaleFlowCameraLocation(Activity activity) {
|
||||
/**
|
||||
* Shows a dialog alerting the user about location services being off
|
||||
* and asking them to turn it on
|
||||
* TODO: Add a seperate callback in LocationPermissionsHelper for this.
|
||||
* Ref: https://github.com/commons-app/apps-android-commons/pull/5494/files#r1510553114
|
||||
*
|
||||
* @param activity Activity reference
|
||||
* @param dialogTextResource Resource id of text to be shown in dialog
|
||||
* @param toastTextResource Resource id of text to be shown in toast
|
||||
*/
|
||||
private void showLocationOffDialog(Activity activity, int dialogTextResource,
|
||||
int toastTextResource) {
|
||||
DialogUtil
|
||||
.showAlertDialog(activity,
|
||||
activity.getString(R.string.ask_to_turn_location_on),
|
||||
activity.getString(dialogTextResource),
|
||||
activity.getString(R.string.title_app_shortcut_setting),
|
||||
activity.getString(R.string.cancel),
|
||||
() -> locationPermissionsHelper.openLocationSettings(activity),
|
||||
() -> {
|
||||
Toast.makeText(activity, activity.getString(toastTextResource),
|
||||
Toast.LENGTH_LONG).show();
|
||||
initiateCameraUpload(activity);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void handleShowRationaleFlowCameraLocation(Activity activity,
|
||||
ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher) {
|
||||
DialogUtil.showAlertDialog(activity, activity.getString(R.string.location_permission_title),
|
||||
activity.getString(R.string.in_app_camera_location_permission_rationale),
|
||||
activity.getString(android.R.string.ok),
|
||||
activity.getString(android.R.string.cancel),
|
||||
() -> {
|
||||
if (!locationPermissionsHelper.isLocationAccessToAppsTurnedOn()) {
|
||||
locationPermissionsHelper.showLocationOffDialog(activity);
|
||||
}
|
||||
createDialogsAndHandleLocationPermissions(activity,
|
||||
inAppCameraLocationPermissionLauncher);
|
||||
},
|
||||
() -> locationPermissionCallback.onLocationPermissionDenied(
|
||||
activity.getString(R.string.in_app_camera_location_permission_denied)),
|
||||
|
|
@ -162,6 +181,7 @@ public class ContributionController {
|
|||
inAppCameraLocationPermissionLauncher);
|
||||
},
|
||||
() -> {
|
||||
ViewUtil.showLongToast(activity, R.string.in_app_camera_location_permission_denied);
|
||||
defaultKvStore.putBoolean("inAppCameraLocationPref", false);
|
||||
initiateCameraUpload(activity);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -147,21 +147,20 @@ public class ContributionsFragment
|
|||
areAllGranted = areAllGranted && b;
|
||||
}
|
||||
|
||||
if (areAllGranted) {
|
||||
onLocationPermissionGranted();
|
||||
if (areAllGranted) {
|
||||
onLocationPermissionGranted();
|
||||
} else {
|
||||
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
&& store.getBoolean("displayLocationPermissionForCardView", true)
|
||||
&& !store.getBoolean("doNotAskForLocationPermission", false)
|
||||
&& (((MainActivity) getActivity()).activeFragment == ActiveFragment.CONTRIBUTIONS)) {
|
||||
binding.cardViewNearby.permissionType = NearbyNotificationCardView.PermissionType.ENABLE_LOCATION_PERMISSION;
|
||||
} else {
|
||||
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
&& store.getBoolean("displayLocationPermissionForCardView", true)
|
||||
&& !store.getBoolean("doNotAskForLocationPermission", false)
|
||||
&& (((MainActivity) getActivity()).activeFragment == ActiveFragment.CONTRIBUTIONS)) {
|
||||
binding.cardViewNearby.permissionType = NearbyNotificationCardView.PermissionType.ENABLE_LOCATION_PERMISSION;
|
||||
showNearbyCardPermissionRationale();
|
||||
} else {
|
||||
displayYouWontSeeNearbyMessage();
|
||||
}
|
||||
displayYouWontSeeNearbyMessage();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@NonNull
|
||||
public static ContributionsFragment newInstance() {
|
||||
|
|
@ -537,6 +536,7 @@ public class ContributionsFragment
|
|||
private void displayYouWontSeeNearbyMessage() {
|
||||
ViewUtil.showLongToast(getActivity(),
|
||||
getResources().getString(R.string.unable_to_display_nearest_place));
|
||||
// Set to true as the user doesn't want the app to ask for location permission anymore
|
||||
store.putBoolean("doNotAskForLocationPermission", true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,26 +98,30 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
|
|||
private int contributionsSize;
|
||||
private String userName;
|
||||
|
||||
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
|
||||
@Override
|
||||
public void onActivityResult(Map<String, Boolean> result) {
|
||||
boolean areAllGranted = true;
|
||||
for (final boolean b : result.values()) {
|
||||
areAllGranted = areAllGranted && b;
|
||||
}
|
||||
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestMultiplePermissions(),
|
||||
new ActivityResultCallback<Map<String, Boolean>>() {
|
||||
@Override
|
||||
public void onActivityResult(Map<String, Boolean> result) {
|
||||
boolean areAllGranted = true;
|
||||
for (final boolean b : result.values()) {
|
||||
areAllGranted = areAllGranted && b;
|
||||
}
|
||||
|
||||
if (areAllGranted) {
|
||||
controller.locationPermissionCallback.onLocationPermissionGranted();
|
||||
} else {
|
||||
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||
controller.handleShowRationaleFlowCameraLocation(getActivity());
|
||||
if (areAllGranted) {
|
||||
controller.locationPermissionCallback.onLocationPermissionGranted();
|
||||
} else {
|
||||
controller.locationPermissionCallback.onLocationPermissionDenied(
|
||||
getActivity().getString(R.string.in_app_camera_location_permission_denied));
|
||||
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||
controller.handleShowRationaleFlowCameraLocation(getActivity(),
|
||||
inAppCameraLocationPermissionLauncher);
|
||||
} else {
|
||||
controller.locationPermissionCallback.onLocationPermissionDenied(
|
||||
getActivity().getString(
|
||||
R.string.in_app_camera_location_permission_denied));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -11,11 +11,9 @@ public class ExploreMapContract {
|
|||
|
||||
interface View {
|
||||
boolean isNetworkConnectionEstablished();
|
||||
void populatePlaces(LatLng currentLatLng);
|
||||
void checkPermissionsAndPerformAction();
|
||||
void recenterMap(LatLng currentLatLng);
|
||||
void showLocationOffDialog();
|
||||
void openLocationSettings();
|
||||
void populatePlaces(LatLng curlatLng);
|
||||
void askForLocationPermission();
|
||||
void recenterMap(LatLng curLatLng);
|
||||
void hideBottomDetailsSheet();
|
||||
LatLng getMapCenter();
|
||||
LatLng getMapFocus();
|
||||
|
|
|
|||
|
|
@ -48,8 +48,11 @@ import fr.free.nrw.commons.databinding.FragmentExploreMapBinding;
|
|||
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||
import fr.free.nrw.commons.explore.ExploreMapRootFragment;
|
||||
import fr.free.nrw.commons.explore.paging.LiveDataConverter;
|
||||
import fr.free.nrw.commons.filepicker.Constants;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper.LocationPermissionCallback;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.location.LocationUpdateListener;
|
||||
import fr.free.nrw.commons.media.MediaClient;
|
||||
|
|
@ -65,7 +68,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
|||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.osmdroid.events.MapEventsReceiver;
|
||||
|
|
@ -87,7 +89,7 @@ import org.osmdroid.views.overlay.TilesOverlay;
|
|||
import timber.log.Timber;
|
||||
|
||||
public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
||||
implements ExploreMapContract.View, LocationUpdateListener {
|
||||
implements ExploreMapContract.View, LocationUpdateListener, LocationPermissionCallback {
|
||||
|
||||
private BottomSheetBehavior bottomSheetDetailsBehavior;
|
||||
private BroadcastReceiver broadcastReceiver;
|
||||
|
|
@ -119,48 +121,40 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
BookmarkLocationsDao bookmarkLocationDao; // May be needed in future if we want to integrate bookmarking explore places
|
||||
@Inject
|
||||
SystemThemeUtils systemThemeUtils;
|
||||
LocationPermissionsHelper locationPermissionsHelper;
|
||||
|
||||
private ExploreMapPresenter presenter;
|
||||
|
||||
public FragmentExploreMapBinding binding;
|
||||
|
||||
private ActivityResultLauncher<String[]> activityResultLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestMultiplePermissions(),
|
||||
new ActivityResultCallback<Map<String, Boolean>>() {
|
||||
@Override
|
||||
public void onActivityResult(Map<String, Boolean> result) {
|
||||
boolean areAllGranted = true;
|
||||
for (final boolean b : result.values()) {
|
||||
areAllGranted = areAllGranted && b;
|
||||
}
|
||||
|
||||
if (areAllGranted) {
|
||||
locationPermissionGranted();
|
||||
private ActivityResultLauncher<String> activityResultLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(), isGranted -> {
|
||||
if (isGranted) {
|
||||
locationPermissionGranted();
|
||||
} else {
|
||||
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||
DialogUtil.showAlertDialog(getActivity(),
|
||||
getActivity().getString(R.string.location_permission_title),
|
||||
getActivity().getString(R.string.location_permission_rationale_explore),
|
||||
getActivity().getString(android.R.string.ok),
|
||||
getActivity().getString(android.R.string.cancel),
|
||||
() -> {
|
||||
askForLocationPermission();
|
||||
},
|
||||
null,
|
||||
null,
|
||||
false);
|
||||
} else {
|
||||
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||
DialogUtil.showAlertDialog(getActivity(),
|
||||
getActivity().getString(R.string.location_permission_title),
|
||||
getActivity().getString(R.string.location_permission_rationale_nearby),
|
||||
getActivity().getString(android.R.string.ok),
|
||||
getActivity().getString(android.R.string.cancel),
|
||||
() -> {
|
||||
if (!(locationManager.isNetworkProviderEnabled()
|
||||
|| locationManager.isGPSProviderEnabled())) {
|
||||
showLocationOffDialog();
|
||||
}
|
||||
},
|
||||
() -> isPermissionDenied = true,
|
||||
null,
|
||||
false);
|
||||
} else {
|
||||
isPermissionDenied = true;
|
||||
if (isPermissionDenied) {
|
||||
locationPermissionsHelper.showAppSettingsDialog(getActivity(),
|
||||
R.string.explore_map_needs_location);
|
||||
}
|
||||
|
||||
Timber.d("The user checked 'Don't ask again' or denied the permission twice");
|
||||
isPermissionDenied = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@NonNull
|
||||
public static ExploreMapFragment newInstance() {
|
||||
ExploreMapFragment fragment = new ExploreMapFragment();
|
||||
|
|
@ -184,7 +178,7 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
setSearchThisAreaButtonVisibility(false);
|
||||
binding.tvAttribution.setText(Html.fromHtml(getString(R.string.map_attribution)));
|
||||
initNetworkBroadCastReceiver();
|
||||
|
||||
locationPermissionsHelper = new LocationPermissionsHelper(getActivity(),locationManager,this);
|
||||
if (presenter == null) {
|
||||
presenter = new ExploreMapPresenter(bookmarkLocationDao);
|
||||
}
|
||||
|
|
@ -278,7 +272,9 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
|
||||
});
|
||||
|
||||
if (!locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
askForLocationPermission();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -288,8 +284,7 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
presenter.attachView(this);
|
||||
registerNetworkReceiver();
|
||||
if (isResumed()) {
|
||||
if (!isPermissionDenied && !applicationKvStore
|
||||
.getBoolean("doNotAskForLocationPermission", false)) {
|
||||
if (locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
performMapReadyActions();
|
||||
} else {
|
||||
startMapWithoutPermission();
|
||||
|
|
@ -297,8 +292,24 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
// unregistering the broadcastReceiver, as it was causing an exception and a potential crash
|
||||
unregisterNetworkReceiver();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unregisters the networkReceiver
|
||||
*/
|
||||
private void unregisterNetworkReceiver() {
|
||||
if (getActivity() != null) {
|
||||
getActivity().unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
private void startMapWithoutPermission() {
|
||||
applicationKvStore.putBoolean("doNotAskForLocationPermission", true);
|
||||
lastKnownLocation = MapUtils.defaultLatLng;
|
||||
moveCameraToPosition(
|
||||
new GeoPoint(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()));
|
||||
|
|
@ -316,13 +327,14 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
binding.mapView.getOverlayManager().getTilesOverlay()
|
||||
.setColorFilter(TilesOverlay.INVERT_COLORS);
|
||||
}
|
||||
if (!applicationKvStore.getBoolean("doNotAskForLocationPermission", false) ||
|
||||
PermissionUtils.hasPermission(getActivity(),
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION})) {
|
||||
checkPermissionsAndPerformAction();
|
||||
} else {
|
||||
if (applicationKvStore.getBoolean("doNotAskForLocationPermission", false) &&
|
||||
!locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
isPermissionDenied = true;
|
||||
}
|
||||
lastKnownLocation = MapUtils.defaultLatLng;
|
||||
moveCameraToPosition(
|
||||
new GeoPoint(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()));
|
||||
presenter.onMapReady(exploreMapController);
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
|
|
@ -394,7 +406,6 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
public void populatePlaces(LatLng currentLatLng) {
|
||||
final Observable<MapController.ExplorePlacesInfo> nearbyPlacesInfoObservable;
|
||||
if (currentLatLng == null) {
|
||||
checkPermissionsAndPerformAction();
|
||||
return;
|
||||
}
|
||||
if (currentLatLng.equals(getLastMapFocus())) { // Means we are checking around current location
|
||||
|
|
@ -417,8 +428,9 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
},
|
||||
throwable -> {
|
||||
Timber.d(throwable);
|
||||
showErrorMessage(getString(R.string.error_fetching_nearby_places)
|
||||
+ throwable.getLocalizedMessage());
|
||||
// Not showing the user, throwable localizedErrorMessage
|
||||
showErrorMessage(getString(R.string.error_fetching_nearby_places));
|
||||
|
||||
setProgressBarVisibility(false);
|
||||
presenter.lockUnlockNearby(false);
|
||||
}));
|
||||
|
|
@ -445,9 +457,9 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkPermissionsAndPerformAction() {
|
||||
Timber.d("Checking permission and perfoming action");
|
||||
activityResultLauncher.launch(new String[]{permission.ACCESS_FINE_LOCATION});
|
||||
public void askForLocationPermission() {
|
||||
Timber.d("Asking for location permission");
|
||||
activityResultLauncher.launch(permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
|
||||
private void locationPermissionGranted() {
|
||||
|
|
@ -466,9 +478,9 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
locationManager.requestLocationUpdatesFromProvider(LocationManager.NETWORK_PROVIDER);
|
||||
locationManager.requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER);
|
||||
setProgressBarVisibility(true);
|
||||
} else {
|
||||
Toast.makeText(getContext(), getString(R.string.nearby_location_not_available),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
else {
|
||||
locationPermissionsHelper.showLocationOffDialog(getActivity(), R.string.ask_to_turn_location_on_text);
|
||||
}
|
||||
presenter.onMapReady(exploreMapController);
|
||||
registerUnregisterLocationListener(false);
|
||||
|
|
@ -480,13 +492,24 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
|
||||
@Override
|
||||
public void recenterMap(LatLng currentLatLng) {
|
||||
if (isPermissionDenied || currentLatLng == null) {
|
||||
recenterToUserLocation = true;
|
||||
checkPermissionsAndPerformAction();
|
||||
if (!isPermissionDenied && !(locationManager.isNetworkProviderEnabled()
|
||||
|| locationManager.isGPSProviderEnabled())) {
|
||||
showLocationOffDialog();
|
||||
// if user has denied permission twice, then show dialog
|
||||
if (isPermissionDenied) {
|
||||
if (locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
// this will run when user has given permission by opening app's settings
|
||||
isPermissionDenied = false;
|
||||
recenterMap(currentLatLng);
|
||||
} else {
|
||||
askForLocationPermission();
|
||||
}
|
||||
} else {
|
||||
if (!locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
askForLocationPermission();
|
||||
} else {
|
||||
locationPermissionGranted();
|
||||
}
|
||||
}
|
||||
if (currentLatLng == null) {
|
||||
recenterToUserLocation = true;
|
||||
return;
|
||||
}
|
||||
recenterMarkerToPosition(new GeoPoint(currentLatLng.getLatitude(), currentLatLng.getLongitude()));
|
||||
|
|
@ -514,31 +537,6 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showLocationOffDialog() {
|
||||
// This creates a dialog box that prompts the user to enable location
|
||||
DialogUtil
|
||||
.showAlertDialog(getActivity(), getString(R.string.ask_to_turn_location_on),
|
||||
getString(R.string.nearby_needs_location),
|
||||
getString(R.string.yes), getString(R.string.no), this::openLocationSettings, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openLocationSettings() {
|
||||
// This method opens the location settings of the device along with a followup toast.
|
||||
final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
|
||||
final PackageManager packageManager = getActivity().getPackageManager();
|
||||
|
||||
if (intent.resolveActivity(packageManager) != null) {
|
||||
startActivity(intent);
|
||||
Toast.makeText(getContext(), R.string.recommend_high_accuracy_mode, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
} else {
|
||||
Toast.makeText(getContext(), R.string.cannot_open_location_settings, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideBottomDetailsSheet() {
|
||||
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||
|
|
@ -843,7 +841,20 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
if (mapCenter != null) {
|
||||
latLnge = new fr.free.nrw.commons.location.LatLng(
|
||||
mapCenter.getLatitude(), mapCenter.getLongitude(), 100);
|
||||
} else {
|
||||
if (applicationKvStore.getString("LastLocation") != null) {
|
||||
final String[] locationLatLng
|
||||
= applicationKvStore.getString("LastLocation").split(",");
|
||||
lastKnownLocation
|
||||
= new fr.free.nrw.commons.location.LatLng(Double.parseDouble(locationLatLng[0]),
|
||||
Double.parseDouble(locationLatLng[1]), 1f);
|
||||
latLnge = lastKnownLocation;
|
||||
} else {
|
||||
latLnge = new fr.free.nrw.commons.location.LatLng(51.506255446947776,
|
||||
-0.07483536015053005, 1f);
|
||||
}
|
||||
}
|
||||
moveCameraToPosition(new GeoPoint(latLnge.getLatitude(),latLnge.getLongitude()));
|
||||
return latLnge;
|
||||
}
|
||||
|
||||
|
|
@ -902,4 +913,10 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationPermissionDenied(String toastMessage) {}
|
||||
|
||||
@Override
|
||||
public void onLocationPermissionGranted() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,6 @@ public class ExploreMapPresenter
|
|||
|
||||
public void onMapReady(ExploreMapController exploreMapController) {
|
||||
this.exploreMapController = exploreMapController;
|
||||
exploreMapFragmentView.addSearchThisAreaButtonAction();
|
||||
if (null != exploreMapFragmentView) {
|
||||
exploreMapFragmentView.addSearchThisAreaButtonAction();
|
||||
initializeMapOperations();
|
||||
|
|
@ -141,7 +140,6 @@ public class ExploreMapPresenter
|
|||
public void initializeMapOperations() {
|
||||
lockUnlockNearby(false);
|
||||
updateMap(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||
exploreMapFragmentView.addSearchThisAreaButtonAction();
|
||||
}
|
||||
|
||||
public Observable<ExplorePlacesInfo> loadAttractionsFromLocation(LatLng currentLatLng,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
package fr.free.nrw.commons.location;
|
||||
|
||||
import android.Manifest;
|
||||
import android.Manifest.permission;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.provider.Settings;
|
||||
import android.widget.Toast;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.filepicker.Constants.RequestCodes;
|
||||
|
|
@ -12,120 +15,172 @@ import fr.free.nrw.commons.utils.DialogUtil;
|
|||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
|
||||
/**
|
||||
* Helper class to handle location permissions
|
||||
* Helper class to handle location permissions.
|
||||
*
|
||||
* Location flow for fragments containing a map is as follows:
|
||||
* Case 1: When location permission has never been asked for or denied before
|
||||
* Check if permission is already granted or not.
|
||||
* If not already granted, ask for it (if it isn't denied twice before).
|
||||
* If now user grants permission, go to Case 3/4, else go to Case 2.
|
||||
*
|
||||
* Case 2: When location permission is just asked but has been denied
|
||||
* Shows a toast to tell the user why location permission is needed.
|
||||
* Also shows a rationale to the user, on agreeing to which, we go back to Case 1.
|
||||
* Show current location / nearby pins / nearby images according to the default location.
|
||||
*
|
||||
* Case 3: When location permission are already granted, but location services are off
|
||||
* Asks the user to turn on the location service, using a dialog.
|
||||
* If the user rejects, checks for the last known location and shows stuff using that location.
|
||||
* Also displays a toast telling the user why location should be turned on.
|
||||
*
|
||||
* Case 4: When location permission has been granted and location services are also on
|
||||
* Do whatever is required by that particular activity / fragment using current location.
|
||||
*
|
||||
*/
|
||||
public class LocationPermissionsHelper {
|
||||
|
||||
Activity activity;
|
||||
LocationServiceManager locationManager;
|
||||
LocationPermissionCallback callback;
|
||||
|
||||
public LocationPermissionsHelper(Activity activity, LocationServiceManager locationManager,
|
||||
LocationPermissionCallback callback) {
|
||||
this.activity = activity;
|
||||
this.locationManager = locationManager;
|
||||
this.callback = callback;
|
||||
}
|
||||
public static class Dialog {
|
||||
int dialogTitleResource;
|
||||
int dialogTextResource;
|
||||
|
||||
public Dialog(int dialogTitle, int dialogText) {
|
||||
dialogTitleResource = dialogTitle;
|
||||
dialogTextResource = dialogText;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the entire location permissions flow
|
||||
* Ask for location permission if the user agrees on attaching location with pictures and the
|
||||
* app does not have the access to location
|
||||
*
|
||||
* @param locationAccessDialog
|
||||
* @param locationOffDialog
|
||||
* @param dialogTitleResource Resource id of the title of the dialog
|
||||
* @param dialogTextResource Resource id of the text of the dialog
|
||||
*/
|
||||
public void handleLocationPermissions(Dialog locationAccessDialog,
|
||||
Dialog locationOffDialog) {
|
||||
requestForLocationAccess(locationAccessDialog, locationOffDialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask for location permission if the user agrees on attaching location with pictures
|
||||
* and the app does not have the access to location
|
||||
*
|
||||
* @param locationAccessDialog
|
||||
* @param locationOffDialog
|
||||
*/
|
||||
private void requestForLocationAccess(
|
||||
Dialog locationAccessDialog,
|
||||
Dialog locationOffDialog
|
||||
public void requestForLocationAccess(
|
||||
int dialogTitleResource,
|
||||
int dialogTextResource
|
||||
) {
|
||||
if (PermissionUtils.hasPermission(activity, new String[]{permission.ACCESS_FINE_LOCATION})) {
|
||||
if (checkLocationPermission(activity)) {
|
||||
callback.onLocationPermissionGranted();
|
||||
} else {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission.ACCESS_FINE_LOCATION)) {
|
||||
if (locationAccessDialog != null && locationOffDialog != null) {
|
||||
DialogUtil.showAlertDialog(activity, activity.getString(locationAccessDialog.dialogTitleResource),
|
||||
activity.getString(locationAccessDialog.dialogTextResource),
|
||||
activity.getString(android.R.string.ok),
|
||||
activity.getString(android.R.string.cancel),
|
||||
() -> {
|
||||
if (!isLocationAccessToAppsTurnedOn()) {
|
||||
showLocationOffDialog(activity);
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(activity,
|
||||
new String[]{permission.ACCESS_FINE_LOCATION}, 1);
|
||||
}
|
||||
},
|
||||
() -> callback.onLocationPermissionDenied(activity.getString(R.string.in_app_camera_location_permission_denied)),
|
||||
null,
|
||||
false);
|
||||
}
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
|
||||
permission.ACCESS_FINE_LOCATION)) {
|
||||
DialogUtil.showAlertDialog(activity, activity.getString(dialogTitleResource),
|
||||
activity.getString(dialogTextResource),
|
||||
activity.getString(android.R.string.ok),
|
||||
activity.getString(android.R.string.cancel),
|
||||
() -> {
|
||||
ActivityCompat.requestPermissions(activity,
|
||||
new String[]{permission.ACCESS_FINE_LOCATION}, 1);
|
||||
},
|
||||
() -> callback.onLocationPermissionDenied(
|
||||
activity.getString(R.string.upload_map_location_access)),
|
||||
null,
|
||||
false);
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(activity, new String[]{permission.ACCESS_FINE_LOCATION},
|
||||
ActivityCompat.requestPermissions(activity,
|
||||
new String[]{permission.ACCESS_FINE_LOCATION},
|
||||
RequestCodes.LOCATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void showLocationOffDialog(Activity activity) {
|
||||
/**
|
||||
* Shows a dialog for user to open the settings page and turn on location services
|
||||
*
|
||||
* @param activity Activity object
|
||||
* @param dialogTextResource int id of the required string resource
|
||||
*/
|
||||
public void showLocationOffDialog(Activity activity, int dialogTextResource) {
|
||||
DialogUtil
|
||||
.showAlertDialog(activity,
|
||||
activity.getString(R.string.ask_to_turn_location_on),
|
||||
activity.getString(R.string.in_app_camera_needs_location),
|
||||
activity.getString(dialogTextResource),
|
||||
activity.getString(R.string.title_app_shortcut_setting),
|
||||
activity.getString(R.string.cancel),
|
||||
() -> openLocationSettings(activity),
|
||||
() -> callback.onLocationPermissionDenied(activity.getString(
|
||||
R.string.in_app_camera_location_unavailable)));
|
||||
() -> Toast.makeText(activity, activity.getString(dialogTextResource),
|
||||
Toast.LENGTH_LONG).show()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open location source settings so that apps with location access can access it
|
||||
* Opens the location access page in settings, for user to turn on location services
|
||||
*
|
||||
* TODO: modify it to fix https://github.com/commons-app/apps-android-commons/issues/5255
|
||||
* @param activity Activtiy object
|
||||
*/
|
||||
|
||||
public void openLocationSettings(Activity activity) {
|
||||
final Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
|
||||
final PackageManager packageManager = activity.getPackageManager();
|
||||
|
||||
if (intent.resolveActivity(packageManager)!= null) {
|
||||
if (intent.resolveActivity(packageManager) != null) {
|
||||
activity.startActivity(intent);
|
||||
} else {
|
||||
Toast.makeText(activity, R.string.cannot_open_location_settings, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a dialog for user to open the app's settings page and give location permission
|
||||
*
|
||||
* @param activity Activity object
|
||||
* @param dialogTextResource int id of the required string resource
|
||||
*/
|
||||
public void showAppSettingsDialog(Activity activity, int dialogTextResource) {
|
||||
DialogUtil
|
||||
.showAlertDialog(activity, activity.getString(R.string.location_permission_title),
|
||||
activity.getString(dialogTextResource),
|
||||
activity.getString(R.string.title_app_shortcut_setting),
|
||||
activity.getString(R.string.cancel),
|
||||
() -> openAppSettings(activity),
|
||||
() -> Toast.makeText(activity, activity.getString(dialogTextResource),
|
||||
Toast.LENGTH_LONG).show()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens detailed settings page of the app for the user to turn on location services
|
||||
*
|
||||
* @param activity Activity object
|
||||
*/
|
||||
public void openAppSettings(Activity activity) {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if apps have access to location even after having individual access
|
||||
*
|
||||
* @return
|
||||
* @return Returns true if location services are on and false otherwise
|
||||
*/
|
||||
public boolean isLocationAccessToAppsTurnedOn() {
|
||||
return (locationManager.isNetworkProviderEnabled() || locationManager.isGPSProviderEnabled());
|
||||
return (locationManager.isNetworkProviderEnabled()
|
||||
|| locationManager.isGPSProviderEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if location permission is already granted or not
|
||||
*
|
||||
* @param activity Activity object
|
||||
* @return Returns true if location permission is granted and false otherwise
|
||||
*/
|
||||
public boolean checkLocationPermission(Activity activity) {
|
||||
return PermissionUtils.hasPermission(activity,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle onPermissionDenied within individual classes based on the requirements
|
||||
*/
|
||||
public interface LocationPermissionCallback {
|
||||
|
||||
void onLocationPermissionDenied(String toastMessage);
|
||||
|
||||
void onLocationPermissionGranted();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public interface NearbyParentFragmentContract {
|
|||
|
||||
boolean isListBottomSheetExpanded();
|
||||
|
||||
void checkPermissionsAndPerformAction();
|
||||
void askForLocationPermission();
|
||||
|
||||
void displayLoginSkippedWarning();
|
||||
|
||||
|
|
@ -36,8 +36,6 @@ public interface NearbyParentFragmentContract {
|
|||
|
||||
void recenterMap(LatLng currentLatLng);
|
||||
|
||||
void showLocationOffDialog();
|
||||
|
||||
void openLocationSettings();
|
||||
|
||||
void hideBottomSheet();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import static fr.free.nrw.commons.location.LocationServiceManager.LocationChange
|
|||
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.MAP_UPDATED;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT;
|
||||
|
||||
import android.Manifest;
|
||||
import android.Manifest.permission;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
|
|
@ -67,6 +66,8 @@ import fr.free.nrw.commons.contributions.MainActivity.ActiveFragment;
|
|||
import fr.free.nrw.commons.databinding.FragmentNearbyParentBinding;
|
||||
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper;
|
||||
import fr.free.nrw.commons.location.LocationPermissionsHelper.LocationPermissionCallback;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.location.LocationUpdateListener;
|
||||
|
|
@ -84,9 +85,9 @@ import fr.free.nrw.commons.upload.FileUtils;
|
|||
import fr.free.nrw.commons.utils.DialogUtil;
|
||||
import fr.free.nrw.commons.utils.ExecutorUtils;
|
||||
import fr.free.nrw.commons.utils.LayoutUtils;
|
||||
import fr.free.nrw.commons.utils.MapUtils;
|
||||
import fr.free.nrw.commons.utils.NearbyFABUtils;
|
||||
import fr.free.nrw.commons.utils.NetworkUtils;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
import fr.free.nrw.commons.utils.SystemThemeUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||
|
|
@ -130,7 +131,8 @@ import timber.log.Timber;
|
|||
|
||||
public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||
implements NearbyParentFragmentContract.View,
|
||||
WikidataEditListener.WikidataP18EditListener, LocationUpdateListener {
|
||||
WikidataEditListener.WikidataP18EditListener, LocationUpdateListener,
|
||||
LocationPermissionCallback {
|
||||
|
||||
|
||||
FragmentNearbyParentBinding binding;
|
||||
|
|
@ -152,6 +154,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
SystemThemeUtils systemThemeUtils;
|
||||
@Inject
|
||||
CommonPlaceClickActions commonPlaceClickActions;
|
||||
private LocationPermissionsHelper locationPermissionsHelper;
|
||||
private NearbyFilterSearchRecyclerViewAdapter nearbyFilterSearchRecyclerViewAdapter;
|
||||
private BottomSheetBehavior bottomSheetListBehavior;
|
||||
private BottomSheetBehavior bottomSheetDetailsBehavior;
|
||||
|
|
@ -201,7 +204,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
controller.locationPermissionCallback.onLocationPermissionGranted();
|
||||
} else {
|
||||
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||
controller.handleShowRationaleFlowCameraLocation(getActivity());
|
||||
controller.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher);
|
||||
} else {
|
||||
controller.locationPermissionCallback.onLocationPermissionDenied(
|
||||
getActivity().getString(
|
||||
|
|
@ -223,15 +226,17 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
getActivity().getString(android.R.string.ok),
|
||||
getActivity().getString(android.R.string.cancel),
|
||||
() -> {
|
||||
if (!(locationManager.isNetworkProviderEnabled()
|
||||
|| locationManager.isGPSProviderEnabled())) {
|
||||
showLocationOffDialog();
|
||||
}
|
||||
askForLocationPermission();
|
||||
},
|
||||
() -> isPermissionDenied = true,
|
||||
null,
|
||||
null,
|
||||
false);
|
||||
} else {
|
||||
if (isPermissionDenied) {
|
||||
locationPermissionsHelper.showAppSettingsDialog(getActivity(),
|
||||
R.string.nearby_needs_location);
|
||||
}
|
||||
Timber.d("The user checked 'Don't ask again' or denied the permission twice");
|
||||
isPermissionDenied = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -323,7 +328,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
} else {
|
||||
binding.rlContainerWlmMonthMessage.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
locationPermissionsHelper = new LocationPermissionsHelper(getActivity(), locationManager,
|
||||
this);
|
||||
presenter.attachView(this);
|
||||
isPermissionDenied = false;
|
||||
recenterToUserLocation = false;
|
||||
|
|
@ -426,7 +432,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
initNearbyFilter();
|
||||
addCheckBoxCallback();
|
||||
performMapReadyActions();
|
||||
moveCameraToPosition(lastMapFocus);
|
||||
initRvNearbyList();
|
||||
onResume();
|
||||
|
|
@ -471,6 +476,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
|
||||
binding.tvLearnMore.setOnClickListener(v ->onLearnMoreClicked());
|
||||
binding.nearbyFilter.ivToggleChips.setOnClickListener(v -> onToggleChipsClicked());
|
||||
|
||||
if (!locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
askForLocationPermission();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -527,14 +536,18 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
|
||||
private void performMapReadyActions() {
|
||||
if (((MainActivity) getActivity()).activeFragment == ActiveFragment.NEARBY) {
|
||||
if (!applicationKvStore.getBoolean("doNotAskForLocationPermission", false) ||
|
||||
PermissionUtils.hasPermission(getActivity(),
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION})) {
|
||||
checkPermissionsAndPerformAction();
|
||||
} else {
|
||||
if (applicationKvStore.getBoolean("doNotAskForLocationPermission", false) &&
|
||||
!locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
isPermissionDenied = true;
|
||||
}
|
||||
}
|
||||
presenter.onMapReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void askForLocationPermission() {
|
||||
Timber.d("Asking for location permission");
|
||||
locationPermissionLauncher.launch(permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
|
||||
private void locationPermissionGranted() {
|
||||
|
|
@ -554,8 +567,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
locationManager.requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER);
|
||||
setProgressBarVisibility(true);
|
||||
} else {
|
||||
Toast.makeText(getContext(), getString(R.string.nearby_location_not_available),
|
||||
Toast.LENGTH_LONG).show();
|
||||
locationPermissionsHelper.showLocationOffDialog(getActivity(), R.string.ask_to_turn_location_on_text);
|
||||
}
|
||||
presenter.onMapReady();
|
||||
registerUnregisterLocationListener(false);
|
||||
|
|
@ -568,15 +580,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
presenter.attachView(this);
|
||||
registerNetworkReceiver();
|
||||
if (isResumed() && ((MainActivity) getActivity()).activeFragment == ActiveFragment.NEARBY) {
|
||||
if (!isPermissionDenied && !applicationKvStore.getBoolean(
|
||||
"doNotAskForLocationPermission", false)) {
|
||||
if (!locationManager.isGPSProviderEnabled()) {
|
||||
startMapWithCondition("Without GPS");
|
||||
} else {
|
||||
startTheMap();
|
||||
}
|
||||
if (locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
locationPermissionGranted();
|
||||
} else {
|
||||
startMapWithCondition("Without Permission");
|
||||
startMapWithoutPermission();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -586,12 +593,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
* coordinates, other than that it points to the last known location which can be get by the key
|
||||
* "LastLocation" from applicationKvStore
|
||||
*
|
||||
* @param condition : for which condition the map should start
|
||||
*/
|
||||
private void startMapWithCondition(final String condition) {
|
||||
if (condition.equals("Without Permission")) {
|
||||
applicationKvStore.putBoolean("doNotAskForLocationPermission", true);
|
||||
}
|
||||
private void startMapWithoutPermission() {
|
||||
if (applicationKvStore.getString("LastLocation") != null) {
|
||||
final String[] locationLatLng
|
||||
= applicationKvStore.getString("LastLocation").split(",");
|
||||
|
|
@ -599,12 +602,13 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
= new fr.free.nrw.commons.location.LatLng(Double.parseDouble(locationLatLng[0]),
|
||||
Double.parseDouble(locationLatLng[1]), 1f);
|
||||
} else {
|
||||
lastKnownLocation = new fr.free.nrw.commons.location.LatLng(51.50550,
|
||||
-0.07520, 1f);
|
||||
lastKnownLocation = MapUtils.defaultLatLng;
|
||||
}
|
||||
if (binding.map != null) {
|
||||
recenterMap(lastKnownLocation);
|
||||
moveCameraToPosition(
|
||||
new GeoPoint(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()));
|
||||
}
|
||||
presenter.onMapReady();
|
||||
}
|
||||
|
||||
private void registerNetworkReceiver() {
|
||||
|
|
@ -1426,12 +1430,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermissionsAndPerformAction() {
|
||||
Timber.d("Checking permission and perfoming action");
|
||||
locationPermissionLauncher.launch(permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts animation of fab plus (turning on opening) and other FABs
|
||||
*/
|
||||
|
|
@ -1559,6 +1557,14 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
return presenter.backButtonClicked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationPermissionDenied(String toastMessage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationPermissionGranted() {
|
||||
}
|
||||
|
||||
/**
|
||||
* onLogoutComplete is called after shared preferences and data stored in local database are
|
||||
* cleared.
|
||||
|
|
@ -1856,18 +1862,37 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
|
||||
@Override
|
||||
public void recenterMap(fr.free.nrw.commons.location.LatLng currentLatLng) {
|
||||
if (isPermissionDenied || currentLatLng == null) {
|
||||
recenterToUserLocation = true;
|
||||
checkPermissionsAndPerformAction();
|
||||
if (!isPermissionDenied && !(locationManager.isNetworkProviderEnabled()
|
||||
|| locationManager.isGPSProviderEnabled())) {
|
||||
showLocationOffDialog();
|
||||
// if user has denied permission twice, then show dialog
|
||||
if (isPermissionDenied) {
|
||||
if (locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
// this will run when user has given permission by opening app's settings
|
||||
isPermissionDenied = false;
|
||||
locationPermissionGranted();
|
||||
return;
|
||||
} else {
|
||||
askForLocationPermission();
|
||||
}
|
||||
} else {
|
||||
if (!locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||
askForLocationPermission();
|
||||
} else {
|
||||
locationPermissionGranted();
|
||||
}
|
||||
}
|
||||
if (currentLatLng == null) {
|
||||
recenterToUserLocation = true;
|
||||
return;
|
||||
}
|
||||
addCurrentLocationMarker(currentLatLng);
|
||||
binding.map.getController()
|
||||
.animateTo(new GeoPoint(currentLatLng.getLatitude(), currentLatLng.getLongitude()));
|
||||
|
||||
/*
|
||||
* FIXME: With the revamp of the location permission helper in the MR
|
||||
* #5494[1], there is a doubt that the following code is redundant.
|
||||
* If we could confirm the same, the following code can be removed. If it
|
||||
* turns out to be necessary, we could replace this with a comment
|
||||
* clarifying why it is necessary.
|
||||
*
|
||||
* Ref: https://github.com/commons-app/apps-android-commons/pull/5494#discussion_r1560404794
|
||||
*/
|
||||
if (lastMapFocus != null) {
|
||||
Location mylocation = new Location("");
|
||||
Location dest_location = new Location("");
|
||||
|
|
@ -1890,15 +1915,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showLocationOffDialog() {
|
||||
// This creates a dialog box that prompts the user to enable location
|
||||
DialogUtil
|
||||
.showAlertDialog(getActivity(), getString(R.string.ask_to_turn_location_on),
|
||||
getString(R.string.nearby_needs_location),
|
||||
getString(R.string.yes), getString(R.string.no), this::openLocationSettings, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openLocationSettings() {
|
||||
// This method opens the location settings of the device along with a followup toast.
|
||||
|
|
@ -2103,7 +2119,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
super.setUserVisibleHint(isVisibleToUser);
|
||||
this.isVisibleToUser = isVisibleToUser;
|
||||
if (isResumed() && isVisibleToUser) {
|
||||
startTheMap();
|
||||
performMapReadyActions();
|
||||
} else {
|
||||
if (null != bottomSheetListBehavior) {
|
||||
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||
|
|
@ -2115,10 +2131,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
private void startTheMap() {
|
||||
performMapReadyActions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all markers from the map and resets certain map overlays and gestures. After clearing
|
||||
* markers, it re-adds a scale bar overlay and rotation gesture overlay to the map.
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@ public class NearbyParentFragmentPresenter
|
|||
public void initializeMapOperations() {
|
||||
lockUnlockNearby(false);
|
||||
updateMapAndList(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||
this.nearbyParentFragmentView.addSearchThisAreaButtonAction();
|
||||
nearbyParentFragmentView.setCheckBoxAction();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
areAllGranted = areAllGranted && b;
|
||||
}
|
||||
if (!areAllGranted && shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||
contributionController.handleShowRationaleFlowCameraLocation(getActivity());
|
||||
contributionController.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -282,6 +282,8 @@
|
|||
<string name="nearby_location_not_available">Nearby might not work properly, Location not available.</string>
|
||||
<string name="upload_location_access_denied">Location access denied. Please set your location manually to use this feature.</string>
|
||||
<string name="location_permission_rationale_nearby">Permission required to display a list of nearby places</string>
|
||||
<string name="location_permission_rationale_explore">Permission required to display a list of nearby images</string>
|
||||
|
||||
|
||||
<string name="nearby_directions">Directions</string>
|
||||
<string name="nearby_wikidata">Wikidata</string>
|
||||
|
|
@ -355,7 +357,7 @@
|
|||
<string name="share_app_title">Share App</string>
|
||||
<string name="rotate">Rotate</string>
|
||||
|
||||
<string name="error_fetching_nearby_places">Error fetching nearby places.</string>
|
||||
<string name="error_fetching_nearby_places">Could not load nearby places</string>
|
||||
<string name="no_pictures_in_this_area">No pictures in this area</string>
|
||||
<string name="no_nearby_places_around">No nearby places around</string>
|
||||
<string name="error_fetching_nearby_monuments">Error fetching nearby monuments.</string>
|
||||
|
|
@ -586,7 +588,7 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="coordinates_edit_helper_edit_message_else">Could not add coordinates.</string>
|
||||
<string name="description_edit_helper_edit_message_else">Could not add descriptions.</string>
|
||||
<string name="caption_edit_helper_edit_message_else">Could not add caption.</string>
|
||||
<string name="coordinates_picking_unsuccessful">Unable to get coordinates.</string>
|
||||
<string name="coordinates_picking_unsuccessful">Image\'s coordinates not updated</string>
|
||||
<string name="descriptions_picking_unsuccessful">Unable to get descriptions.</string>
|
||||
<string name="description_activity_title">Edit descriptions and captions</string>
|
||||
|
||||
|
|
@ -623,8 +625,10 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="cannot_open_location_settings">Failed to open location settings. Please turn on location manually</string>
|
||||
<string name="recommend_high_accuracy_mode">For best results, choose the High Accuracy mode.</string>
|
||||
<string name="ask_to_turn_location_on">Turn on location?</string>
|
||||
<string name="ask_to_turn_location_on_text">Kindly turn on location services for the app show your current location</string>
|
||||
<string name="nearby_needs_location">Nearby needs location enabled to work properly</string>
|
||||
<string name="upload_map_location_access">You need to give access to your current location to set location automatically.</string>
|
||||
<string name="explore_map_needs_location">Explore map needs location permission to display nearby images</string>
|
||||
<string name="upload_map_location_access">You need to give location permission to set location automatically.</string>
|
||||
<string name="use_location_from_similar_image">Did you shoot these two pictures at the same place? Do you want to use the latitude/longitude of the picture on the right?</string>
|
||||
<string name="load_more">Load More</string>
|
||||
<string name="nearby_no_results">No places found, try changing your search criteria.</string>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ class NearbyParentFragmentPresenterTest {
|
|||
verify(nearbyParentFragmentView).`setProgressBarVisibility`(true)
|
||||
assertTrue(null == nearbyParentFragmentView.mapCenter)
|
||||
verify(nearbyParentFragmentView).populatePlaces(null)
|
||||
verify(nearbyParentFragmentView).addSearchThisAreaButtonAction()
|
||||
verify(nearbyParentFragmentView).setCheckBoxAction()
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +120,7 @@ class NearbyParentFragmentPresenterTest {
|
|||
/**
|
||||
* Test updateMapAndList method returns with zero interactions when last location is null
|
||||
*/
|
||||
@Test @Ignore
|
||||
@Test
|
||||
fun testUpdateMapAndListWhenLastLocationIsNull() {
|
||||
whenever(nearbyParentFragmentView.isNetworkConnectionEstablished()).thenReturn(true)
|
||||
whenever(nearbyParentFragmentView.getLastLocation()).thenReturn(null)
|
||||
|
|
|
|||
|
|
@ -379,12 +379,4 @@ class NearbyParentFragmentUnitTest {
|
|||
Assert.assertEquals(shadowActivity.nextStartedActivityForResult, null)
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
@Throws(Exception::class)
|
||||
fun testShowLocationOffDialog() {
|
||||
fragment.showLocationOffDialog()
|
||||
val dialog: AlertDialog = ShadowAlertDialog.getLatestDialog() as AlertDialog
|
||||
Assert.assertEquals(dialog.isShowing, true)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue