Add all location permission related methods to view contract and implement in fragment. Call them from presenter by passing locationServiceManager parameter

This commit is contained in:
neslihanturan 2019-05-16 16:26:44 +03:00
parent f8926aa2f1
commit 80708023aa
3 changed files with 169 additions and 2 deletions

View file

@ -1,10 +1,18 @@
package fr.free.nrw.commons.nearby.mvp.contract; package fr.free.nrw.commons.nearby.mvp.contract;
import fr.free.nrw.commons.location.LocationServiceManager;
public interface NearbyParentFragmentContract { public interface NearbyParentFragmentContract {
interface View { interface View {
void setListFragmentExpanded(); void setListFragmentExpanded();
void refreshView(); void refreshView();
void registerLocationUpdates(LocationServiceManager locationServiceManager);
void requestLocationPermissions(LocationServiceManager locationServiceManager);
void showLocationPermissionDeniedErrorDialog(LocationServiceManager locationServiceManager);
void checkGps(LocationServiceManager locationServiceManager);
void checkLocationPermission(LocationServiceManager locationServiceManager);
} }
interface UserActions { interface UserActions {

View file

@ -1,5 +1,7 @@
package fr.free.nrw.commons.nearby.mvp.fragments; package fr.free.nrw.commons.nearby.mvp.fragments;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -14,10 +16,12 @@ import javax.inject.Inject;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.location.LocationServiceManager; import fr.free.nrw.commons.location.LocationServiceManager;
@ -27,6 +31,7 @@ import fr.free.nrw.commons.nearby.NearbyListFragment;
import fr.free.nrw.commons.nearby.NearbyMapFragment; import fr.free.nrw.commons.nearby.NearbyMapFragment;
import fr.free.nrw.commons.nearby.mvp.contract.NearbyParentFragmentContract; import fr.free.nrw.commons.nearby.mvp.contract.NearbyParentFragmentContract;
import fr.free.nrw.commons.wikidata.WikidataEditListener; import fr.free.nrw.commons.wikidata.WikidataEditListener;
import timber.log.Timber;
/** /**
* This fragment is under MainActivity at the came level with ContributionFragment and holds * This fragment is under MainActivity at the came level with ContributionFragment and holds
@ -50,8 +55,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
@BindView(R.id.loading_nearby_list) @BindView(R.id.loading_nearby_list)
ConstraintLayout loading_nearby_layout; ConstraintLayout loading_nearby_layout;
@Inject
LocationServiceManager locationManager;
@Inject @Inject
NearbyController nearbyController; NearbyController nearbyController;
@Inject @Inject
@ -138,4 +141,147 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
public void refreshView() { public void refreshView() {
} }
/**
* This method first checks if the location permissions has been granted and then register the
* location manager for updates.
* @param locationServiceManager passed from presenter to check updates if location
* permissions are given
*/
@Override
public void registerLocationUpdates(LocationServiceManager locationServiceManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (locationServiceManager.isLocationPermissionGranted(requireContext())) {
locationServiceManager.registerLocationManager();
} else {
// Should we show an explanation?
if (locationServiceManager.isPermissionExplanationRequired(getActivity())) {
new AlertDialog.Builder(getActivity())
.setMessage(getString(R.string.location_permission_rationale_nearby))
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
requestLocationPermissions(locationServiceManager);
dialog.dismiss();
})
.setNegativeButton(android.R.string.cancel, (dialog, id) -> {
showLocationPermissionDeniedErrorDialog(locationServiceManager);
dialog.cancel();
})
.create()
.show();
} else {
// No explanation needed, we can request the permission.
requestLocationPermissions(locationServiceManager);
}
}
} else {
locationServiceManager.registerLocationManager();
}
}
/**
* Request location permission if activity is not null
* @param locationServiceManager passed from presenter, to listen/un-listen location changes
*/
@Override
public void requestLocationPermissions(LocationServiceManager locationServiceManager) {
if (!getActivity().isFinishing()) {
locationServiceManager.requestPermissions(getActivity());
}
}
/**
* Will warn user if location is denied
* @param locationServiceManager will be passed to checkGps if needs permission
*/
@Override
public void showLocationPermissionDeniedErrorDialog(LocationServiceManager locationServiceManager) {
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(locationServiceManager);
})
.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
* @param locationServiceManager will be used to check if provider is enable
*/
@Override
public void checkGps(LocationServiceManager locationServiceManager) {
Timber.d("checking GPS");
if (!locationServiceManager.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.
* @param locationServiceManager will be used to detect if location permission is granted or not
*/
@Override
public void checkLocationPermission(LocationServiceManager locationServiceManager) {
Timber.d("Checking location permission");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (locationServiceManager.isLocationPermissionGranted(requireContext())) {
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
} else {
// Should we show an explanation?
if (locationServiceManager.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(locationServiceManager);
}
}
} else {
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
}
}
} }

View file

@ -1,6 +1,9 @@
package fr.free.nrw.commons.nearby.mvp.presenter; package fr.free.nrw.commons.nearby.mvp.presenter;
import javax.inject.Inject;
import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.location.LocationUpdateListener; import fr.free.nrw.commons.location.LocationUpdateListener;
import fr.free.nrw.commons.nearby.mvp.contract.NearbyParentFragmentContract; import fr.free.nrw.commons.nearby.mvp.contract.NearbyParentFragmentContract;
import fr.free.nrw.commons.wikidata.WikidataEditListener; import fr.free.nrw.commons.wikidata.WikidataEditListener;
@ -9,6 +12,9 @@ public class NearbyParentFragmentPresenter
implements NearbyParentFragmentContract.UserActions, implements NearbyParentFragmentContract.UserActions,
WikidataEditListener.WikidataP18EditListener, WikidataEditListener.WikidataP18EditListener,
LocationUpdateListener { LocationUpdateListener {
@Inject
LocationServiceManager locationManager;
private NearbyParentFragmentContract.View nearbyParentFragmentView; private NearbyParentFragmentContract.View nearbyParentFragmentView;
public NearbyParentFragmentPresenter(NearbyParentFragmentContract.View nearbyParentFragmentView) { public NearbyParentFragmentPresenter(NearbyParentFragmentContract.View nearbyParentFragmentView) {
@ -25,8 +31,15 @@ public class NearbyParentFragmentPresenter
initializeNearbyOperations(); initializeNearbyOperations();
} }
/**
* Initializes nearby operations by following these steps:
* - Add this location listener to location manager
*/
@Override @Override
public void initializeNearbyOperations() { public void initializeNearbyOperations() {
locationManager.addLocationListener(this);
nearbyParentFragmentView.registerLocationUpdates(locationManager);
} }