PermissionX

repository·master·Indexed 25 days ago

https://github.com/guolindev/permissionx

An Android extension library designed to simplify requesting runtime permissions. It provides tools for handling complex scenarios, such as showing rationale dialogs via onExplainRequestReason, directing users to app settings when permissions are permanently denied using onForwardToSettings, and implementing custom UI through CustomDialogFragment and RationaleDialog. The library supports pre-request explanations via explainReasonBeforeRequest() and provides detailed request callbacks including allGranted, grantedList, and deniedList.

Tokens
2.8K
Snippets
8
Records
15
Agent score
87%

What's inside PermissionX

  1. Install PermissionX via Gradle

    master

    To use PermissionX in your Android project, add the following dependency to your build.gradle file. Ensure you have google() and mavenCentral() in your repositories block.

    repositories {
      google()
      mavenCentral()
    }
    
    dependencies {
        implementation 'com.guolindev.permissionx:permissionx:1.8.1'
    }
  2. Show rationale before requesting permissions

    master

    To improve user experience, you can show a rationale dialog before the actual system permission request occurs by using the .explainReasonBeforeRequest() method.

    PermissionX.init(activity)
        .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.CAMERA, Manifest.permission.CALL_PHONE)
        .explainReasonBeforeRequest()
        .request { allGranted, grantedList, deniedList ->
            // handle result
        }
  3. Handle 'Never Ask Again' using onForwardToSettings

    master

    When a user denies permissions and selects 'never ask again', you can use .onForwardToSettings to guide them to the app settings. This should be chained before the .request() method.

    Use scope.showForwardToSettingsDialog(deniedList, message, positiveButtonText, negativeButtonText):

    • If the user clicks the positive button, PermissionX will open the app's settings page. When the user returns to the app, PermissionX will automatically re-request the necessary permissions.
    • Parameters are similar to showRequestReasonDialog.
    PermissionX.init(activity)
        .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.CAMERA, Manifest.permission.CALL_PHONE)
        .onExplainRequestReason { scope, deniedList ->
            scope.showRequestReasonDialog(deniedList, "Core fundamental are based on these permissions", "OK", "Cancel")
        }
        .onForwardToSettings { scope, deniedList ->
            scope.showForwardToSettingsDialog(deniedList, "You need to allow necessary permissions in Settings manually", "OK", "Cancel")
        }
        .request { allGranted, grantedList, deniedList ->
            if (allGranted) {
                Toast.makeText(this, "All permissions are granted", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(this, "These permissions are denied: $deniedList", Toast.LENGTH_LONG).show()
            }
        }
  4. Show rationale dialog using onExplainRequestReason

    master

    If a user denies a permission, you can use .onExplainRequestReason to show a rationale dialog explaining why the permission is needed. This should be chained before the .request() method.

    Use scope.showRequestReasonDialog(deniedList, message, positiveButtonText, negativeButtonText):

    • deniedList: The list of denied permissions.
    • message: The explanation text.
    • positiveButtonText: Text for the positive button. If clicked, PermissionX will re-request the permissions.
    • negativeButtonText: (Optional) Text for the negative button. If omitted, the dialog becomes uncancelable.
    PermissionX.init(activity)
        .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.CAMERA, Manifest.permission.CALL_PHONE)
        .onExplainRequestReason { scope, deniedList ->
            scope.showRequestReasonDialog(deniedList, "Core fundamental are based on these permissions", "OK", "Cancel")
        }
        .request { allGranted, grantedList, deniedList ->
            if (allGranted) {
                Toast.makeText(this, "All permissions are granted", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(this, "These permissions are denied: $deniedList", Toast.LENGTH_LONG).show()
            }
        }
  5. Request Android runtime permissions

    master

    To request permissions, first declare them in your AndroidManifest.xml. Then, use PermissionX.init(activity) (where activity is a FragmentActivity or Fragment), specify the permissions via .permissions(), and call .request().

    The .request() callback provides:

    • allGranted: Boolean indicating if all requested permissions were granted.
    • grantedList: List of permissions that were granted.
    • deniedList: List of permissions that were denied.
    PermissionX.init(activity)
        .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.CAMERA, Manifest.permission.CALL_PHONE)
        .request { allGranted, grantedList, deniedList ->
            if (allGranted) {
                Toast.makeText(this, "All permissions are granted", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(this, "These permissions are denied: $deniedList", Toast.LENGTH_LONG).show()
            }
        }
  6. Implement a custom RationaleDialog using DefaultDialog

    master

    If you do not provide a custom rationale dialog when using PermissionX, the library falls back to DefaultDialog. DefaultDialog is a standard implementation of the RationaleDialog interface that displays a message, a list of requested permissions (grouped by permission group), and positive/negative action buttons.

    While DefaultDialog is provided as a fallback, you can implement your own version of RationaleDialog to have full control over the UI. To be compatible with PermissionX's rationale flow, your implementation must provide:

    • getPositiveButton(): A View representing the button to continue requesting permissions.
    • getNegativeButton(): A View? representing the button to abort the request. If you return null, it implies all permissions are necessary and no abort option is provided.
    • getPermissionsToRequest(): A List<String> of the permissions that need to be requested again.
  7. Show a rationale dialog using ExplainScope

    master

    When implementing permission explanation logic via ExplainReasonCallback or ExplainReasonCallbackWithBeforeParam, you can use ExplainScope to show a dialog explaining why permissions are necessary. You have three ways to provide the dialog content:

    1. Using raw strings: Provide the list of permissions, a message, and button text.
    2. Using a RationaleDialog: Provide a pre-configured dialog object.
    3. Using a RationaleDialogFragment: Provide a DialogFragment to manage the explanation UI.
  8. Implement a custom rationale dialog with CustomDialogFragment

    master

    If you want to provide a custom UI for explaining why permissions are needed (rationale), you can extend CustomDialogFragment. This class is a specialized implementation of RationaleDialogFragment that allows you to pass a custom message and a list of permissions to be displayed in a grouped format.

    To use it, instantiate it with a custom message and the list of permission strings you wish to display. The dialog will automatically group permissions by their Android permission groups (e.g., grouping READ_CONTACTS and WRITE_CONTACTS under CONTACTS).

  9. Configure permission request callbacks

    master

    You can provide custom callbacks to handle different stages of the permission request lifecycle using PermissionBuilder methods:

    • onExplainRequestReason(callback): Triggered when permissions need to be explained to the user (e.g., after a denial). You can use ExplainReasonCallback or ExplainReasonCallbackWithBeforeParam to receive information about whether the explanation is happening before or after the request.
    • onForwardToSettings(callback): Triggered when a user has permanently denied a permission and you want to guide them to the app settings.
    • request(callback): The final callback that returns the results of the permission request, including allGranted, grantedList, and deniedList.