preface
EasyPermissions is a library for checking and applying for Android dynamic permissions, simplifying native permissions logic. Please refer to the official document for the usage method.
A, requirements,
It is necessary to replace the two prompt pop-up boxes encapsulated in the library with the unified internal design style of app, which are as follows:
- Prompt box 1: indicates that a user refuses permission.
- Prompt box 2: show the built-in AppSettingsDialog when the user refuses permission and chooses not to ask again.
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());
// (Optional) Check whether the user denied any permissions and checked "NEVER ASK AGAIN."
// This will display a dialog directing them to enable the permission in app settings.
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this).build().show(); }}Copy the code
Click OK to jump to the application information in the Settings for changing permissions
public void onClick(DialogInterface dialog, int which) {
if (which == Dialog.BUTTON_POSITIVE) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", getPackageName(), null));
intent.addFlags(mIntentFlags);
startActivityForResult(intent, APP_SETTINGS_RC);
} else if (which == Dialog.BUTTON_NEGATIVE) {
setResult(Activity.RESULT_CANCELED);
finish();
} else {
throw new IllegalStateException("Unknown button type: "+ which); }}Copy the code
Second, the implementation
- Prompt 2 is easy to replace, just replace AppSettingsDialog with your own Dialog.
override fun onPermissionsDenied(requestCode: Int, perms: List<String>) {
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
CommonDialog.Builder(this).build().show()
}
}
Copy the code
- Prompt 1 did not find a method to expose the replacement.
Call for a time limit:
private fun requestPermission(vararg perms: String) {
val request = PermissionRequest.Builder(this, REQUEST_CODE_PERMISSIONS, *perms)
.setRationale("This app may not work correctly without the requested permissions.")
.setPositiveButtonText("Sure")
.setNegativeButtonText("Cancel")
.build()
EasyPermissions.requestPermissions(request)
}
Copy the code
Get the PermissionHelper from the PermissionRequest getHelper() and requestPermissions from the requestPermissions method
public static void requestPermissions(PermissionRequest request) {
// Check for permissions before dispatching the request
if (hasPermissions(request.getHelper().getContext(), request.getPerms())) {
notifyAlreadyHasPermissions(
request.getHelper().getHost(), request.getRequestCode(), request.getPerms());
return;
}
// Request permissions
request.getHelper().requestPermissions(
request.getRationale(),
request.getPositiveButtonText(),
request.getNegativeButtonText(),
request.getTheme(),
request.getRequestCode(),
request.getPerms());
}
Copy the code
The PermissionHelper is created when the PermissionRequest is created
public Builder(@NonNull Activity activity, int requestCode,
@NonNull @Size(min = 1) String... perms) {
mHelper = PermissionHelper.newInstance(activity);
mRequestCode = requestCode;
mPerms = perms;
}
public Builder(@NonNull Fragment fragment, int requestCode,
@NonNull @Size(min = 1) String... perms) {
mHelper = PermissionHelper.newInstance(fragment);
mRequestCode = requestCode;
mPerms = perms;
}
Copy the code
PermissionHelper call showRequestPermissionRationale display box
public void requestPermissions(@NonNull String rationale,
@NonNull String positiveButton,
@NonNull String negativeButton,
@StyleRes int theme,
int requestCode,
@NonNull String... perms) {
if (shouldShowRationale(perms)) {
showRequestPermissionRationale(
rationale, positiveButton, negativeButton, theme, requestCode, perms);
} else{ directRequestPermissions(requestCode, perms); }}Copy the code
PermissionHelper is an abstract class with the following inheritance
Look at the find a BaseSupportPermissionsHelper showRequestPermissionRationale method
public void showRequestPermissionRationale(@NonNull String rationale,
@NonNull String positiveButton,
@NonNull String negativeButton,
@StyleRes int theme,
int requestCode,
@NonNull String... perms) {
FragmentManager fm = getSupportFragmentManager();
// Check if fragment is already showing
Fragment fragment = fm.findFragmentByTag(RationaleDialogFragmentCompat.TAG);
if (fragment instanceof RationaleDialogFragmentCompat) {
Log.d(TAG, "Found existing fragment, not showing rationale.");
return;
}
RationaleDialogFragmentCompat
.newInstance(rationale, positiveButton, negativeButton, theme, requestCode, perms)
.showAllowingStateLoss(fm, RationaleDialogFragmentCompat.TAG);
}
Copy the code
RationaleDialogFragmentCompat inherited from DialogFragment
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Rationale dialog should not be cancelable
setCancelable(false);
// Get config from arguments, create click listener
RationaleDialogConfig config = new RationaleDialogConfig(getArguments());
RationaleDialogClickListener clickListener =
new RationaleDialogClickListener(this, config, mPermissionCallbacks, mRationaleCallbacks);
// Create an AlertDialog
return config.createSupportDialog(getContext(), clickListener);
}
Copy the code
RationaleDialogConfig:
AlertDialog createSupportDialog(Context context, Dialog.OnClickListener listener) {
AlertDialog.Builder builder;
if (theme > 0) {
builder = new AlertDialog.Builder(context, theme);
} else {
builder = new AlertDialog.Builder(context);
}
return builder
.setCancelable(false)
.setPositiveButton(positiveButton, listener)
.setNegativeButton(negativeButton, listener)
.setMessage(rationaleMsg)
.create();
}
Copy the code
It is possible to download a copy of the source code to replace the default AlertDialog and package it. Another solution is used here: you can hook the mHelper for PermissionRequest
private final PermissionHelper mHelper;
Copy the code
Change mHelper showRequestPermissionRationale method to the pop-up Dialog, first define a proxy class:
public class PermissionsHelperProxy<T>(
private val permissionHelper: BaseSupportPermissionsHelper<T>
) : BaseSupportPermissionsHelper<T>(permissionHelper.host!!) {
override fun directRequestPermissions(requestCode: Int.vararg perms: String?). {
permissionHelper.directRequestPermissions(requestCode, *perms)
}
override fun shouldShowRequestPermissionRationale(perm: String): Boolean {
return permissionHelper.shouldShowRequestPermissionRationale(perm)
}
override fun getContext(a): Context {
return permissionHelper.context
}
override fun getSupportFragmentManager(a): FragmentManager {
return permissionHelper.supportFragmentManager
}
override fun showRequestPermissionRationale(
rationale: String,
positiveButton: String,
negativeButton: String.@StyleRes theme: Int,
requestCode: Int.vararg perms: String
) {
CommonDialog.Builder(context).build().show()
}
Copy the code
Replace at the limit of claim:
private fun requestPermission(vararg perms: String) {
val request = PermissionRequest.Builder(this, REQUEST_CODE_PERMISSIONS, *perms)
.setRationale("This app may not work correctly without the requested permissions.")
.setPositiveButtonText("Sure")
.setNegativeButtonText("Cancel")
.build()
try {
val clazz = request.javaClass
val field = clazz.getDeclaredField("mHelper")
field.isAccessible = true
val permissionHelper =
field.get(request) asBaseSupportPermissionsHelper<AppCompatActivity? > field.set(request, PermissionsHelperProxy(permissionHelper))
} catch (e: Exception) {
}
EasyPermissions.requestPermissions(request)
}
Copy the code
Success: