mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Use dexter for requesting storage permissions (#2258)
* Use dexter for requesting storage permissions * minor changes * Fix minor issue
This commit is contained in:
parent
2ea6bd7f65
commit
a48a09a785
13 changed files with 149 additions and 408 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package fr.free.nrw.commons;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public class BookmarkLocationsFragment extends DaggerFragment {
|
|||
@Inject
|
||||
BookmarkLocationsController controller;
|
||||
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
|
||||
@Inject @Named("default_preferences") SharedPreferences defaultPrefs;
|
||||
private NearbyAdapterFactory adapterFactory;
|
||||
private ContributionController contributionController;
|
||||
|
||||
|
|
@ -66,7 +67,7 @@ public class BookmarkLocationsFragment extends DaggerFragment {
|
|||
) {
|
||||
View v = inflater.inflate(R.layout.fragment_bookmarks_locations, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
contributionController = new ContributionController(this);
|
||||
contributionController = new ContributionController(this, defaultPrefs);
|
||||
adapterFactory = new NearbyAdapterFactory(this, contributionController);
|
||||
return v;
|
||||
}
|
||||
|
|
@ -100,30 +101,6 @@ public class BookmarkLocationsFragment extends DaggerFragment {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults);
|
||||
|
||||
switch (requestCode) {
|
||||
// 4 = "Read external storage" allowed when gallery selected
|
||||
case 4: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
|
||||
Timber.d("Call controller.startGalleryPick()");
|
||||
contributionController.startGalleryPick();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 5 = "Write external storage" allowed when camera selected
|
||||
case 5: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Timber.d("Call controller.startCameraCapture()");
|
||||
contributionController.startCameraCapture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
|
|
@ -14,12 +17,24 @@ import android.support.v4.app.Fragment;
|
|||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.content.FileProvider;
|
||||
|
||||
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 java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.upload.UploadActivity;
|
||||
import fr.free.nrw.commons.utils.DialogUtil;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static android.content.Intent.ACTION_GET_CONTENT;
|
||||
|
|
@ -34,14 +49,16 @@ import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ITEM_LOCAT
|
|||
|
||||
public class ContributionController {
|
||||
|
||||
public static final int SELECT_FROM_GALLERY = 1;
|
||||
static final int SELECT_FROM_GALLERY = 1;
|
||||
public static final int SELECT_FROM_CAMERA = 2;
|
||||
public static final int PICK_IMAGE_MULTIPLE = 3;
|
||||
static final int PICK_IMAGE_MULTIPLE = 3;
|
||||
|
||||
private Fragment fragment;
|
||||
private SharedPreferences defaultPrefs;
|
||||
|
||||
public ContributionController(Fragment fragment) {
|
||||
public ContributionController(Fragment fragment, SharedPreferences defaultSharedPrefs) {
|
||||
this.fragment = fragment;
|
||||
this.defaultPrefs = defaultSharedPrefs;
|
||||
}
|
||||
|
||||
// See http://stackoverflow.com/a/5054673/17865 for why this is done
|
||||
|
|
@ -58,6 +75,85 @@ public class ContributionController {
|
|||
photoFile);
|
||||
}
|
||||
|
||||
public void initiateCameraPick(Activity activity) {
|
||||
boolean useExtStorage = defaultPrefs.getBoolean("useExternalStorage", true);
|
||||
if (!useExtStorage) {
|
||||
startCameraCapture();
|
||||
return;
|
||||
}
|
||||
Dexter.withActivity(activity)
|
||||
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
.withListener(new BasePermissionListener() {
|
||||
@Override
|
||||
public void onPermissionGranted(PermissionGrantedResponse response) {
|
||||
startCameraCapture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionDenied(PermissionDeniedResponse response) {
|
||||
if (response.isPermanentlyDenied()) {
|
||||
DialogUtil.showAlertDialog(activity,
|
||||
activity.getString(R.string.storage_permission_title),
|
||||
activity.getString(R.string.write_storage_permission_rationale),
|
||||
activity.getString(R.string.navigation_item_settings),
|
||||
null,
|
||||
() -> PermissionUtils.askUserToManuallyEnablePermissionFromSettings(activity),
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
|
||||
DialogUtil.showAlertDialog(activity,
|
||||
activity.getString(R.string.storage_permission_title),
|
||||
activity.getString(R.string.write_storage_permission_rationale),
|
||||
activity.getString(android.R.string.ok),
|
||||
activity.getString(android.R.string.cancel),
|
||||
token::continuePermissionRequest,
|
||||
token::cancelPermissionRequest);
|
||||
}
|
||||
}).check();
|
||||
}
|
||||
|
||||
public void initiateGalleryPick(Activity activity) {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
startGalleryPick();
|
||||
} else {
|
||||
Dexter.withActivity(activity)
|
||||
.withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.withListener(new BasePermissionListener() {
|
||||
@Override
|
||||
public void onPermissionGranted(PermissionGrantedResponse response) {
|
||||
startCameraCapture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionDenied(PermissionDeniedResponse response) {
|
||||
if (response.isPermanentlyDenied()) {
|
||||
DialogUtil.showAlertDialog(activity,
|
||||
activity.getString(R.string.storage_permission_title),
|
||||
activity.getString(R.string.read_storage_permission_rationale),
|
||||
activity.getString(R.string.navigation_item_settings),
|
||||
null,
|
||||
() -> PermissionUtils.askUserToManuallyEnablePermissionFromSettings(activity),
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
|
||||
DialogUtil.showAlertDialog(activity,
|
||||
activity.getString(R.string.storage_permission_title),
|
||||
activity.getString(R.string.read_storage_permission_rationale),
|
||||
activity.getString(android.R.string.ok),
|
||||
activity.getString(android.R.string.cancel),
|
||||
token::continuePermissionRequest,
|
||||
token::cancelPermissionRequest);
|
||||
}
|
||||
}).check();
|
||||
}
|
||||
}
|
||||
|
||||
private static void requestWritePermission(Context context, Intent intent, Uri uri) {
|
||||
|
||||
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent,
|
||||
|
|
@ -69,7 +165,7 @@ public class ContributionController {
|
|||
}
|
||||
}
|
||||
|
||||
public void startCameraCapture() {
|
||||
private void startCameraCapture() {
|
||||
|
||||
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
lastGeneratedCaptureUri = reGenerateImageCaptureUriInCache();
|
||||
|
|
@ -84,7 +180,7 @@ public class ContributionController {
|
|||
fragment.startActivityForResult(takePictureIntent, SELECT_FROM_CAMERA);
|
||||
}
|
||||
|
||||
public void startGalleryPick() {
|
||||
private void startGalleryPick() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
startMultipleGalleryPick();
|
||||
} else {
|
||||
|
|
@ -92,7 +188,7 @@ public class ContributionController {
|
|||
}
|
||||
}
|
||||
|
||||
public void startSingleGalleryPick() {
|
||||
private void startSingleGalleryPick() {
|
||||
//FIXME: Starts gallery (opens Google Photos)
|
||||
Intent pickImageIntent = new Intent(ACTION_GET_CONTENT);
|
||||
pickImageIntent.setType("image/*");
|
||||
|
|
@ -107,7 +203,7 @@ public class ContributionController {
|
|||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
public void startMultipleGalleryPick() {
|
||||
private void startMultipleGalleryPick() {
|
||||
Intent pickImageIntent = new Intent(ACTION_GET_CONTENT);
|
||||
pickImageIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||
pickImageIntent.setType("image/*");
|
||||
|
|
@ -120,7 +216,7 @@ public class ContributionController {
|
|||
fragment.startActivityForResult(pickImageIntent, PICK_IMAGE_MULTIPLE);
|
||||
}
|
||||
|
||||
public void handleImagesPicked(int requestCode, @Nullable ArrayList<Uri> uri) {
|
||||
void handleImagesPicked(int requestCode, @Nullable ArrayList<Uri> uri) {
|
||||
FragmentActivity activity = fragment.getActivity();
|
||||
Intent shareIntent = new Intent(activity, UploadActivity.class);
|
||||
shareIntent.setAction(ACTION_SEND_MULTIPLE);
|
||||
|
|
|
|||
|
|
@ -4,15 +4,12 @@ import android.content.ClipData;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
|
@ -26,7 +23,6 @@ import android.widget.ProgressBar;
|
|||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
|
@ -36,11 +32,8 @@ import butterknife.ButterKnife;
|
|||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.view.View.*;
|
||||
|
|
@ -96,7 +89,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (controller == null) {
|
||||
controller = new ContributionController(this);
|
||||
controller = new ContributionController(this, defaultPrefs);
|
||||
}
|
||||
controller.loadState(savedInstanceState);
|
||||
}
|
||||
|
|
@ -107,7 +100,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
if (controller != null) {
|
||||
controller.saveState(outState);
|
||||
} else {
|
||||
controller = new ContributionController(this);
|
||||
controller = new ContributionController(this, defaultPrefs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,88 +123,11 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
}
|
||||
|
||||
private void setListeners() {
|
||||
|
||||
fabPlus.setOnClickListener(view -> animateFAB(isFabOpen));
|
||||
fabCamera.setOnClickListener(view -> {
|
||||
boolean useExtStorage = defaultPrefs.getBoolean("useExternalStorage", true);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && useExtStorage) {
|
||||
// Here, thisActivity is the current activity
|
||||
if (ContextCompat.checkSelfPermission(getActivity(), WRITE_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
if (shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) {
|
||||
// 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(getParentFragment().getActivity())
|
||||
.setMessage(getString(R.string.write_storage_permission_rationale))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
getActivity().requestPermissions
|
||||
(new String[]{WRITE_EXTERNAL_STORAGE}, PermissionUtils.CAMERA_PERMISSION_FROM_CONTRIBUTION_LIST);
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
.show();
|
||||
} else {
|
||||
// No explanation needed, we can request the permission.
|
||||
requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE},
|
||||
3);
|
||||
// MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE is an
|
||||
// app-defined int constant. The callback method gets the
|
||||
// result of the request.
|
||||
}
|
||||
} else {
|
||||
controller.startCameraCapture();
|
||||
}
|
||||
} else {
|
||||
controller.startCameraCapture();
|
||||
}
|
||||
});
|
||||
|
||||
fabGallery.setOnClickListener(view -> {
|
||||
// Gallery crashes before reach ShareActivity screen so must implement permissions check here
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
|
||||
// Here, thisActivity is the current activity
|
||||
if (ContextCompat.checkSelfPermission(getActivity(), READ_EXTERNAL_STORAGE)
|
||||
!= PERMISSION_GRANTED) {
|
||||
|
||||
// Should we show an explanation?
|
||||
if (shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) {
|
||||
|
||||
// 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(getParentFragment().getActivity())
|
||||
.setMessage(getString(R.string.read_storage_permission_rationale))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
getActivity().requestPermissions
|
||||
(new String[]{READ_EXTERNAL_STORAGE}, PermissionUtils.GALLERY_PERMISSION_FROM_CONTRIBUTION_LIST);
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
.show();
|
||||
|
||||
} else {
|
||||
|
||||
// No explanation needed, we can request the permission.
|
||||
|
||||
requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 1);
|
||||
|
||||
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
|
||||
// app-defined int constant. The callback method gets the
|
||||
// result of the request.
|
||||
}
|
||||
} else {
|
||||
controller.startGalleryPick();
|
||||
}
|
||||
|
||||
} else {
|
||||
controller.startGalleryPick();
|
||||
}
|
||||
controller.initiateCameraPick(getActivity());
|
||||
});
|
||||
fabGallery.setOnClickListener(view -> controller.initiateGalleryPick(getActivity()));
|
||||
}
|
||||
|
||||
private void animateFAB(boolean isFabOpen) {
|
||||
|
|
@ -260,40 +176,6 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
Timber.d("onRequestPermissionsResult: req code = " + " perm = "
|
||||
+ Arrays.toString(permissions) + " grant =" + Arrays.toString(grantResults));
|
||||
|
||||
switch (requestCode) {
|
||||
// 1 = Storage allowed when gallery selected
|
||||
case 1: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
|
||||
Timber.d("Call controller.startGalleryPick()");
|
||||
controller.startGalleryPick();
|
||||
}
|
||||
}
|
||||
break;
|
||||
// 2 = Location allowed when 'nearby places' selected
|
||||
case 2: {
|
||||
// TODO: understand and fix
|
||||
/*if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
|
||||
Timber.d("Location permission granted");
|
||||
Intent nearbyIntent = new Intent(getActivity(), MainActivity.class);
|
||||
startActivity(nearbyIntent);
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
case 3: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Timber.d("Call controller.startCameraCapture()");
|
||||
controller.startCameraCapture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMultipleImages(int requestCode, Intent data) {
|
||||
if (getContext() == null) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -477,60 +477,6 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
|||
}
|
||||
return;
|
||||
}
|
||||
// Storage permission for gallery
|
||||
case PermissionUtils.GALLERY_PERMISSION_FROM_CONTRIBUTION_LIST: {
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// Storage permission given
|
||||
ContributionsListFragment contributionsListFragment =
|
||||
(ContributionsListFragment) contributionsActivityPagerAdapter
|
||||
.getItem(0).getChildFragmentManager()
|
||||
.findFragmentByTag(ContributionsFragment.CONTRIBUTION_LIST_FRAGMENT_TAG);
|
||||
contributionsListFragment.controller.startGalleryPick();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case PermissionUtils.CAMERA_PERMISSION_FROM_CONTRIBUTION_LIST: {
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// Storage permission given
|
||||
ContributionsListFragment contributionsListFragment =
|
||||
(ContributionsListFragment) contributionsActivityPagerAdapter
|
||||
.getItem(0).getChildFragmentManager()
|
||||
.findFragmentByTag(ContributionsFragment.CONTRIBUTION_LIST_FRAGMENT_TAG);
|
||||
contributionsListFragment.controller.startCameraCapture();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case PermissionUtils.CAMERA_PERMISSION_FROM_NEARBY_MAP: {
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// Storage permission given
|
||||
NearbyMapFragment nearbyMapFragment =
|
||||
((NearbyFragment) contributionsActivityPagerAdapter
|
||||
.getItem(1)).nearbyMapFragment;
|
||||
nearbyMapFragment.controller.startCameraCapture();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case PermissionUtils.GALLERY_PERMISSION_FROM_NEARBY_MAP: {
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// Storage permission given
|
||||
NearbyMapFragment nearbyMapFragment =
|
||||
((NearbyFragment) contributionsActivityPagerAdapter
|
||||
.getItem(1)).nearbyMapFragment;
|
||||
nearbyMapFragment.controller.startGalleryPick();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
package fr.free.nrw.commons.nearby;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.ContributionController;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
|
||||
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
/**
|
||||
* Initiates the uploads made from a Nearby Place, in both the list and map views.
|
||||
*/
|
||||
class DirectUpload {
|
||||
|
||||
private ContributionController controller;
|
||||
private Fragment fragment;
|
||||
|
||||
DirectUpload(Fragment fragment, ContributionController controller) {
|
||||
this.fragment = fragment;
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the upload if user selects the Gallery FAB.
|
||||
* The permission requests will be handled by the Fragments.
|
||||
* Do not use requestCode 1 as it will conflict with NearbyFragment's requestCodes.
|
||||
*/
|
||||
void initiateGalleryUpload() {
|
||||
// Only need to handle permissions for Marshmallow and above
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
return;
|
||||
}
|
||||
|
||||
Activity parentActivity = fragment.getActivity();
|
||||
if (parentActivity == null) {
|
||||
controller.startSingleGalleryPick();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have permission, go ahead
|
||||
if (ContextCompat.checkSelfPermission(parentActivity, READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {
|
||||
controller.startSingleGalleryPick();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't have permission, and we need to show the rationale, show the rationale
|
||||
if (fragment.shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) {
|
||||
new AlertDialog.Builder(parentActivity)
|
||||
.setMessage(parentActivity.getString(R.string.read_storage_permission_rationale))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
parentActivity.requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, PermissionUtils.GALLERY_PERMISSION_FROM_NEARBY_MAP);
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't have permission, and we don't need to show rationale just request permission
|
||||
parentActivity.requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, PermissionUtils.GALLERY_PERMISSION_FROM_NEARBY_MAP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the upload if user selects the Camera FAB.
|
||||
* The permission requests will be handled by the Fragments.
|
||||
* Do not use requestCode 1 as it will conflict with NearbyFragment's requestCodes.
|
||||
*/
|
||||
void initiateCameraUpload() {
|
||||
// Only need to handle permissions for Marshmallow and above
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
return;
|
||||
}
|
||||
|
||||
Activity parentActivity = fragment.getActivity();
|
||||
if (parentActivity == null) {
|
||||
controller.startCameraCapture();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have permission, go ahead
|
||||
if (ContextCompat.checkSelfPermission(parentActivity, WRITE_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {
|
||||
controller.startCameraCapture();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't have permission, and we need to show the rationale, show the rationale
|
||||
if (fragment.shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) {
|
||||
new AlertDialog.Builder(parentActivity)
|
||||
.setMessage(parentActivity.getString(R.string.write_storage_permission_rationale))
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
parentActivity.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, PermissionUtils.CAMERA_PERMISSION_FROM_NEARBY_MAP);
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't have permission, and we don't need to show rationale just request permission
|
||||
parentActivity.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, PermissionUtils.CAMERA_PERMISSION_FROM_NEARBY_MAP);
|
||||
}
|
||||
}
|
||||
|
|
@ -54,9 +54,8 @@ public class NearbyListFragment extends DaggerFragment {
|
|||
private ContributionController controller;
|
||||
|
||||
|
||||
@Inject
|
||||
@Named("direct_nearby_upload_prefs")
|
||||
SharedPreferences directPrefs;
|
||||
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
|
||||
@Inject @Named("default_preferences") SharedPreferences defaultPrefs;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
|
@ -79,7 +78,7 @@ public class NearbyListFragment extends DaggerFragment {
|
|||
recyclerView = view.findViewById(R.id.listView);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
||||
controller = new ContributionController(this);
|
||||
controller = new ContributionController(this, defaultPrefs);
|
||||
adapterFactory = new NearbyAdapterFactory(this, controller);
|
||||
return view;
|
||||
}
|
||||
|
|
@ -139,31 +138,6 @@ public class NearbyListFragment extends DaggerFragment {
|
|||
return placeList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults);
|
||||
|
||||
switch (requestCode) {
|
||||
// 4 = "Read external storage" allowed when gallery selected
|
||||
case 4: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
|
||||
Timber.d("Call controller.startGalleryPick()");
|
||||
controller.startGalleryPick();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 5 = "Write external storage" allowed when camera selected
|
||||
case 5: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Timber.d("Call controller.startCameraCapture()");
|
||||
controller.startCameraCapture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
private Animation fab_open;
|
||||
private Animation rotate_forward;
|
||||
public ContributionController controller;
|
||||
private DirectUpload directUpload;
|
||||
|
||||
private Place place;
|
||||
private Marker selected;
|
||||
|
|
@ -137,6 +136,9 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
@Named("prefs")
|
||||
SharedPreferences prefs;
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
SharedPreferences defaultPrefs;
|
||||
@Inject
|
||||
@Named("direct_nearby_upload_prefs")
|
||||
SharedPreferences directPrefs;
|
||||
@Inject
|
||||
|
|
@ -152,9 +154,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
super.onCreate(savedInstanceState);
|
||||
Timber.d("Nearby map fragment created");
|
||||
|
||||
controller = new ContributionController(this);
|
||||
directUpload = new DirectUpload(this, controller);
|
||||
|
||||
controller = new ContributionController(this, defaultPrefs);
|
||||
Bundle bundle = this.getArguments();
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Uri.class, new UriDeserializer())
|
||||
|
|
@ -862,7 +862,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
if (fabCamera.isShown()) {
|
||||
Timber.d("Camera button tapped. Place: %s", place.toString());
|
||||
storeSharedPrefs();
|
||||
directUpload.initiateCameraUpload();
|
||||
controller.initiateCameraPick(getActivity());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -870,7 +870,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
if (fabGallery.isShown()) {
|
||||
Timber.d("Gallery button tapped. Place: %s", place.toString());
|
||||
storeSharedPrefs();
|
||||
directUpload.initiateGalleryUpload();
|
||||
controller.initiateGalleryPick(getActivity());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -885,31 +885,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
editor.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults);
|
||||
|
||||
// Do not use requestCode 1 as it will conflict with NearbyFragment's requestCodes
|
||||
switch (requestCode) {
|
||||
// 4 = "Read external storage" allowed when gallery selected
|
||||
case 4: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
|
||||
Timber.d("Call controller.startGalleryPick()");
|
||||
controller.startGalleryPick();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 5 = "Write external storage" allowed when camera selected
|
||||
case 5: {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Timber.d("Call controller.startCameraCapture()");
|
||||
controller.startCameraCapture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ public class PlaceRenderer extends Renderer<Place> {
|
|||
BookmarkLocationsDao bookmarkLocationDao;
|
||||
@Inject @Named("prefs") SharedPreferences prefs;
|
||||
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
SharedPreferences defaultPrefs;
|
||||
|
||||
public PlaceRenderer(){
|
||||
openedItems = new ArrayList<>();
|
||||
|
|
@ -138,9 +141,8 @@ public class PlaceRenderer extends Renderer<Place> {
|
|||
.show();
|
||||
} else {
|
||||
Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
|
||||
DirectUpload directUpload = new DirectUpload(fragment, controller);
|
||||
storeSharedPrefs();
|
||||
directUpload.initiateCameraUpload();
|
||||
controller.initiateCameraPick(fragment.getActivity());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -159,9 +161,8 @@ public class PlaceRenderer extends Renderer<Place> {
|
|||
.show();
|
||||
}else {
|
||||
Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
|
||||
DirectUpload directUpload = new DirectUpload(fragment, controller);
|
||||
storeSharedPrefs();
|
||||
directUpload.initiateGalleryUpload();
|
||||
controller.initiateGalleryPick(fragment.getActivity());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -143,19 +143,23 @@ public class DialogUtil {
|
|||
builder.setTitle(title);
|
||||
builder.setMessage(message);
|
||||
|
||||
builder.setPositiveButton(positiveButtonText, (dialogInterface, i) -> {
|
||||
dialogInterface.dismiss();
|
||||
if (onPositiveBtnClick != null) {
|
||||
onPositiveBtnClick.run();
|
||||
}
|
||||
});
|
||||
if (!StringUtils.isNullOrWhiteSpace(positiveButtonText)) {
|
||||
builder.setPositiveButton(positiveButtonText, (dialogInterface, i) -> {
|
||||
dialogInterface.dismiss();
|
||||
if (onPositiveBtnClick != null) {
|
||||
onPositiveBtnClick.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
builder.setNegativeButton(negativeButtonText, (DialogInterface dialogInterface, int i) -> {
|
||||
dialogInterface.dismiss();
|
||||
if (onNegativeBtnClick != null) {
|
||||
onNegativeBtnClick.run();
|
||||
}
|
||||
});
|
||||
if (!StringUtils.isNullOrWhiteSpace(negativeButtonText)) {
|
||||
builder.setNegativeButton(negativeButtonText, (DialogInterface dialogInterface, int i) -> {
|
||||
dialogInterface.dismiss();
|
||||
if (onNegativeBtnClick != null) {
|
||||
onNegativeBtnClick.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
showSafely(activity, dialog);
|
||||
|
|
@ -179,13 +183,13 @@ public class DialogUtil {
|
|||
onPositiveBtnClick,
|
||||
onNegativeBtnClick,
|
||||
customView,
|
||||
false);
|
||||
cancelable);
|
||||
}
|
||||
|
||||
/*
|
||||
Shows alert dialog with custom view
|
||||
*/
|
||||
private static void showAlertDialog(Activity activity,
|
||||
public static void showAlertDialog(Activity activity,
|
||||
String title,
|
||||
String message,
|
||||
String positiveButtonText,
|
||||
|
|
|
|||
|
|
@ -12,11 +12,6 @@ import fr.free.nrw.commons.CommonsApplication;
|
|||
|
||||
public class PermissionUtils {
|
||||
|
||||
public static final int CAMERA_PERMISSION_FROM_CONTRIBUTION_LIST = 100;
|
||||
public static final int GALLERY_PERMISSION_FROM_CONTRIBUTION_LIST = 101;
|
||||
public static final int CAMERA_PERMISSION_FROM_NEARBY_MAP = 102;
|
||||
public static final int GALLERY_PERMISSION_FROM_NEARBY_MAP = 103;
|
||||
|
||||
/**
|
||||
* This method can be used by any activity which requires a permission which has been blocked(marked never ask again by the user)
|
||||
It open the app settings from where the user can manually give us the required permission.
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ import android.support.annotation.StringRes;
|
|||
import android.support.design.widget.Snackbar;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class ViewUtil {
|
||||
|
|
@ -85,14 +83,16 @@ public class ViewUtil {
|
|||
* A snack bar which has an action button which on click dismisses the snackbar and invokes the
|
||||
* listener passed
|
||||
*/
|
||||
public static void showDismissibleSnackBar(View view, int messageResourceId,
|
||||
int actionButtonResourceId, View.OnClickListener onClickListener) {
|
||||
public static void showDismissibleSnackBar(View view,
|
||||
int messageResourceId,
|
||||
int actionButtonResourceId,
|
||||
View.OnClickListener onClickListener) {
|
||||
if (view.getContext() == null) {
|
||||
return;
|
||||
}
|
||||
ExecutorUtils.uiExecutor().execute(() -> {
|
||||
Snackbar snackbar = Snackbar.make(view, view.getContext().getString(messageResourceId),
|
||||
Snackbar.LENGTH_INDEFINITE);
|
||||
Snackbar.LENGTH_INDEFINITE);
|
||||
snackbar.setAction(view.getContext().getString(actionButtonResourceId), v -> {
|
||||
snackbar.dismiss();
|
||||
onClickListener.onClick(v);
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@
|
|||
<string name="detail_description_empty">No description</string>
|
||||
<string name="detail_license_empty">Unknown license</string>
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
<string name="storage_permission_title">Requesting Storage Permission</string>
|
||||
<string name="read_storage_permission_rationale">Required permission: Read external storage. App cannot access your gallery without this.</string>
|
||||
<string name="write_storage_permission_rationale">Required permission: Write external storage. App cannot access your camera without this.</string>
|
||||
<string name="location_permission_rationale">Optional permission: Get current location for category suggestions</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue