mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Use image picker to pick images for upload (#2278)
* Use image picker to pick images for upload * Consolidate storage permissions in Upload activity * With proper request codes for image upload * Use constants for upload limits * Check for request code while handling requests * Let fragment initiate the camera/gallery instead of activity * Delete unused external storage utils
This commit is contained in:
parent
b05b302e65
commit
164ef9bcac
17 changed files with 339 additions and 637 deletions
|
|
@ -39,6 +39,7 @@ dependencies {
|
|||
implementation files('libs/simplemagic-1.9.jar')
|
||||
implementation "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION"
|
||||
kapt "com.jakewharton:butterknife-compiler:$BUTTERKNIFE_VERSION"
|
||||
implementation 'com.github.esafirm.android-image-picker:imagepicker:1.13.1'
|
||||
|
||||
// Logging
|
||||
implementation 'ch.acra:acra:4.9.2'
|
||||
|
|
|
|||
|
|
@ -117,8 +117,6 @@
|
|||
android:name=".bookmarks.BookmarksActivity"
|
||||
android:label="@string/title_activity_bookmarks" />
|
||||
|
||||
<activity android:name="com.github.pedrovgs.lynx.LynxActivity"/>
|
||||
|
||||
<service android:name=".upload.UploadService" />
|
||||
<service
|
||||
android:name=".auth.WikiAccountAuthenticatorService"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package fr.free.nrw.commons.bookmarks.locations;
|
|||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
|
@ -15,6 +14,8 @@ import android.widget.ProgressBar;
|
|||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.esafirm.imagepicker.features.ImagePicker;
|
||||
import com.esafirm.imagepicker.model.Image;
|
||||
import com.pedrogomez.renderers.RVRendererAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -30,12 +31,8 @@ import fr.free.nrw.commons.R;
|
|||
import fr.free.nrw.commons.contributions.ContributionController;
|
||||
import fr.free.nrw.commons.nearby.NearbyAdapterFactory;
|
||||
import fr.free.nrw.commons.nearby.Place;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ENTITY_ID_PREF;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ITEM_LOCATION;
|
||||
import fr.free.nrw.commons.utils.ImageUtils;
|
||||
import fr.free.nrw.commons.utils.IntentUtils;
|
||||
|
||||
public class BookmarkLocationsFragment extends DaggerFragment {
|
||||
|
||||
|
|
@ -44,12 +41,11 @@ public class BookmarkLocationsFragment extends DaggerFragment {
|
|||
@BindView(R.id.listView) RecyclerView recyclerView;
|
||||
@BindView(R.id.parentLayout) RelativeLayout parentLayout;
|
||||
|
||||
@Inject
|
||||
BookmarkLocationsController controller;
|
||||
@Inject BookmarkLocationsController controller;
|
||||
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
|
||||
@Inject @Named("default_preferences") SharedPreferences defaultPrefs;
|
||||
private NearbyAdapterFactory adapterFactory;
|
||||
private ContributionController contributionController;
|
||||
@Inject ContributionController contributionController;
|
||||
|
||||
/**
|
||||
* Create an instance of the fragment with the right bundle parameters
|
||||
|
|
@ -67,7 +63,6 @@ public class BookmarkLocationsFragment extends DaggerFragment {
|
|||
) {
|
||||
View v = inflater.inflate(R.layout.fragment_bookmarks_locations, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
contributionController = new ContributionController(this, defaultPrefs);
|
||||
adapterFactory = new NearbyAdapterFactory(this, contributionController);
|
||||
return v;
|
||||
}
|
||||
|
|
@ -103,23 +98,12 @@ public class BookmarkLocationsFragment extends DaggerFragment {
|
|||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode == RESULT_OK) {
|
||||
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||
requestCode, resultCode, data);
|
||||
String wikidataEntityId = directPrefs.getString(WIKIDATA_ENTITY_ID_PREF, null);
|
||||
String wikidataItemLocation = directPrefs.getString(WIKIDATA_ITEM_LOCATION, null);
|
||||
if (requestCode == ContributionController.SELECT_FROM_CAMERA) {
|
||||
// If coming from camera, pass null as uri. Because camera photos get saved to a
|
||||
// fixed directory
|
||||
contributionController.handleImagePicked(requestCode, null, true, wikidataEntityId, wikidataItemLocation);
|
||||
} else {
|
||||
contributionController.handleImagePicked(requestCode, data.getData(), true, wikidataEntityId, wikidataItemLocation);
|
||||
}
|
||||
if (IntentUtils.shouldBookmarksHandle(requestCode, resultCode, data)) {
|
||||
List<Image> images = ImagePicker.getImages(data);
|
||||
Intent shareIntent = contributionController.handleImagesPicked(ImageUtils.getUriListFromImages(images), requestCode);
|
||||
startActivity(shareIntent);
|
||||
} else {
|
||||
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||
requestCode, resultCode, data);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,285 +1,151 @@
|
|||
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;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
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 com.esafirm.imagepicker.features.ImagePicker;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
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 fr.free.nrw.commons.utils.StringUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static android.content.Intent.ACTION_GET_CONTENT;
|
||||
import static android.content.Intent.ACTION_SEND;
|
||||
import static android.content.Intent.ACTION_SEND_MULTIPLE;
|
||||
import static android.content.Intent.EXTRA_STREAM;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.SOURCE_CAMERA;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.SOURCE_EXTERNAL;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.SOURCE_GALLERY;
|
||||
import static fr.free.nrw.commons.upload.UploadService.EXTRA_SOURCE;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.IS_DIRECT_UPLOAD;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ENTITY_ID_PREF;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ITEM_LOCATION;
|
||||
|
||||
@Singleton
|
||||
public class ContributionController {
|
||||
|
||||
static final int SELECT_FROM_GALLERY = 1;
|
||||
public static final int SELECT_FROM_CAMERA = 2;
|
||||
static final int PICK_IMAGE_MULTIPLE = 3;
|
||||
//request codes
|
||||
public static final int CAMERA_UPLOAD_REQUEST_CODE = 10011;
|
||||
public static final int GALLERY_UPLOAD_REQUEST_CODE = 10012;
|
||||
public static final int NEARBY_CAMERA_UPLOAD_REQUEST_CODE = 10013;
|
||||
public static final int NEARBY_GALLERY_UPLOAD_REQUEST_CODE = 10014;
|
||||
public static final int BOOKMARK_CAMERA_UPLOAD_REQUEST_CODE = 10015;
|
||||
public static final int BOOKMARK_GALLERY_UPLOAD_REQUEST_CODE = 10016;
|
||||
|
||||
private Fragment fragment;
|
||||
private SharedPreferences defaultPrefs;
|
||||
//upload limits
|
||||
public static final int MULTIPLE_UPLOAD_IMAGE_LIMIT = 5;
|
||||
public static final int NEARBY_UPLOAD_IMAGE_LIMIT = 1;
|
||||
|
||||
public ContributionController(Fragment fragment, SharedPreferences defaultSharedPrefs) {
|
||||
this.fragment = fragment;
|
||||
private final Context context;
|
||||
private final SharedPreferences defaultPrefs;
|
||||
private final SharedPreferences directPrefs;
|
||||
|
||||
@Inject
|
||||
public ContributionController(Context context,
|
||||
@Named("default_preferences") SharedPreferences defaultSharedPrefs,
|
||||
@Named("direct_nearby_upload_prefs") SharedPreferences directPrefs) {
|
||||
this.context = context;
|
||||
this.defaultPrefs = defaultSharedPrefs;
|
||||
this.directPrefs = directPrefs;
|
||||
}
|
||||
|
||||
// See http://stackoverflow.com/a/5054673/17865 for why this is done
|
||||
private Uri lastGeneratedCaptureUri;
|
||||
|
||||
private Uri reGenerateImageCaptureUriInCache() {
|
||||
File photoFile = new File(fragment.getContext().getCacheDir() + "/images",
|
||||
new Date().getTime() + ".jpg");
|
||||
photoFile.getParentFile().mkdirs();
|
||||
Context applicationContext = fragment.getActivity().getApplicationContext();
|
||||
return FileProvider.getUriForFile(
|
||||
fragment.getContext(),
|
||||
applicationContext.getPackageName() + ".provider",
|
||||
photoFile);
|
||||
}
|
||||
|
||||
public void initiateCameraPick(Activity activity) {
|
||||
public void initiateCameraPick(Fragment fragment,
|
||||
int requestCode) {
|
||||
boolean useExtStorage = defaultPrefs.getBoolean("useExternalStorage", true);
|
||||
if (!useExtStorage) {
|
||||
startCameraCapture();
|
||||
initiateCameraUpload(fragment, requestCode);
|
||||
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();
|
||||
PermissionUtils.checkPermissionsAndPerformAction(fragment.getActivity(),
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
() -> initiateCameraUpload(fragment, requestCode),
|
||||
R.string.storage_permission_title,
|
||||
R.string.write_storage_permission_rationale);
|
||||
}
|
||||
|
||||
public void initiateGalleryPick(Activity activity) {
|
||||
public void initiateGalleryPick(Fragment fragment,
|
||||
int imageLimit,
|
||||
int requestCode) {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
startGalleryPick();
|
||||
initiateGalleryUpload(fragment, imageLimit, requestCode);
|
||||
} else {
|
||||
Dexter.withActivity(activity)
|
||||
.withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.withListener(new BasePermissionListener() {
|
||||
@Override
|
||||
public void onPermissionGranted(PermissionGrantedResponse response) {
|
||||
startGalleryPick();
|
||||
}
|
||||
|
||||
@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();
|
||||
PermissionUtils.checkPermissionsAndPerformAction(fragment.getActivity(),
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
() -> initiateGalleryUpload(fragment, imageLimit, requestCode),
|
||||
R.string.storage_permission_title,
|
||||
R.string.read_storage_permission_rationale);
|
||||
}
|
||||
}
|
||||
|
||||
private static void requestWritePermission(Context context, Intent intent, Uri uri) {
|
||||
private void initiateGalleryUpload(Fragment fragment,
|
||||
int imageLimit,
|
||||
int requestCode) {
|
||||
ImagePicker imagePicker = ImagePicker.ImagePickerWithFragment
|
||||
.create(fragment)
|
||||
.showCamera(false)
|
||||
.folderMode(true)
|
||||
.includeVideo(false)
|
||||
.enableLog(true);
|
||||
|
||||
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY);
|
||||
for (ResolveInfo resolveInfo : resInfoList) {
|
||||
String packageName = resolveInfo.activityInfo.packageName;
|
||||
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
private void startCameraCapture() {
|
||||
|
||||
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
lastGeneratedCaptureUri = reGenerateImageCaptureUriInCache();
|
||||
|
||||
// Intent.setFlags doesn't work for API level <20
|
||||
requestWritePermission(fragment.getContext(), takePictureIntent, lastGeneratedCaptureUri);
|
||||
|
||||
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, lastGeneratedCaptureUri);
|
||||
if (!fragment.isAdded()) {
|
||||
return;
|
||||
}
|
||||
fragment.startActivityForResult(takePictureIntent, SELECT_FROM_CAMERA);
|
||||
}
|
||||
|
||||
private void startGalleryPick() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
startMultipleGalleryPick();
|
||||
if (imageLimit > 1) {
|
||||
imagePicker.multi().limit(imageLimit).start(requestCode);
|
||||
} else {
|
||||
startSingleGalleryPick();
|
||||
imagePicker.single().start(requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void startSingleGalleryPick() {
|
||||
//FIXME: Starts gallery (opens Google Photos)
|
||||
Intent pickImageIntent = new Intent(ACTION_GET_CONTENT);
|
||||
pickImageIntent.setType("image/*");
|
||||
// See https://stackoverflow.com/questions/22366596/android-illegalstateexception-fragment-not-attached-to-activity-webview
|
||||
if (!fragment.isAdded()) {
|
||||
Timber.d("Fragment is not added, startActivityForResult cannot be called");
|
||||
return;
|
||||
}
|
||||
Timber.d("startSingleGalleryPick() called with pickImageIntent");
|
||||
|
||||
fragment.startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY);
|
||||
private void initiateCameraUpload(Fragment fragment, int requestCode) {
|
||||
ImagePicker.cameraOnly()
|
||||
.start(fragment, requestCode);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
private void startMultipleGalleryPick() {
|
||||
Intent pickImageIntent = new Intent(ACTION_GET_CONTENT);
|
||||
pickImageIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||
pickImageIntent.setType("image/*");
|
||||
if (!fragment.isAdded()) {
|
||||
Timber.d("Fragment is not added, startActivityForResult cannot be called");
|
||||
return;
|
||||
}
|
||||
Timber.d("startMultipleGalleryPick() called with pickImageIntent");
|
||||
|
||||
fragment.startActivityForResult(pickImageIntent, PICK_IMAGE_MULTIPLE);
|
||||
}
|
||||
|
||||
void handleImagesPicked(int requestCode, @Nullable ArrayList<Uri> uri) {
|
||||
FragmentActivity activity = fragment.getActivity();
|
||||
Intent shareIntent = new Intent(activity, UploadActivity.class);
|
||||
public Intent handleImagesPicked(ArrayList<Uri> uriList, int requestCode) {
|
||||
Intent shareIntent = new Intent(context, UploadActivity.class);
|
||||
shareIntent.setAction(ACTION_SEND_MULTIPLE);
|
||||
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_GALLERY);
|
||||
shareIntent.putExtra(EXTRA_STREAM, uri);
|
||||
shareIntent.putExtra(EXTRA_SOURCE, getSourceFromRequestCode(requestCode));
|
||||
shareIntent.putExtra(EXTRA_STREAM, uriList);
|
||||
shareIntent.setType("image/jpeg");
|
||||
if (activity != null) {
|
||||
activity.startActivity(shareIntent);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleImagePicked(int requestCode, @Nullable Uri uri, boolean isDirectUpload, String wikiDataEntityId, String wikidateItemLocation) {
|
||||
FragmentActivity activity = fragment.getActivity();
|
||||
Timber.d("handleImagePicked() called with onActivityResult(). Boolean isDirectUpload: " + isDirectUpload + "String wikiDataEntityId: " + wikiDataEntityId);
|
||||
Intent shareIntent = new Intent(activity, UploadActivity.class);
|
||||
shareIntent.setAction(ACTION_SEND);
|
||||
switch (requestCode) {
|
||||
case SELECT_FROM_GALLERY:
|
||||
//Handles image picked from gallery
|
||||
Uri imageData = uri;
|
||||
shareIntent.setType(activity.getContentResolver().getType(imageData));
|
||||
shareIntent.putExtra(EXTRA_STREAM, imageData);
|
||||
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_GALLERY);
|
||||
break;
|
||||
case SELECT_FROM_CAMERA:
|
||||
//FIXME: Find out appropriate mime type
|
||||
// AFAIK this is the right type for a JPEG image
|
||||
// https://developer.android.com/training/sharing/send.html#send-binary-content
|
||||
shareIntent.setType("image/jpeg");
|
||||
shareIntent.putExtra(EXTRA_STREAM, lastGeneratedCaptureUri);
|
||||
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_CAMERA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
boolean isDirectUpload = directPrefs.getBoolean(IS_DIRECT_UPLOAD, false);
|
||||
|
||||
Timber.i("Image selected");
|
||||
shareIntent.putExtra("isDirectUpload", isDirectUpload);
|
||||
Timber.d("Put extras into image intent, isDirectUpload is " + isDirectUpload);
|
||||
|
||||
try {
|
||||
if (wikiDataEntityId != null && !wikiDataEntityId.equals("")) {
|
||||
shareIntent.putExtra(WIKIDATA_ENTITY_ID_PREF, wikiDataEntityId);
|
||||
shareIntent.putExtra(WIKIDATA_ITEM_LOCATION, wikidateItemLocation);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Timber.e(e, "Security Exception");
|
||||
String wikiDataEntityId = directPrefs.getString(WIKIDATA_ENTITY_ID_PREF, null);
|
||||
String wikiDataItemLocation = directPrefs.getString(WIKIDATA_ITEM_LOCATION, null);
|
||||
|
||||
if (!StringUtils.isNullOrWhiteSpace(wikiDataEntityId)) {
|
||||
shareIntent.putExtra(WIKIDATA_ENTITY_ID_PREF, wikiDataEntityId);
|
||||
shareIntent.putExtra(WIKIDATA_ITEM_LOCATION, wikiDataItemLocation);
|
||||
}
|
||||
|
||||
if (activity != null) {
|
||||
activity.startActivity(shareIntent);
|
||||
}
|
||||
return shareIntent;
|
||||
}
|
||||
|
||||
void saveState(Bundle outState) {
|
||||
if (outState != null) {
|
||||
outState.putParcelable("lastGeneratedCaptureURI", lastGeneratedCaptureUri);
|
||||
private String getSourceFromRequestCode(int requestCode) {
|
||||
switch (requestCode) {
|
||||
case CAMERA_UPLOAD_REQUEST_CODE:
|
||||
case NEARBY_CAMERA_UPLOAD_REQUEST_CODE:
|
||||
case BOOKMARK_CAMERA_UPLOAD_REQUEST_CODE:
|
||||
return SOURCE_CAMERA;
|
||||
case GALLERY_UPLOAD_REQUEST_CODE:
|
||||
case NEARBY_GALLERY_UPLOAD_REQUEST_CODE:
|
||||
case BOOKMARK_GALLERY_UPLOAD_REQUEST_CODE:
|
||||
return SOURCE_GALLERY;
|
||||
}
|
||||
}
|
||||
|
||||
void loadState(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
lastGeneratedCaptureUri = savedInstanceState.getParcelable("lastGeneratedCaptureURI");
|
||||
}
|
||||
return SOURCE_EXTERNAL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,11 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
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.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -22,7 +17,10 @@ import android.widget.ListAdapter;
|
|||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import com.esafirm.imagepicker.features.ImagePicker;
|
||||
import com.esafirm.imagepicker.model.Image;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
|
@ -32,12 +30,14 @@ import butterknife.ButterKnife;
|
|||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||
import fr.free.nrw.commons.utils.ConfigUtils;
|
||||
import timber.log.Timber;
|
||||
import fr.free.nrw.commons.utils.ImageUtils;
|
||||
import fr.free.nrw.commons.utils.IntentUtils;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
import static android.view.View.*;
|
||||
import static android.view.View.GONE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.SELECT_FROM_GALLERY;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.CAMERA_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.GALLERY_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.MULTIPLE_UPLOAD_IMAGE_LIMIT;
|
||||
|
||||
/**
|
||||
* Created by root on 01.06.2018.
|
||||
|
|
@ -60,9 +60,9 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
@BindView(R.id.noDataYet)
|
||||
TextView noDataYet;
|
||||
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
SharedPreferences defaultPrefs;
|
||||
@Inject @Named("default_preferences") SharedPreferences defaultPrefs;
|
||||
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
|
||||
@Inject ContributionController controller;
|
||||
|
||||
private Animation fab_close;
|
||||
private Animation fab_open;
|
||||
|
|
@ -71,7 +71,6 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
|
||||
|
||||
private boolean isFabOpen = false;
|
||||
public ContributionController controller;
|
||||
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_contributions_list, container, false);
|
||||
|
|
@ -84,25 +83,6 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (controller == null) {
|
||||
controller = new ContributionController(this, defaultPrefs);
|
||||
}
|
||||
controller.loadState(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (controller != null) {
|
||||
controller.saveState(outState);
|
||||
} else {
|
||||
controller = new ContributionController(this, defaultPrefs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
|
@ -123,10 +103,8 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
|
||||
private void setListeners() {
|
||||
fabPlus.setOnClickListener(view -> animateFAB(isFabOpen));
|
||||
fabCamera.setOnClickListener(view -> {
|
||||
controller.initiateCameraPick(getActivity());
|
||||
});
|
||||
fabGallery.setOnClickListener(view -> controller.initiateGalleryPick(getActivity()));
|
||||
fabCamera.setOnClickListener(view -> controller.initiateCameraPick(this, CAMERA_UPLOAD_REQUEST_CODE));
|
||||
fabGallery.setOnClickListener(view -> controller.initiateGalleryPick(this, MULTIPLE_UPLOAD_IMAGE_LIMIT, GALLERY_UPLOAD_REQUEST_CODE));
|
||||
}
|
||||
|
||||
private void animateFAB(boolean isFabOpen) {
|
||||
|
|
@ -156,44 +134,14 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
|||
parentFragment.waitForContributionsListFragment.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||
requestCode, resultCode, data);
|
||||
if (requestCode == ContributionController.SELECT_FROM_CAMERA) {
|
||||
// If coming from camera, pass null as uri. Because camera photos get saved to a
|
||||
// fixed directory
|
||||
controller.handleImagePicked(requestCode, null, false, null, null);
|
||||
} else if (requestCode == ContributionController.PICK_IMAGE_MULTIPLE) {
|
||||
handleMultipleImages(requestCode, data);
|
||||
} else if (requestCode == ContributionController.SELECT_FROM_GALLERY){
|
||||
controller.handleImagePicked(requestCode, data.getData(), false, null, null);
|
||||
}
|
||||
if (IntentUtils.shouldContributionsListHandle(requestCode, resultCode, data)) {
|
||||
List<Image> images = ImagePicker.getImages(data);
|
||||
Intent shareIntent = controller.handleImagesPicked(ImageUtils.getUriListFromImages(images), requestCode);
|
||||
startActivity(shareIntent);
|
||||
} else {
|
||||
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||
requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMultipleImages(int requestCode, Intent data) {
|
||||
if (getContext() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
|
||||
&& data.getClipData() != null) {
|
||||
ClipData mClipData = data.getClipData();
|
||||
ArrayList<Uri> mArrayUri = new ArrayList<>();
|
||||
for (int i = 0; i < mClipData.getItemCount(); i++) {
|
||||
|
||||
ClipData.Item item = mClipData.getItemAt(i);
|
||||
Uri uri = item.getUri();
|
||||
mArrayUri.add(uri);
|
||||
}
|
||||
Log.v("LOG_TAG", "Selected Images" + mArrayUri.size());
|
||||
controller.handleImagesPicked(requestCode, mArrayUri);
|
||||
} else if(data.getData() != null) {
|
||||
controller.handleImagePicked(SELECT_FROM_GALLERY, data.getData(), false, null, null);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@ package fr.free.nrw.commons.nearby;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.esafirm.imagepicker.features.ImagePicker;
|
||||
import com.esafirm.imagepicker.model.Image;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
|
@ -30,13 +30,11 @@ import dagger.android.support.DaggerFragment;
|
|||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.ContributionController;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.utils.ImageUtils;
|
||||
import fr.free.nrw.commons.utils.UriDeserializer;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ENTITY_ID_PREF;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ITEM_LOCATION;
|
||||
import static fr.free.nrw.commons.utils.IntentUtils.shouldNearbyHandle;
|
||||
|
||||
public class NearbyListFragment extends DaggerFragment {
|
||||
private Bundle bundleForUpdates; // Carry information from activity about changed nearby places and current location
|
||||
|
|
@ -51,9 +49,8 @@ public class NearbyListFragment extends DaggerFragment {
|
|||
|
||||
private NearbyAdapterFactory adapterFactory;
|
||||
private RecyclerView recyclerView;
|
||||
private ContributionController controller;
|
||||
|
||||
|
||||
@Inject ContributionController controller;
|
||||
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
|
||||
@Inject @Named("default_preferences") SharedPreferences defaultPrefs;
|
||||
|
||||
|
|
@ -77,8 +74,6 @@ public class NearbyListFragment extends DaggerFragment {
|
|||
View view = inflater.inflate(R.layout.fragment_nearby_list, container, false);
|
||||
recyclerView = view.findViewById(R.id.listView);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
||||
controller = new ContributionController(this, defaultPrefs);
|
||||
adapterFactory = new NearbyAdapterFactory(this, controller);
|
||||
return view;
|
||||
}
|
||||
|
|
@ -140,23 +135,12 @@ public class NearbyListFragment extends DaggerFragment {
|
|||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode == RESULT_OK) {
|
||||
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||
requestCode, resultCode, data);
|
||||
String wikidataEntityId = directPrefs.getString(WIKIDATA_ENTITY_ID_PREF, null);
|
||||
String wikidataItemLocation = directPrefs.getString(WIKIDATA_ITEM_LOCATION, null);
|
||||
if (requestCode == ContributionController.SELECT_FROM_CAMERA) {
|
||||
// If coming from camera, pass null as uri. Because camera photos get saved to a
|
||||
// fixed directory
|
||||
controller.handleImagePicked(requestCode, null, true, wikidataEntityId, wikidataItemLocation);
|
||||
} else {
|
||||
controller.handleImagePicked(requestCode, data.getData(), true, wikidataEntityId, wikidataItemLocation);
|
||||
}
|
||||
if (shouldNearbyHandle(requestCode, resultCode, data)) {
|
||||
List<Image> images = ImagePicker.getImages(data);
|
||||
Intent shareIntent = controller.handleImagesPicked(ImageUtils.getUriListFromImages(images), requestCode);
|
||||
startActivity(shareIntent);
|
||||
} else {
|
||||
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||
requestCode, resultCode, data);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import android.animation.TypeEvaluator;
|
|||
import android.animation.ValueAnimator;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
|
@ -28,6 +27,8 @@ import android.widget.LinearLayout;
|
|||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.esafirm.imagepicker.features.ImagePicker;
|
||||
import com.esafirm.imagepicker.model.Image;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
|
@ -44,7 +45,6 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
|
|||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -60,14 +60,18 @@ import fr.free.nrw.commons.Utils;
|
|||
import fr.free.nrw.commons.auth.LoginActivity;
|
||||
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
|
||||
import fr.free.nrw.commons.contributions.ContributionController;
|
||||
import fr.free.nrw.commons.utils.ImageUtils;
|
||||
import fr.free.nrw.commons.utils.IntentUtils;
|
||||
import fr.free.nrw.commons.utils.LocationUtils;
|
||||
import fr.free.nrw.commons.utils.PlaceUtils;
|
||||
import fr.free.nrw.commons.utils.UriDeserializer;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_CAMERA_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_GALLERY_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_UPLOAD_IMAGE_LIMIT;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.IS_DIRECT_UPLOAD;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ENTITY_ID_PREF;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ITEM_LOCATION;
|
||||
|
||||
|
|
@ -111,7 +115,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
private Animation fab_close;
|
||||
private Animation fab_open;
|
||||
private Animation rotate_forward;
|
||||
public ContributionController controller;
|
||||
|
||||
private Place place;
|
||||
private Marker selected;
|
||||
|
|
@ -132,17 +135,11 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
private Bundle bundleForUpdates;// Carry information from activity about changed nearby places and current location
|
||||
private boolean searchedAroundCurrentLocation = true;
|
||||
|
||||
@Inject
|
||||
@Named("prefs")
|
||||
SharedPreferences prefs;
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
SharedPreferences defaultPrefs;
|
||||
@Inject
|
||||
@Named("direct_nearby_upload_prefs")
|
||||
SharedPreferences directPrefs;
|
||||
@Inject
|
||||
BookmarkLocationsDao bookmarkLocationDao;
|
||||
@Inject ContributionController controller;
|
||||
@Inject @Named("prefs") SharedPreferences prefs;
|
||||
@Inject @Named("default_preferences") SharedPreferences defaultPrefs;
|
||||
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
|
||||
@Inject BookmarkLocationsDao bookmarkLocationDao;
|
||||
|
||||
private static final double ZOOM_LEVEL = 14f;
|
||||
|
||||
|
|
@ -154,7 +151,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
super.onCreate(savedInstanceState);
|
||||
Timber.d("Nearby map fragment created");
|
||||
|
||||
controller = new ContributionController(this, defaultPrefs);
|
||||
Bundle bundle = this.getArguments();
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Uri.class, new UriDeserializer())
|
||||
|
|
@ -874,7 +870,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
if (fabCamera.isShown()) {
|
||||
Timber.d("Camera button tapped. Place: %s", place.toString());
|
||||
storeSharedPrefs();
|
||||
controller.initiateCameraPick(getActivity());
|
||||
controller.initiateCameraPick(this, NEARBY_CAMERA_UPLOAD_REQUEST_CODE);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -882,7 +878,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
if (fabGallery.isShown()) {
|
||||
Timber.d("Gallery button tapped. Place: %s", place.toString());
|
||||
storeSharedPrefs();
|
||||
controller.initiateGalleryPick(getActivity());
|
||||
controller.initiateGalleryPick(this, NEARBY_UPLOAD_IMAGE_LIMIT, NEARBY_GALLERY_UPLOAD_REQUEST_CODE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -894,29 +890,18 @@ public class NearbyMapFragment extends DaggerFragment {
|
|||
editor.putString("Category", place.getCategory());
|
||||
editor.putString(WIKIDATA_ENTITY_ID_PREF, place.getWikiDataEntityId());
|
||||
editor.putString(WIKIDATA_ITEM_LOCATION, PlaceUtils.latLangToString(place.location));
|
||||
editor.putBoolean(IS_DIRECT_UPLOAD, true);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
|
||||
if (resultCode == RESULT_OK) {
|
||||
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||
requestCode, resultCode, data);
|
||||
String wikidataEntityId = directPrefs.getString(WIKIDATA_ENTITY_ID_PREF, null);
|
||||
String wikidataItemLocation = directPrefs.getString(WIKIDATA_ITEM_LOCATION, null);
|
||||
if (requestCode == ContributionController.SELECT_FROM_CAMERA) {
|
||||
// If coming from camera, pass null as uri. Because camera photos get saved to a
|
||||
// fixed directory
|
||||
controller.handleImagePicked(requestCode, null, true, wikidataEntityId, wikidataItemLocation);
|
||||
} else {
|
||||
controller.handleImagePicked(requestCode, data.getData(), true, wikidataEntityId, wikidataItemLocation);
|
||||
}
|
||||
if (IntentUtils.shouldNearbyHandle(requestCode, resultCode, data)) {
|
||||
List<Image> images = ImagePicker.getImages(data);
|
||||
Intent shareIntent = controller.handleImagesPicked(ImageUtils.getUriListFromImages(images), requestCode);
|
||||
startActivity(shareIntent);
|
||||
} else {
|
||||
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||
requestCode, resultCode, data);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@ import fr.free.nrw.commons.di.ApplicationlessInjection;
|
|||
import fr.free.nrw.commons.utils.PlaceUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_CAMERA_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_GALLERY_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_UPLOAD_IMAGE_LIMIT;
|
||||
import static fr.free.nrw.commons.theme.NavigationBaseActivity.startActivityWithFlags;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.IS_DIRECT_UPLOAD;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ENTITY_ID_PREF;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ITEM_LOCATION;
|
||||
|
||||
|
|
@ -142,7 +146,7 @@ public class PlaceRenderer extends Renderer<Place> {
|
|||
} else {
|
||||
Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
|
||||
storeSharedPrefs();
|
||||
controller.initiateCameraPick(fragment.getActivity());
|
||||
controller.initiateCameraPick(fragment, NEARBY_CAMERA_UPLOAD_REQUEST_CODE);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -162,7 +166,7 @@ public class PlaceRenderer extends Renderer<Place> {
|
|||
}else {
|
||||
Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
|
||||
storeSharedPrefs();
|
||||
controller.initiateGalleryPick(fragment.getActivity());
|
||||
controller.initiateGalleryPick(fragment, NEARBY_UPLOAD_IMAGE_LIMIT, NEARBY_GALLERY_UPLOAD_REQUEST_CODE);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -197,6 +201,7 @@ public class PlaceRenderer extends Renderer<Place> {
|
|||
editor.putString("Category", place.getCategory());
|
||||
editor.putString(WIKIDATA_ENTITY_ID_PREF, place.getWikiDataEntityId());
|
||||
editor.putString(WIKIDATA_ITEM_LOCATION, PlaceUtils.latLangToString(place.location));
|
||||
editor.putBoolean(IS_DIRECT_UPLOAD, true);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,153 +0,0 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.karumi.dexter.Dexter;
|
||||
import com.karumi.dexter.DexterBuilder;
|
||||
import com.karumi.dexter.listener.PermissionDeniedResponse;
|
||||
import com.karumi.dexter.listener.PermissionGrantedResponse;
|
||||
import com.karumi.dexter.listener.single.BasePermissionListener;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.utils.DialogUtil;
|
||||
import fr.free.nrw.commons.utils.ExternalStorageUtils;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.subjects.CompletableSubject;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class DexterPermissionObtainer {
|
||||
private final String requestedPermission;
|
||||
private android.app.AlertDialog storagePermissionInfoDialog;
|
||||
private DexterBuilder dexterStoragePermissionBuilder;
|
||||
|
||||
private PermissionDeniedResponse permissionDeniedResponse;
|
||||
|
||||
private boolean storagePromptInProgress;
|
||||
|
||||
private final String rationaleTitle;
|
||||
private final String rationaleText;
|
||||
|
||||
private Activity activity;
|
||||
|
||||
private CompletableSubject storagePromptObservable;
|
||||
|
||||
/**
|
||||
* @param activity The activity that is requesting the permission
|
||||
* @param requestedPermission The permission being requested in the form of Manifest.permission.*
|
||||
* @param rationaleTitle The title of the rationale dialog
|
||||
* @param rationaleText The text inside the rationale dialog
|
||||
*/
|
||||
DexterPermissionObtainer(Activity activity, String requestedPermission, String rationaleTitle, String rationaleText) {
|
||||
this.activity = activity;
|
||||
this.rationaleTitle = rationaleTitle;
|
||||
this.rationaleText = rationaleText;
|
||||
this.requestedPermission = requestedPermission;
|
||||
this.storagePromptObservable = CompletableSubject.create();
|
||||
initPermissionsRationaleDialog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if storage permissions are obtained, prompts the users to grant storage permissions if necessary.
|
||||
* When storage permission is present, onPermissionObtained is called.
|
||||
*/
|
||||
Completable confirmStoragePermissions() {
|
||||
if (ExternalStorageUtils.isStoragePermissionGranted(activity)) {
|
||||
Timber.i("Storage permissions already granted.");
|
||||
storagePromptObservable.onComplete();
|
||||
} else if (!storagePromptInProgress) {
|
||||
if (storagePromptObservable.hasComplete()) {
|
||||
storagePromptObservable = CompletableSubject.create();
|
||||
}
|
||||
//If permission is not there, ask for it
|
||||
storagePromptInProgress = true;
|
||||
askDexterToHandleExternalStoragePermission();
|
||||
}
|
||||
return storagePromptObservable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* To be called when the user returns to the original activity after manually enabling storage permissions.
|
||||
*/
|
||||
void onManualPermissionReturned() {
|
||||
//OnActivity result, no matter what the result is, our function can handle that.
|
||||
askDexterToHandleExternalStoragePermission();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method initialised the Dexter's permission builder (if not already initialised). Also makes sure that the builder is initialised
|
||||
* only once, otherwise we would'nt know on which instance of it, the user is working on. And after the builder is initialised, it checks
|
||||
* for the required permission and then handles the permission status, thanks to Dexter's appropriate callbacks.
|
||||
*/
|
||||
private void askDexterToHandleExternalStoragePermission() {
|
||||
Timber.d("External storage permission is being requested");
|
||||
if (null == dexterStoragePermissionBuilder) {
|
||||
dexterStoragePermissionBuilder = Dexter.withActivity(activity)
|
||||
.withPermission(requestedPermission)
|
||||
.withListener(new BasePermissionListener() {
|
||||
@Override
|
||||
public void onPermissionGranted(PermissionGrantedResponse response) {
|
||||
Timber.d("User has granted us the permission for writing the external storage");
|
||||
//If permission is granted, well and good
|
||||
storagePromptInProgress = false;
|
||||
storagePromptObservable.onComplete();
|
||||
//onPermissionObtained.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionDenied(PermissionDeniedResponse response) {
|
||||
Timber.d("User has granted us the permission for writing the external storage");
|
||||
//If permission is not granted in whatsoever scenario, we show him a dialog stating why we need the permission
|
||||
permissionDeniedResponse = response;
|
||||
if (null != storagePermissionInfoDialog && !storagePermissionInfoDialog
|
||||
.isShowing()) {
|
||||
storagePermissionInfoDialog.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
dexterStoragePermissionBuilder.check();
|
||||
}
|
||||
|
||||
/**
|
||||
* We have agreed to show a dialog showing why we need a particular permission.
|
||||
* This method is used to initialise the dialog which is going to show the permission's rationale.
|
||||
* The dialog is initialised along with a callback for positive and negative user actions.
|
||||
*/
|
||||
private void initPermissionsRationaleDialog() {
|
||||
if (storagePermissionInfoDialog == null) {
|
||||
storagePermissionInfoDialog = DialogUtil
|
||||
.getAlertDialogWithPositiveAndNegativeCallbacks(
|
||||
activity,
|
||||
rationaleTitle, rationaleText,
|
||||
R.drawable.ic_launcher, new DialogUtil.Callback() {
|
||||
@Override
|
||||
public void onPositiveButtonClicked() {
|
||||
//If the user is willing to give us the permission
|
||||
//But had somehow previously choose never ask again, we take him to app settings to manually enable permission
|
||||
if (null == permissionDeniedResponse) {
|
||||
//Dexter returned null, lets see if this ever happens
|
||||
Timber.w("Dexter returned null as permissionDeniedResponse");
|
||||
} else if (permissionDeniedResponse.isPermanentlyDenied()) {
|
||||
PermissionUtils.askUserToManuallyEnablePermissionFromSettings(activity);
|
||||
Timber.i("Permission permanently denied.");
|
||||
} else {
|
||||
//or if we still have chance to show runtime permission dialog, we show him that.
|
||||
askDexterToHandleExternalStoragePermission();
|
||||
Timber.d("Asking via Dexter for permission.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNegativeButtonClicked() {
|
||||
//This was the behaviour as of now, I was planning to maybe snack him with some message
|
||||
//and then call finish after some time, or may be it could be associated with some action
|
||||
// on the snack. If the user does not want us to give the permission, even after showing
|
||||
// rationale dialog, lets not trouble him any more.
|
||||
activity.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -57,6 +57,7 @@ import fr.free.nrw.commons.category.CategoryItem;
|
|||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import fr.free.nrw.commons.utils.DialogUtil;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
import fr.free.nrw.commons.utils.StringUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import io.reactivex.Observable;
|
||||
|
|
@ -67,6 +68,7 @@ import timber.log.Timber;
|
|||
|
||||
import static fr.free.nrw.commons.utils.ImageUtils.Result;
|
||||
import static fr.free.nrw.commons.utils.ImageUtils.getErrorMessageForResult;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.IS_DIRECT_UPLOAD;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ENTITY_ID_PREF;
|
||||
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ITEM_LOCATION;
|
||||
|
||||
|
|
@ -126,8 +128,6 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
|
|||
private RVRendererAdapter<CategoryItem> categoriesAdapter;
|
||||
private CompositeDisposable compositeDisposable;
|
||||
|
||||
DexterPermissionObtainer dexterPermissionObtainer;
|
||||
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@Override
|
||||
|
|
@ -150,12 +150,11 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
|
|||
|
||||
presenter.init();
|
||||
|
||||
dexterPermissionObtainer = new DexterPermissionObtainer(this,
|
||||
PermissionUtils.checkPermissionsAndPerformAction(this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
getString(R.string.storage_permission),
|
||||
getString(R.string.write_storage_permission_rationale_for_image_share));
|
||||
|
||||
dexterPermissionObtainer.confirmStoragePermissions().subscribe(this::receiveSharedItems);
|
||||
this::receiveSharedItems,
|
||||
R.string.storage_permission_title,
|
||||
R.string.write_storage_permission_rationale_for_image_share);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -180,9 +179,8 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
|
|||
protected void onResume() {
|
||||
super.onResume();
|
||||
checkIfLoggedIn();
|
||||
compositeDisposable.add(
|
||||
dexterPermissionObtainer.confirmStoragePermissions()
|
||||
.subscribe(() -> presenter.addView(this)));
|
||||
|
||||
checkStoragePermissions();
|
||||
compositeDisposable.add(
|
||||
RxTextView.textChanges(categoriesSearch)
|
||||
.doOnEach(v -> categoriesSearchContainer.setError(null))
|
||||
|
|
@ -193,6 +191,14 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
|
|||
);
|
||||
}
|
||||
|
||||
private void checkStoragePermissions() {
|
||||
PermissionUtils.checkPermissionsAndPerformAction(this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
() -> presenter.addView(this),
|
||||
R.string.storage_permission_title,
|
||||
R.string.write_storage_permission_rationale_for_image_share);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
presenter.removeView();
|
||||
|
|
@ -428,7 +434,7 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
|
|||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == CommonsApplication.OPEN_APPLICATION_DETAIL_SETTINGS) {
|
||||
dexterPermissionObtainer.onManualPermissionReturned();
|
||||
//TODO: Confirm if handling manual permission enabled is required
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -610,33 +616,52 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
|
|||
source = Contribution.SOURCE_EXTERNAL;
|
||||
}
|
||||
|
||||
Timber.d("Received intent %s with action %s and mimeType %s from source %s",
|
||||
intent.toString(),
|
||||
intent.getAction(),
|
||||
mimeType,
|
||||
source);
|
||||
|
||||
ArrayList<Uri> urisList = new ArrayList<>();
|
||||
|
||||
if (Intent.ACTION_SEND.equals(intent.getAction())) {
|
||||
Uri mediaUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
if(mediaUri == null) {
|
||||
handleNullMedia();
|
||||
return;
|
||||
}
|
||||
if (intent.getBooleanExtra("isDirectUpload", false)) {
|
||||
String imageTitle = directPrefs.getString("Title", "");
|
||||
String imageDesc = directPrefs.getString("Desc", "");
|
||||
Timber.i("Received direct upload with title %s and description %s", imageTitle, imageDesc);
|
||||
String wikidataEntityIdPref = intent.getStringExtra(WIKIDATA_ENTITY_ID_PREF);
|
||||
String wikidataItemLocation = intent.getStringExtra(WIKIDATA_ITEM_LOCATION);
|
||||
presenter.receiveDirect(mediaUri, mimeType, source, wikidataEntityIdPref, imageTitle, imageDesc, wikidataItemLocation);
|
||||
} else {
|
||||
Timber.i("Received single upload");
|
||||
presenter.receive(mediaUri, mimeType, source);
|
||||
if (mediaUri != null) {
|
||||
urisList.add(mediaUri);
|
||||
}
|
||||
} else if (Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction())) {
|
||||
ArrayList<Uri> urisList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
|
||||
urisList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
|
||||
Timber.i("Received multiple upload %s", urisList.size());
|
||||
}
|
||||
|
||||
if(urisList.isEmpty()) {
|
||||
handleNullMedia();
|
||||
return;
|
||||
}
|
||||
if (urisList.isEmpty()) {
|
||||
handleNullMedia();
|
||||
return;
|
||||
}
|
||||
|
||||
if (intent.getBooleanExtra("isDirectUpload", false)) {
|
||||
String imageTitle = directPrefs.getString("Title", "");
|
||||
String imageDesc = directPrefs.getString("Desc", "");
|
||||
Timber.i("Received direct upload with title %s and description %s", imageTitle, imageDesc);
|
||||
String wikiDataEntityIdPref = intent.getStringExtra(WIKIDATA_ENTITY_ID_PREF);
|
||||
String wikiDataItemLocation = intent.getStringExtra(WIKIDATA_ITEM_LOCATION);
|
||||
presenter.receiveDirect(urisList.get(0), mimeType, source, wikiDataEntityIdPref, imageTitle, imageDesc, wikiDataItemLocation);
|
||||
} else {
|
||||
presenter.receive(urisList, mimeType, source);
|
||||
}
|
||||
|
||||
resetDirectPrefs();
|
||||
}
|
||||
|
||||
public void resetDirectPrefs() {
|
||||
SharedPreferences.Editor editor = directPrefs.edit();
|
||||
editor.remove("Title");
|
||||
editor.remove("Desc");
|
||||
editor.remove("Category");
|
||||
editor.remove(WIKIDATA_ENTITY_ID_PREF);
|
||||
editor.remove(WIKIDATA_ITEM_LOCATION);
|
||||
editor.remove(IS_DIRECT_UPLOAD);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -97,7 +97,11 @@ public class UploadPresenter {
|
|||
* @param source File source from {@link Contribution.FileSource}
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
void receiveDirect(Uri media, String mimeType, @Contribution.FileSource String source, String wikidataEntityIdPref, String title, String desc, String wikidataItemLocation) {
|
||||
void receiveDirect(Uri media, String mimeType,
|
||||
@Contribution.FileSource String source,
|
||||
String wikidataEntityIdPref,
|
||||
String title, String desc,
|
||||
String wikidataItemLocation) {
|
||||
Completable.fromRunnable(() -> uploadModel.receiveDirect(media, mimeType, source, wikidataEntityIdPref, title, desc, similarImageInterface, wikidataItemLocation))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
package fr.free.nrw.commons.utils;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Created by root on 23.07.2018.
|
||||
*/
|
||||
|
||||
public class ExternalStorageUtils {
|
||||
|
||||
/**
|
||||
* Checks if external storage permission is granted
|
||||
* @param context activity we are on
|
||||
* @return true if permission is granted, false if not
|
||||
*/
|
||||
public static boolean isStoragePermissionGranted(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (context.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
||||
Timber.d("External storage permission granted, API >= 23");
|
||||
return true;
|
||||
} else {
|
||||
Timber.d("External storage permission not granted, API >= 23");
|
||||
return false;
|
||||
}
|
||||
} else { //permission is automatically granted on sdk<23 upon installation
|
||||
Timber.d("External storage permission granted before, API < 23");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests external storage permission
|
||||
* @param context activity we are on
|
||||
*/
|
||||
public static void requestExternalStoragePermission(Context context) {
|
||||
Timber.d("External storage permission requested");
|
||||
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,26 +9,6 @@ import timber.log.Timber;
|
|||
|
||||
public class FragmentUtils {
|
||||
|
||||
public static boolean addAndCommitFragmentWithImmediateExecution(
|
||||
@NonNull FragmentManager fragmentManager,
|
||||
@IdRes int containerViewId,
|
||||
@NonNull Fragment fragment) {
|
||||
if (fragment.isAdded()) {
|
||||
Timber.w("Could not add fragment. The fragment is already added.");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
fragmentManager.beginTransaction()
|
||||
.add(containerViewId, fragment)
|
||||
.commitNow();
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
Timber.e(e, "Could not add & commit fragment. "
|
||||
+ "Did you mean to call commitAllowingStateLoss?");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to check whether the fragment UI is still active or not
|
||||
* @param fragment
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import android.graphics.Rect;
|
|||
import android.net.Uri;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.esafirm.imagepicker.model.Image;
|
||||
import com.facebook.common.executors.CallerThreadExecutor;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
|
|
@ -24,6 +24,8 @@ import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
|||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
|
|
@ -253,4 +255,15 @@ public class ImageUtils {
|
|||
|
||||
return errorMessage.toString();
|
||||
}
|
||||
|
||||
public static ArrayList<Uri> getUriListFromImages(List<Image> imageList) {
|
||||
ArrayList<Uri> uriList = new ArrayList<>();
|
||||
for (Image imagePath : imageList) {
|
||||
if (!StringUtils.isNullOrWhiteSpace(imagePath.getPath())) {
|
||||
uriList.add(Uri.parse(imagePath.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
return uriList;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
41
app/src/main/java/fr/free/nrw/commons/utils/IntentUtils.java
Normal file
41
app/src/main/java/fr/free/nrw/commons/utils/IntentUtils.java
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package fr.free.nrw.commons.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.BOOKMARK_CAMERA_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.BOOKMARK_GALLERY_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.CAMERA_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.GALLERY_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_CAMERA_UPLOAD_REQUEST_CODE;
|
||||
import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_GALLERY_UPLOAD_REQUEST_CODE;
|
||||
|
||||
public class IntentUtils {
|
||||
|
||||
/**
|
||||
* Check if the intent should be handled by nearby list or map fragment
|
||||
*/
|
||||
public static boolean shouldNearbyHandle(int requestCode, int resultCode, Intent data) {
|
||||
return resultCode == Activity.RESULT_OK
|
||||
&& (requestCode == NEARBY_CAMERA_UPLOAD_REQUEST_CODE || requestCode == NEARBY_GALLERY_UPLOAD_REQUEST_CODE)
|
||||
&& data != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the intent should be handled by contributions list fragment
|
||||
*/
|
||||
public static boolean shouldContributionsListHandle(int requestCode, int resultCode, Intent data) {
|
||||
return resultCode == Activity.RESULT_OK
|
||||
&& (requestCode == GALLERY_UPLOAD_REQUEST_CODE || requestCode == CAMERA_UPLOAD_REQUEST_CODE)
|
||||
&& data != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the intent should be handled by contributions list fragment
|
||||
*/
|
||||
public static boolean shouldBookmarksHandle(int requestCode, int resultCode, Intent data) {
|
||||
return resultCode == Activity.RESULT_OK
|
||||
&& (requestCode == BOOKMARK_CAMERA_UPLOAD_REQUEST_CODE || requestCode == BOOKMARK_GALLERY_UPLOAD_REQUEST_CODE)
|
||||
&& data != null;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,18 @@ import android.content.Intent;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
|
||||
import com.karumi.dexter.Dexter;
|
||||
import com.karumi.dexter.PermissionToken;
|
||||
import com.karumi.dexter.listener.PermissionDeniedResponse;
|
||||
import com.karumi.dexter.listener.PermissionGrantedResponse;
|
||||
import com.karumi.dexter.listener.PermissionRequest;
|
||||
import com.karumi.dexter.listener.single.BasePermissionListener;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.R;
|
||||
|
||||
|
||||
public class PermissionUtils {
|
||||
|
|
@ -17,8 +26,7 @@ public class PermissionUtils {
|
|||
It open the app settings from where the user can manually give us the required permission.
|
||||
* @param activity
|
||||
*/
|
||||
public static void askUserToManuallyEnablePermissionFromSettings(
|
||||
Activity activity) {
|
||||
public static void askUserToManuallyEnablePermissionFromSettings(Activity activity) {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
|
|
@ -36,4 +44,62 @@ public class PermissionUtils {
|
|||
return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for a particular permission and runs the runnable to perform an action when the permission is granted
|
||||
* Also, it shows a rationale if needed
|
||||
*
|
||||
* Sample usage:
|
||||
*
|
||||
* PermissionUtils.checkPermissionsAndPerformAction(activity,
|
||||
* Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
* () -> initiateCameraUpload(activity),
|
||||
* R.string.storage_permission_title,
|
||||
* R.string.write_storage_permission_rationale);
|
||||
*
|
||||
*
|
||||
* @param activity activity requesting permissions
|
||||
* @param permission the permission being requests
|
||||
* @param onPermissionGranted the runnable to be executed when the permission is granted
|
||||
* @param rationaleTitle rationale title to be displayed when permission was denied
|
||||
* @param rationaleMessage rationale message to be displayed when permission was denied
|
||||
*/
|
||||
public static void checkPermissionsAndPerformAction(Activity activity,
|
||||
String permission,
|
||||
Runnable onPermissionGranted,
|
||||
@StringRes int rationaleTitle,
|
||||
@StringRes int rationaleMessage) {
|
||||
Dexter.withActivity(activity)
|
||||
.withPermission(permission)
|
||||
.withListener(new BasePermissionListener() {
|
||||
@Override
|
||||
public void onPermissionGranted(PermissionGrantedResponse response) {
|
||||
onPermissionGranted.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionDenied(PermissionDeniedResponse response) {
|
||||
if (response.isPermanentlyDenied()) {
|
||||
DialogUtil.showAlertDialog(activity,
|
||||
activity.getString(rationaleTitle),
|
||||
activity.getString(rationaleMessage),
|
||||
activity.getString(R.string.navigation_item_settings),
|
||||
null,
|
||||
() -> askUserToManuallyEnablePermissionFromSettings(activity),
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
|
||||
DialogUtil.showAlertDialog(activity,
|
||||
activity.getString(rationaleTitle),
|
||||
activity.getString(rationaleMessage),
|
||||
activity.getString(android.R.string.ok),
|
||||
activity.getString(android.R.string.cancel),
|
||||
token::continuePermissionRequest,
|
||||
token::cancelPermissionRequest);
|
||||
}
|
||||
}).check();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ package fr.free.nrw.commons.wikidata;
|
|||
public class WikidataConstants {
|
||||
public static final String WIKIDATA_ENTITY_ID_PREF = "WikiDataEntityId";
|
||||
public static final String WIKIDATA_ITEM_LOCATION = "WikiDataItemLocation";
|
||||
public static final String IS_DIRECT_UPLOAD = "isDirectUpload";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue