# XXPermissions: one call for Android runtime permissions, including the special ones

> XXPermissions wraps Android runtime permission requests and the special permission flows (system alert window, usage stats, notification listener, accessibility) behind a single builder. It is aimed at Android developers who are tired of writing per-version branching by hand. The trade-off is an extra dependency and a framework that assumes you have moved to AndroidX.

**getActivity/XXPermissions** — Android Permissions Framework, Adapt to Android 17

- Repository: https://github.com/getActivity/XXPermissions
- Stars: 6,810 · Forks: 900
- Language: Java
- License: Apache-2.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/getactivity-xxpermissions

## The problem XXPermissions solves for Android apps

Android runtime permissions are not one API. They are a family of APIs that changed shape across releases, and a handful of permissions that never appear in the standard dialog at all. A camera or microphone request goes through the normal grant flow. A request to draw over other apps, read usage statistics, bind a notification listener, become a device admin or run an accessibility service sends the user to a settings screen that your app has to locate and then re-check on return. Doing that by hand means a switch over permission names, a check against the API level, and an Activity result path for each one.

XXPermissions targets that gap. The README describes it as a permission request framework and the repository topics list it alongside easypermission, permissionx, rxpermissions and permissionsdispatcher, which places it in the same category as the other wrappers around ActivityCompat.requestPermissions. What separates it is the scope: the demo screenshots in the repository cover system alert window, notification service, full screen notifications, write settings, manage storage, usage stats, exact alarm, bind notification listener, notification policy access, ignore battery optimizations, bind VPN service, picture in picture, accessibility service, device admin, installed apps and health data. That is a longer list than most wrappers attempt.

Who it is for: an app developer who already knows which permissions the app needs and does not want to own the version-branching logic that gets the user there. It is not a permission rationale designer, and it does not decide what to ask for.

## How the request flow and the special permissions actually work

The public surface is a builder. You call XXPermissions.with(context), chain .permission(...) for each permission you want, and finish with .request(callback). The callback receives two lists, grantedList and deniedList. The README's own example treats an empty deniedList as full success, and when it is not empty it calls XXPermissions.isDoNotAskAgainPermissions(activity, deniedList) to find out whether the user ticked the never-ask-again option. That second call is documented as valid only inside the request callback, which is a real constraint: you cannot check that flag later from an arbitrary place in your code.

Permissions are passed as IPermission objects produced by PermissionLists, for example PermissionLists.getRecordAudioPermission() and PermissionLists.getCameraPermission(). The framework also exposes static helpers for the questions that surround a request: isGrantedPermission and isGrantedPermissions for checking state, getGrantedPermissions and getDeniedPermissions for splitting a list, equalsPermission and containsPermission for comparisons, and isHealthPermission for identifying health permissions.

There is an error-detection mechanism that the builder can turn off per request with .unchecked(). The README shows it commented out in both the Java and Kotlin examples without explaining what triggers it, so treat it as a switch you enable only after you understand why the framework is complaining. The library ships its own ProGuard rules. According to the README, the rules travel with the dependency and you do not add them yourself; the file is library/proguard-permissions.pro if you want to read them.

## Installing XXPermissions and making a first request

The library is distributed through JitPack, not Maven Central, so the repository has to be declared before the dependency resolves. If your Gradle configuration is below 7.0, the README puts the repository in the root build.gradle file:

```groovy
allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}
```

If your Gradle configuration is 7.0 or above, the same repository goes into settings.gradle instead:

```groovy
dependencyResolutionManagement {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}
```

Then add the dependency in the app module. The README pairs XXPermissions with a second library from the same author, DeviceCompat, and states that the project needs Java 8 or above in compileOptions:

```groovy
android {
    compileOptions {
        targetCompatibility JavaVersion.VERSION_1_8
        sourceCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'com.github.getActivity:DeviceCompat:2.6'
    implementation 'com.github.getActivity:XXPermissions:28.3'
}
```

A minimal request in Java looks like this. The two permissions come from PermissionLists, and the callback branches on whether deniedList is empty:

```java
XXPermissions.with(this)
    .permission(PermissionLists.getRecordAudioPermission())
    .permission(PermissionLists.getCameraPermission())
    .request((grantedList, deniedList) -> {
        if (!deniedList.isEmpty()) {
            boolean doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList);
            return;
        }
        // handle the granted case here
    });
```

The Kotlin form is the same builder with a trailing lambda, and the README shows it returning from the lambda with return@request on the failure branch. What you should see after running either version is the system permission dialog for the permissions the user has not yet decided on, followed by your callback. If a permission is already granted, no dialog appears for it.

## Scoped storage is a decision the library makes you declare

The one piece of configuration that is easy to get wrong is the scoped storage flag. If your project has adapted Android 10 scoped storage, the README asks you to declare that in the manifest so the framework knows:

```xml
<manifest>
    <application>
        <meta-data
            android:name="ScopedStorage"
            android:value="true" />
    </application>
</manifest>
```

If your project has not adapted scoped storage, the README says to skip this step. The consequence is not cosmetic. With the flag set, the README states you can request READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE. Without it, requesting those two permissions will not let the app read files on external storage, and the README directs you to MANAGE_EXTERNAL_STORAGE instead. In other words, the meta-data is not a hint that changes which dialog appears; it changes which permission actually grants access. Declaring it wrongly gives you an app that requests successfully and still cannot open the file.

## Where XXPermissions is the wrong choice

The clearest limitation is the AndroidX requirement. The README states that later versions of the framework no longer support Support projects, and it offers two workarounds for teams that have not migrated: pinning to older artifacts (DeviceCompat 2.3 with XXPermissions 26.8) or running the released aar through Google's JetifierStandalone in reverse mode to produce a Support-compatible aar. The README itself calls these stopgaps rather than long-term options, and the honest reading is that a Support project adopting the current version is taking on a migration it has been avoiding.

The second limitation is that XXPermissions is a request layer, not a policy layer. It tells you whether the user granted, denied, or denied with never-ask-again. It does not tell you what to show before the request, how to explain a denial, or when to stop asking. The repository ships a demo APK and screenshots of each special permission screen, which is useful for seeing what the user will face, but the rationale copy and the retry logic are yours.

Third, the special permissions still depend on the user finding a system settings screen and toggling something. A wrapper can take you there and can re-check on return, but it cannot make the flow frictionless, and the README's own documentation is thinner on those flows than on the standard request path. If your app depends on accessibility service or device admin, budget time for manual testing across manufacturer builds.

## How it compares with RxPermissions and PermissionsDispatcher

The repository topics name rxpermissions and permissionsdispatcher directly, so the comparison is fair. RxPermissions models a permission request as an Observable you compose into a stream, which fits codebases already built around RxJava and is awkward in codebases that are not. PermissionsDispatcher generates annotated methods at compile time, so the request flow is expressed as annotations on your Activity or Fragment and the generated code does the wiring; that keeps the call site declarative but adds an annotation processor to the build and ties requests to the annotated component.

XXPermissions takes the third route: a runtime builder with a callback and no annotation processing. The difference that matters in practice is coverage. The README's demo covers special permissions such as system alert window, usage stats, notification listener, accessibility service and device admin, which a plain wrapper around ActivityCompat.requestPermissions does not handle. If all you ever request is camera and location, the builder is convenient but not decisive. If you also need the settings-screen permissions, that coverage is the reason to pick this one.

## Maintenance, versioning and licence

The repository is not archived, and the last push was on 2026-06-21, which is the same date as release 28.3. The release history shows 28.3, 28.2 and 28.0, so the project has shipped more than one version in the recent past, and the description claims adaptation to Android 17. The README's compatibility advice is version-specific in both directions: the current line for AndroidX projects, and the 26.8 line paired with DeviceCompat 2.3 for Support projects. When you upgrade, check the release notes for the version you are moving to rather than assuming the API is stable across the major number, and note that DeviceCompat is a separate dependency with its own version, so the two can drift apart.

The licence is Apache-2.0, which is a permissive licence that generally allows commercial use and modification provided the notice and licence text are preserved. That is a statement about the licence text, not legal advice; if your organisation has a policy on third-party dependencies, run the aar and its transitive dependencies through it. The distribution channel matters here too: JitPack builds artifacts from the repository, so your build depends on JitPack being reachable, which is why the repository declaration comes before the dependency in the install steps.

## Conclusion

Adopt XXPermissions if you are on AndroidX, writing Java or Kotlin, and you keep re-implementing the same request flow plus the special permission screens for system alert window, usage stats, notification listener or accessibility. Do not adopt it if your project is still on the Support library and you are not willing to migrate, since the README states later versions no longer support Support projects, or if you only need one runtime permission and would rather not add a dependency. Before wiring it in, verify three things: that your Gradle configuration can reach the JitPack repository, that your compileOptions target Java 8 or above, and whether your project has adapted scoped storage, because that answer decides whether you declare the ScopedStorage meta-data and request MANAGE_EXTERNAL_STORAGE instead of READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE.

## FAQ

### What are permissions in Android and what do they do?

They are the grants an app needs before it can use protected capabilities, and XXPermissions exists to request them. The framework's request callback returns the granted and denied lists, and its helpers such as isGrantedPermission let you check state without triggering a dialog.

### How do I add the XXPermissions dependency to my Android project?

Declare the JitPack repository, in the root build.gradle below Gradle 7.0 or in settings.gradle at 7.0 and above, then add the implementation line for com.github.getActivity:XXPermissions:28.3 in the app module. The README pairs it with com.github.getActivity:DeviceCompat:2.6 and requires compileOptions at Java 8 or above.

### Why does XXPermissions need the ScopedStorage meta-data in AndroidManifest.xml?

It tells the framework whether your project has adapted Android 10 scoped storage. With it declared you can request READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE; without it the README says those requests will not let you read external storage and you should use MANAGE_EXTERNAL_STORAGE instead.

### Does XXPermissions work with Kotlin as well as Java?

Yes. The README gives the same builder in both languages, with the Kotlin version using a trailing lambda and return@request on the failure branch. The permission objects come from PermissionLists in both cases.

### How do I know whether the user selected never ask again in XXPermissions?

Call XXPermissions.isDoNotAskAgainPermissions(activity, deniedList) inside the request callback. The README states this call only works when it is made from the permission request callback, so it cannot be deferred to another part of your code.

### Can I use XXPermissions in a project that still uses the Support library?

The README states that later versions no longer support Support projects. It lists two workarounds, pinning to XXPermissions 26.8 with DeviceCompat 2.3 or converting the released aar with JetifierStandalone in reverse mode, but describes both as temporary and recommends migrating to AndroidX.

## Sources

- [getActivity/XXPermissions on GitHub](https://github.com/getActivity/XXPermissions)
- [Issues](https://github.com/getActivity/XXPermissions/issues)
- [License: Apache-2.0](https://github.com/getActivity/XXPermissions/blob/master/LICENSE)
- [README](https://github.com/getActivity/XXPermissions/blob/master/README.md)
- [Releases](https://github.com/getActivity/XXPermissions/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/getactivity-xxpermissions
