add method to get correct storage permission and check partial access

Additionally, add final keywords to reduce compiler warnings
This commit is contained in:
Rohit Verma 2024-08-24 20:52:14 +05:30 committed by Rohit Verma
parent 349b8ef482
commit f8d164b6a2

View file

@ -1,6 +1,7 @@
package fr.free.nrw.commons.utils; package fr.free.nrw.commons.utils;
import android.Manifest; import android.Manifest;
import android.Manifest.permission;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -20,24 +21,23 @@ import fr.free.nrw.commons.R;
import fr.free.nrw.commons.upload.UploadActivity; import fr.free.nrw.commons.upload.UploadActivity;
import java.util.List; import java.util.List;
public class PermissionUtils { public class PermissionUtils {
public static String[] PERMISSIONS_STORAGE = getPermissionsStorage();
public static String[] PERMISSIONS_STORAGE = isSDKVersionScopedStorageCompatible() ? static String[] getPermissionsStorage() {
isSDKVersionTiramisu() ? new String[]{ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
Manifest.permission.READ_MEDIA_IMAGES} : return new String[]{ Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE} Manifest.permission.READ_MEDIA_IMAGES };
: isSDKVersionTiramisu() ? new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, }
Manifest.permission.READ_MEDIA_IMAGES} if(Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU) {
: new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, return new String[]{ Manifest.permission.READ_MEDIA_IMAGES };
Manifest.permission.READ_EXTERNAL_STORAGE}; }
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
private static boolean isSDKVersionScopedStorageCompatible() { return new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE };
return Build.VERSION.SDK_INT > Build.VERSION_CODES.P; }
} return new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
public static boolean isSDKVersionTiramisu() { Manifest.permission.WRITE_EXTERNAL_STORAGE };
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
} }
/** /**
@ -45,11 +45,11 @@ public class PermissionUtils {
* blocked(marked never ask again by the user) It open the app settings from where the user can * blocked(marked never ask again by the user) It open the app settings from where the user can
* manually give us the required permission. * manually give us the required permission.
* *
* @param activity * @param activity The Activity which requires a permission which has been blocked
*/ */
private static void askUserToManuallyEnablePermissionFromSettings(Activity activity) { private static void askUserToManuallyEnablePermissionFromSettings(final Activity activity) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null); final Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri); intent.setData(uri);
activity.startActivityForResult(intent, activity.startActivityForResult(intent,
CommonsApplication.OPEN_APPLICATION_DETAIL_SETTINGS); CommonsApplication.OPEN_APPLICATION_DETAIL_SETTINGS);
@ -58,14 +58,13 @@ public class PermissionUtils {
/** /**
* Checks whether the app already has a particular permission * Checks whether the app already has a particular permission
* *
* @param activity * @param activity The Activity context to check permissions against
* @param permissions permissions to be checked * @param permissions An array of permission strings to check
* @return * @return `true if the app has all the specified permissions, `false` otherwise
*/ */
public static boolean hasPermission(Activity activity, String permissions[]) { public static boolean hasPermission(final Activity activity, final String[] permissions) {
boolean hasPermission = true; boolean hasPermission = true;
for (String permission : permissions for(final String permission : permissions) {
) {
hasPermission = hasPermission && hasPermission = hasPermission &&
ContextCompat.checkSelfPermission(activity, permission) ContextCompat.checkSelfPermission(activity, permission)
== PackageManager.PERMISSION_GRANTED; == PackageManager.PERMISSION_GRANTED;
@ -73,6 +72,15 @@ public class PermissionUtils {
return hasPermission; return hasPermission;
} }
public static boolean hasPartialAccess(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
return ContextCompat.checkSelfPermission(activity,
permission.READ_MEDIA_VISUAL_USER_SELECTED
) == PackageManager.PERMISSION_GRANTED;
}
return false;
}
/** /**
* Checks for a particular permission and runs the runnable to perform an action when the * 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 * permission is granted Also, it shows a rationale if needed
@ -99,9 +107,17 @@ public class PermissionUtils {
* @param rationaleMessage rationale message to be displayed when permission was denied. It * @param rationaleMessage rationale message to be displayed when permission was denied. It
* can be an invalid @StringRes * can be an invalid @StringRes
*/ */
public static void checkPermissionsAndPerformAction(Activity activity, public static void checkPermissionsAndPerformAction(
Runnable onPermissionGranted, @StringRes int rationaleTitle, final Activity activity,
@StringRes int rationaleMessage, String... permissions) { final Runnable onPermissionGranted,
final @StringRes int rationaleTitle,
final @StringRes int rationaleMessage,
final String... permissions
) {
if (hasPartialAccess(activity)) {
onPermissionGranted.run();
return;
}
checkPermissionsAndPerformAction(activity, onPermissionGranted, null, checkPermissionsAndPerformAction(activity, onPermissionGranted, null,
rationaleTitle, rationaleMessage, permissions); rationaleTitle, rationaleMessage, permissions);
} }
@ -125,25 +141,30 @@ public class PermissionUtils {
* @param rationaleTitle rationale title to be displayed when permission was denied * @param rationaleTitle rationale title to be displayed when permission was denied
* @param rationaleMessage rationale message to be displayed when permission was denied * @param rationaleMessage rationale message to be displayed when permission was denied
*/ */
public static void checkPermissionsAndPerformAction(Activity activity, public static void checkPermissionsAndPerformAction(
Runnable onPermissionGranted, Runnable onPermissionDenied, @StringRes int rationaleTitle, final Activity activity,
@StringRes int rationaleMessage, String... permissions) { final Runnable onPermissionGranted,
final Runnable onPermissionDenied,
final @StringRes int rationaleTitle,
final @StringRes int rationaleMessage,
final String... permissions
) {
Dexter.withActivity(activity) Dexter.withActivity(activity)
.withPermissions(permissions) .withPermissions(permissions)
.withListener(new MultiplePermissionsListener() { .withListener(new MultiplePermissionsListener() {
@Override @Override
public void onPermissionsChecked(MultiplePermissionsReport report) { public void onPermissionsChecked(final MultiplePermissionsReport report) {
if (report.areAllPermissionsGranted()) { if (report.areAllPermissionsGranted() || hasPartialAccess(activity)) {
onPermissionGranted.run(); onPermissionGranted.run();
return; return;
} }
if (report.isAnyPermissionPermanentlyDenied()) { if (report.isAnyPermissionPermanentlyDenied()) {
// permission is denied permanently, we will show user a dialog message. // permission is denied permanently, we will show user a dialog message.
DialogUtil.showAlertDialog(activity, activity.getString(rationaleTitle), DialogUtil.showAlertDialog(
activity, activity.getString(rationaleTitle),
activity.getString(rationaleMessage), activity.getString(rationaleMessage),
activity.getString(R.string.navigation_item_settings), activity.getString(R.string.navigation_item_settings),
null, null, () -> {
() -> {
askUserToManuallyEnablePermissionFromSettings(activity); askUserToManuallyEnablePermissionFromSettings(activity);
if (activity instanceof UploadActivity) { if (activity instanceof UploadActivity) {
((UploadActivity) activity).setShowPermissionsDialog(true); ((UploadActivity) activity).setShowPermissionsDialog(true);
@ -158,13 +179,16 @@ public class PermissionUtils {
} }
@Override @Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, public void onPermissionRationaleShouldBeShown(
PermissionToken token) { final List<PermissionRequest> permissions,
final PermissionToken token
) {
if (rationaleTitle == -1 && rationaleMessage == -1) { if (rationaleTitle == -1 && rationaleMessage == -1) {
token.continuePermissionRequest(); token.continuePermissionRequest();
return; return;
} }
DialogUtil.showAlertDialog(activity, activity.getString(rationaleTitle), DialogUtil.showAlertDialog(
activity, activity.getString(rationaleTitle),
activity.getString(rationaleMessage), activity.getString(rationaleMessage),
activity.getString(android.R.string.ok), activity.getString(android.R.string.ok),
activity.getString(android.R.string.cancel), activity.getString(android.R.string.cancel),
@ -173,24 +197,19 @@ public class PermissionUtils {
((UploadActivity) activity).setShowPermissionsDialog(true); ((UploadActivity) activity).setShowPermissionsDialog(true);
} }
token.continuePermissionRequest(); token.continuePermissionRequest();
} },
,
() -> { () -> {
Toast.makeText(activity.getApplicationContext(), Toast.makeText(activity.getApplicationContext(),
R.string.permissions_are_required_for_functionality, R.string.permissions_are_required_for_functionality,
Toast.LENGTH_LONG) Toast.LENGTH_LONG
.show(); ).show();
token.cancelPermissionRequest(); token.cancelPermissionRequest();
if (activity instanceof UploadActivity) { if (activity instanceof UploadActivity) {
activity.finish(); activity.finish();
} }
} }, null, false
, );
null,
false);
} }
}) }).onSameThread().check();
.onSameThread()
.check();
} }
} }