From 53a53e410d2e81451a9eb4cb786ce8af984ecc21 Mon Sep 17 00:00:00 2001 From: Ashish Date: Wed, 22 Aug 2018 23:01:38 +0530 Subject: [PATCH 01/10] Added permission for Dexter, the runtime permission handling library --- app/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index c056fb4295..a2b5477ad2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,6 +77,9 @@ dependencies { releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY" testImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY" + //For handling runtime permissions + implementation 'com.karumi:dexter:5.0.0' + } android { From da395427572a4c242d8f2c7e87e7e49048670b0a Mon Sep 17 00:00:00 2001 From: Ashish Date: Thu, 23 Aug 2018 00:22:14 +0530 Subject: [PATCH 02/10] [Preparing fir issue #1773] Added a utility function which would take the user to app settings screen where he could manually give us the required permission --- .../nrw/commons/utils/PermissionUtils.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java diff --git a/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java new file mode 100644 index 0000000000..fd7f4d12fd --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java @@ -0,0 +1,19 @@ +package fr.free.nrw.commons.utils; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.provider.Settings; + +public class PermissionUtils { + + //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 manully give us the required permission. + 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); + activity.startActivityForResult(intent, Constants.REQUEST_CODES.OPEN_APPLICATION_DETAIL_SETTINGS); + } +} From 8783e9bcb437bd30e53774386c78ee5492afb55f Mon Sep 17 00:00:00 2001 From: Ashish Date: Thu, 23 Aug 2018 00:23:16 +0530 Subject: [PATCH 03/10] Added an alert dialog with positive and negative callback [Preparing fir issue #1773] --- .../fr/free/nrw/commons/utils/DialogUtil.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java b/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java index 78c1ca155e..406ca2c606 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java @@ -1,7 +1,10 @@ package fr.free.nrw.commons.utils; import android.app.Activity; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; import android.app.Dialog; +import android.content.Context; import android.os.Build; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; @@ -92,4 +95,31 @@ public static void showSafely(FragmentActivity activity, DialogFragment dialog) Timber.e(e, "Could not show dialog."); } } + + public static AlertDialog getAlertDialogWithPositiveAndNegativeCallbacks( + Context context, String title, String message, int iconResourceId, Callback callback) { + + AlertDialog alertDialog = new Builder(context) + .setTitle(title) + .setMessage(message) + .setPositiveButton("Okay", (dialog, which) -> { + dialog.dismiss(); + callback.onPositiveButtonClicked(); + }) + .setNegativeButton("Cancel", (dialog, which) -> { + dialog.dismiss(); + callback.onNegativeButtonClicked(); + }) + .setIcon(iconResourceId).create(); + + return alertDialog; + + } + + public static interface Callback { + + void onPositiveButtonClicked(); + + void onNegativeButtonClicked(); + } } From 411504817e739db21d49df3eec8716ae0fad766a Mon Sep 17 00:00:00 2001 From: Ashish Date: Thu, 23 Aug 2018 00:25:04 +0530 Subject: [PATCH 04/10] Improvements in the way External Storage Permission is handled in MultipleShareActivity[Bug fix #1697] 1. Used dexter to handle the external storage permission 2. Behaviour changes : When user tries to share(uppload) images to commons via MultipleShareActivity, following decision tree is followed a. If the app has permission for external storage, normal upload operation is followed b. If the app does not has the permission for external storage, dexter is used to ask for the same c. If the user gives us the required permission, normal upload flow is proceeded d. If the doesnot gives us the required permission a rationale dialog is shown with the appropriate message to let him know why we need the permission e. If he presses okay, steps a-c are followed and if he presses cancel, we close the app. f. If while asking for permission, the user chooses never ask again, then next time he tries to upload an image via MSA, the rational dialog follows the app setting screen where he could manually give us the required permission and the onActivityResult of same is handled --- .../commons/upload/MultipleShareActivity.java | 108 +++++++++++++++--- app/src/main/res/values/strings.xml | 2 + 2 files changed, 94 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java index e429c3ee80..f6916efaab 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java @@ -1,6 +1,8 @@ package fr.free.nrw.commons.upload; import android.Manifest; +import android.Manifest.permission; +import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.ContentResolver; import android.content.Context; @@ -12,7 +14,7 @@ import android.os.Build; import android.os.Bundle; import android.os.ParcelFileDescriptor; -import android.support.annotation.NonNull; +import android.provider.Settings; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentManager; @@ -23,6 +25,19 @@ import android.widget.AdapterView; import android.widget.Toast; +import com.karumi.dexter.Dexter; +import com.karumi.dexter.DexterBuilder; +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.karumi.dexter.listener.single.PermissionListener; +import fr.free.nrw.commons.utils.Constants; +import fr.free.nrw.commons.utils.Constants.REQUEST_CODES; +import fr.free.nrw.commons.utils.DialogUtil; +import fr.free.nrw.commons.utils.DialogUtil.Callback; +import fr.free.nrw.commons.utils.PermissionUtils; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; @@ -41,7 +56,6 @@ import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.modifications.CategoryModifier; -import fr.free.nrw.commons.modifications.ModificationsContentProvider; import fr.free.nrw.commons.modifications.ModifierSequence; import fr.free.nrw.commons.modifications.ModifierSequenceDao; import fr.free.nrw.commons.modifications.TemplateRemoveModifier; @@ -81,6 +95,9 @@ public class MultipleShareActivity extends AuthenticatedActivity private boolean locationPermitted = false; private boolean isMultipleUploadsPrepared = false; private boolean isMultipleUploadsFinalised = false; // Checks is user clicked to upload button or regret before this phase + private final String TAG="#MultipleShareActivity#"; + private AlertDialog storagePermissionInfoDialog; + private DexterBuilder dexterStoragePermissionBuilder; @Override public Media getMediaAtPosition(int i) { @@ -124,17 +141,6 @@ public void OnMultipleUploadInitiated() { multipleUploadBegins(); } - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if (requestCode == 1 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - Timber.d("onRequestPermissionsResult external storage permission granted"); - prepareMultipleUpoadList(); - } else { - // Permission is not granted, close activity - finish(); - } - } - private void multipleUploadBegins() { Timber.d("Multiple upload begins"); @@ -275,12 +281,82 @@ protected void onAuthCookieAcquired(String authCookie) { isMultipleUploadsPrepared = false; mwApi.setAuthCookie(authCookie); if (!ExternalStorageUtils.isStoragePermissionGranted(this)) { - ExternalStorageUtils.requestExternalStoragePermission(this); + //If permission is not there, handle the negative cases + askDexterToHandleExternalStoragePermission(); isMultipleUploadsPrepared = false; return; // Postpone operation to do after gettion permission } else { isMultipleUploadsPrepared = true; - prepareMultipleUpoadList(); + prepareMultipleUploadList(); + } + } + + private void askDexterToHandleExternalStoragePermission() { + Timber.d(TAG, "External storage permission is being requested"); + if (null == dexterStoragePermissionBuilder) { + dexterStoragePermissionBuilder = Dexter.withActivity(this) + .withPermission(permission.WRITE_EXTERNAL_STORAGE) + .withListener(new BasePermissionListener() { + @Override + public void onPermissionGranted(PermissionGrantedResponse response) { + Timber.d(TAG, + "User has granted us the permission for writing the external storage"); + //If permission is granted, well and good + prepareMultipleUploadList(); + } + + @Override + public void onPermissionDenied(PermissionDeniedResponse response) { + Timber.d(TAG, + "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 + if (storagePermissionInfoDialog == null) { + storagePermissionInfoDialog = DialogUtil + .getAlertDialogWithPositiveAndNegativeCallbacks( + MultipleShareActivity.this, + getString(R.string.storage_permission), getString( + R.string.write_storage_permission_rationale_for_image_share), + R.drawable.ic_launcher, new 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 (response.isPermanentlyDenied()) { + PermissionUtils + .askUserToManuallyEnablePermissionFromSettings( + MultipleShareActivity.this); + } else { + //or if we still have chance to show runtime permission dialog, we show him that. + askDexterToHandleExternalStoragePermission(); + } + } + + @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 anymore + finish(); + } + }); + } + + if (null != storagePermissionInfoDialog && !storagePermissionInfoDialog + .isShowing()) { + storagePermissionInfoDialog.show(); + } + } + }); + } + dexterStoragePermissionBuilder.check(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_CODES.OPEN_APPLICATION_DETAIL_SETTINGS) { + //OnActivity result, no matter what the result is, our function can handle that. + askDexterToHandleExternalStoragePermission(); } } @@ -288,7 +364,7 @@ protected void onAuthCookieAcquired(String authCookie) { * Prepares a list from files will be uploaded. Saves these files temporarily to external * storage. Adds them to uploads list */ - private void prepareMultipleUpoadList() { + private void prepareMultipleUploadList() { Intent intent = getIntent(); if (Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction())) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ffc7d88c15..f7b5d4c7f5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -350,4 +350,6 @@ The percentage of images you have uploaded to Commons that were not deleted The number of images you have uploaded to Commons that were used in Wikimedia articles Commons Notification + Storage Permission + We need your permission to access the external storage of your device in order to upload images. From 16a9afc7f2d141890fb3a5806dd4c88b089f4a84 Mon Sep 17 00:00:00 2001 From: Ashish Date: Thu, 23 Aug 2018 00:33:45 +0530 Subject: [PATCH 05/10] Added a Constants class to handle request and result codes from one place and other related constants common to the all app elements --- .../main/java/fr/free/nrw/commons/utils/Constants.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/Constants.java diff --git a/app/src/main/java/fr/free/nrw/commons/utils/Constants.java b/app/src/main/java/fr/free/nrw/commons/utils/Constants.java new file mode 100644 index 0000000000..d5d9effc83 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/Constants.java @@ -0,0 +1,9 @@ +package fr.free.nrw.commons.utils; + +public class Constants { + + public class REQUEST_CODES { + + public static final int OPEN_APPLICATION_DETAIL_SETTINGS = 1001; + } +} From 28dfae077b75d3e788520b270eb696024cbc2c92 Mon Sep 17 00:00:00 2001 From: Ashish Date: Thu, 23 Aug 2018 18:19:21 +0530 Subject: [PATCH 06/10] replaced hardcoded strings ok and cancel in DialogUtil to string resources --- app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java b/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java index 406ca2c606..70fdc7ed85 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java @@ -10,6 +10,7 @@ import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; +import fr.free.nrw.commons.R; import timber.log.Timber; public class DialogUtil { @@ -102,11 +103,11 @@ public static AlertDialog getAlertDialogWithPositiveAndNegativeCallbacks( AlertDialog alertDialog = new Builder(context) .setTitle(title) .setMessage(message) - .setPositiveButton("Okay", (dialog, which) -> { + .setPositiveButton(context.getString(R.string.ok), (dialog, which) -> { dialog.dismiss(); callback.onPositiveButtonClicked(); }) - .setNegativeButton("Cancel", (dialog, which) -> { + .setNegativeButton(context.getString(R.string.cancel), (dialog, which) -> { dialog.dismiss(); callback.onNegativeButtonClicked(); }) From d0547677bed9123edd1e3fabc969160dadae0713 Mon Sep 17 00:00:00 2001 From: Ashish Date: Fri, 24 Aug 2018 23:57:18 +0530 Subject: [PATCH 07/10] init permission rationale dialog in activities onCreate --- .../commons/upload/MultipleShareActivity.java | 77 ++++++++++--------- .../fr/free/nrw/commons/utils/DialogUtil.java | 6 +- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java index f6916efaab..342a02f02f 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java @@ -14,7 +14,6 @@ import android.os.Build; import android.os.Bundle; import android.os.ParcelFileDescriptor; -import android.provider.Settings; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentManager; @@ -27,13 +26,9 @@ import com.karumi.dexter.Dexter; import com.karumi.dexter.DexterBuilder; -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.karumi.dexter.listener.single.PermissionListener; -import fr.free.nrw.commons.utils.Constants; import fr.free.nrw.commons.utils.Constants.REQUEST_CODES; import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.DialogUtil.Callback; @@ -99,6 +94,8 @@ public class MultipleShareActivity extends AuthenticatedActivity private AlertDialog storagePermissionInfoDialog; private DexterBuilder dexterStoragePermissionBuilder; + PermissionDeniedResponse permissionDeniedResponse; + @Override public Media getMediaAtPosition(int i) { return photosList.get(i); @@ -222,6 +219,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_multiple_uploads); ButterKnife.bind(this); initDrawer(); + initPermissionsRationaleDialog(); if (savedInstanceState != null) { photosList = savedInstanceState.getParcelableArrayList("uploadsList"); @@ -239,6 +237,43 @@ protected void onCreate(Bundle savedInstanceState) { } } + private void initPermissionsRationaleDialog() { + if (storagePermissionInfoDialog == null) { + storagePermissionInfoDialog = DialogUtil + .getAlertDialogWithPositiveAndNegativeCallbacks( + MultipleShareActivity.this, + getString(R.string.storage_permission), getString( + R.string.write_storage_permission_rationale_for_image_share), + R.drawable.ic_launcher, new 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 + return; + } + else if (permissionDeniedResponse.isPermanentlyDenied()) { + PermissionUtils + .askUserToManuallyEnablePermissionFromSettings( + MultipleShareActivity.this); + } else { + //or if we still have chance to show runtime permission dialog, we show him that. + askDexterToHandleExternalStoragePermission(); + } + } + + @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 anymore + finish(); + } + }); + } + } + @Override protected void onDestroy() { super.onDestroy(); @@ -310,37 +345,7 @@ public void onPermissionDenied(PermissionDeniedResponse response) { Timber.d(TAG, "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 - if (storagePermissionInfoDialog == null) { - storagePermissionInfoDialog = DialogUtil - .getAlertDialogWithPositiveAndNegativeCallbacks( - MultipleShareActivity.this, - getString(R.string.storage_permission), getString( - R.string.write_storage_permission_rationale_for_image_share), - R.drawable.ic_launcher, new 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 (response.isPermanentlyDenied()) { - PermissionUtils - .askUserToManuallyEnablePermissionFromSettings( - MultipleShareActivity.this); - } else { - //or if we still have chance to show runtime permission dialog, we show him that. - askDexterToHandleExternalStoragePermission(); - } - } - - @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 anymore - finish(); - } - }); - } - + permissionDeniedResponse=response; if (null != storagePermissionInfoDialog && !storagePermissionInfoDialog .isShowing()) { storagePermissionInfoDialog.show(); diff --git a/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java b/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java index 70fdc7ed85..2e4592e400 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/DialogUtil.java @@ -104,12 +104,12 @@ public static AlertDialog getAlertDialogWithPositiveAndNegativeCallbacks( .setTitle(title) .setMessage(message) .setPositiveButton(context.getString(R.string.ok), (dialog, which) -> { - dialog.dismiss(); callback.onPositiveButtonClicked(); + dialog.dismiss(); }) .setNegativeButton(context.getString(R.string.cancel), (dialog, which) -> { - dialog.dismiss(); callback.onNegativeButtonClicked(); + dialog.dismiss(); }) .setIcon(iconResourceId).create(); @@ -117,7 +117,7 @@ public static AlertDialog getAlertDialogWithPositiveAndNegativeCallbacks( } - public static interface Callback { + public interface Callback { void onPositiveButtonClicked(); From 8b079502562c8f43a58d05332c3efd98a5f0339b Mon Sep 17 00:00:00 2001 From: Ashish Date: Sun, 2 Sep 2018 09:38:59 +0530 Subject: [PATCH 08/10] Code formatting, updated access modifiers wherever required, added javadocs for new methods created --- .../commons/upload/MultipleShareActivity.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java index 342a02f02f..e352eecc15 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java @@ -94,7 +94,7 @@ public class MultipleShareActivity extends AuthenticatedActivity private AlertDialog storagePermissionInfoDialog; private DexterBuilder dexterStoragePermissionBuilder; - PermissionDeniedResponse permissionDeniedResponse; + private PermissionDeniedResponse permissionDeniedResponse; @Override public Media getMediaAtPosition(int i) { @@ -237,6 +237,12 @@ protected void onCreate(Bundle savedInstanceState) { } } + + /** + * 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 @@ -254,9 +260,7 @@ public void onPositiveButtonClicked() { return; } else if (permissionDeniedResponse.isPermanentlyDenied()) { - PermissionUtils - .askUserToManuallyEnablePermissionFromSettings( - MultipleShareActivity.this); + PermissionUtils.askUserToManuallyEnablePermissionFromSettings(MultipleShareActivity.this); } else { //or if we still have chance to show runtime permission dialog, we show him that. askDexterToHandleExternalStoragePermission(); @@ -326,6 +330,11 @@ protected void onAuthCookieAcquired(String authCookie) { } } + /** + * 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(TAG, "External storage permission is being requested"); if (null == dexterStoragePermissionBuilder) { @@ -334,16 +343,14 @@ private void askDexterToHandleExternalStoragePermission() { .withListener(new BasePermissionListener() { @Override public void onPermissionGranted(PermissionGrantedResponse response) { - Timber.d(TAG, - "User has granted us the permission for writing the external storage"); + Timber.d(TAG,"User has granted us the permission for writing the external storage"); //If permission is granted, well and good prepareMultipleUploadList(); } @Override public void onPermissionDenied(PermissionDeniedResponse response) { - Timber.d(TAG, - "User has granted us the permission for writing the external storage"); + Timber.d(TAG,"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 From 59c21aa681f690c9ccff273288495e34bbc04d29 Mon Sep 17 00:00:00 2001 From: Ashish Date: Mon, 3 Sep 2018 14:09:52 +0530 Subject: [PATCH 09/10] *shifted constants to app class *Added JavaDocs in PermissionUtils --- .../java/fr/free/nrw/commons/CommonsApplication.java | 12 ++++++++++++ .../nrw/commons/upload/MultipleShareActivity.java | 4 ++-- .../java/fr/free/nrw/commons/utils/Constants.java | 9 --------- .../fr/free/nrw/commons/utils/PermissionUtils.java | 10 +++++++--- 4 files changed, 21 insertions(+), 14 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/utils/Constants.java diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index 51b8b0b0f9..5a3cc43304 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -54,6 +54,14 @@ public class CommonsApplication extends Application { @Inject @Named("application_preferences") SharedPreferences applicationPrefs; @Inject @Named("prefs") SharedPreferences otherPrefs; + /** + * Constants begin + */ + public class REQUEST_CODES { + + public static final int OPEN_APPLICATION_DETAIL_SETTINGS = 1001; + } + public static final String DEFAULT_EDIT_SUMMARY = "Uploaded using [[COM:MOA|Commons Mobile App]]"; public static final String FEEDBACK_EMAIL = "commons-app-android@googlegroups.com"; @@ -66,6 +74,10 @@ public class CommonsApplication extends Application { public static final String NOTIFICATION_CHANNEL_ID_ALL = "CommonsNotificationAll"; + /** + * Constants End + */ + private RefWatcher refWatcher; diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java index e352eecc15..8c34691b62 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java @@ -29,7 +29,7 @@ import com.karumi.dexter.listener.PermissionDeniedResponse; import com.karumi.dexter.listener.PermissionGrantedResponse; import com.karumi.dexter.listener.single.BasePermissionListener; -import fr.free.nrw.commons.utils.Constants.REQUEST_CODES; +import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.DialogUtil.Callback; import fr.free.nrw.commons.utils.PermissionUtils; @@ -366,7 +366,7 @@ public void onPermissionDenied(PermissionDeniedResponse response) { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_CODES.OPEN_APPLICATION_DETAIL_SETTINGS) { + if (requestCode == CommonsApplication.REQUEST_CODES.OPEN_APPLICATION_DETAIL_SETTINGS) { //OnActivity result, no matter what the result is, our function can handle that. askDexterToHandleExternalStoragePermission(); } diff --git a/app/src/main/java/fr/free/nrw/commons/utils/Constants.java b/app/src/main/java/fr/free/nrw/commons/utils/Constants.java deleted file mode 100644 index d5d9effc83..0000000000 --- a/app/src/main/java/fr/free/nrw/commons/utils/Constants.java +++ /dev/null @@ -1,9 +0,0 @@ -package fr.free.nrw.commons.utils; - -public class Constants { - - public class REQUEST_CODES { - - public static final int OPEN_APPLICATION_DETAIL_SETTINGS = 1001; - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java index fd7f4d12fd..bea06fc3e3 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java @@ -4,16 +4,20 @@ import android.content.Intent; import android.net.Uri; import android.provider.Settings; +import fr.free.nrw.commons.CommonsApplication; public class PermissionUtils { - //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 manully give us the required permission. + /** + * 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. + * @param 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); - activity.startActivityForResult(intent, Constants.REQUEST_CODES.OPEN_APPLICATION_DETAIL_SETTINGS); + activity.startActivityForResult(intent,CommonsApplication.REQUEST_CODES.OPEN_APPLICATION_DETAIL_SETTINGS); } } From a332be785b66102a89a3b2681ff631904ecee0b3 Mon Sep 17 00:00:00 2001 From: Ashish Date: Mon, 3 Sep 2018 14:46:24 +0530 Subject: [PATCH 10/10] removed class REQUEST_CODES from CommonsApplication and instead put the enclosing constants in the App class itself --- .../main/java/fr/free/nrw/commons/CommonsApplication.java | 5 +---- .../fr/free/nrw/commons/upload/MultipleShareActivity.java | 2 +- .../main/java/fr/free/nrw/commons/utils/PermissionUtils.java | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index 5a3cc43304..2ee5f305fb 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -57,10 +57,7 @@ public class CommonsApplication extends Application { /** * Constants begin */ - public class REQUEST_CODES { - - public static final int OPEN_APPLICATION_DETAIL_SETTINGS = 1001; - } + public static final int OPEN_APPLICATION_DETAIL_SETTINGS = 1001; public static final String DEFAULT_EDIT_SUMMARY = "Uploaded using [[COM:MOA|Commons Mobile App]]"; diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java index 8c34691b62..a35eb46eec 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java @@ -366,7 +366,7 @@ public void onPermissionDenied(PermissionDeniedResponse response) { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == CommonsApplication.REQUEST_CODES.OPEN_APPLICATION_DETAIL_SETTINGS) { + if (requestCode == CommonsApplication.OPEN_APPLICATION_DETAIL_SETTINGS) { //OnActivity result, no matter what the result is, our function can handle that. askDexterToHandleExternalStoragePermission(); } diff --git a/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java index bea06fc3e3..ecdc015119 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/PermissionUtils.java @@ -18,6 +18,6 @@ public static void askUserToManuallyEnablePermissionFromSettings( Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", activity.getPackageName(), null); intent.setData(uri); - activity.startActivityForResult(intent,CommonsApplication.REQUEST_CODES.OPEN_APPLICATION_DETAIL_SETTINGS); + activity.startActivityForResult(intent,CommonsApplication.OPEN_APPLICATION_DETAIL_SETTINGS); } }