SkillAgentSearch skills...

XXPermissions

Android Permissions Framework, Adapt to Android 16

Install / Use

/learn @getActivity/XXPermissions

README

English Doc

权限请求框架

集成步骤

  • 如果你的项目 Gradle 配置是在 7.0 以下,需要在 build.gradle 文件中加入
allprojects {
    repositories {
        // JitPack 远程仓库:https://jitpack.io
        maven { url 'https://jitpack.io' }
    }
}
  • 如果你的 Gradle 配置是 7.0 及以上,则需要在 settings.gradle 文件中加入
dependencyResolutionManagement {
    repositories {
        // JitPack 远程仓库:https://jitpack.io
        maven { url 'https://jitpack.io' }
    }
}
  • 配置完远程仓库后,在项目 app 模块下的 build.gradle 文件中加入远程依赖
android {
    // 支持 JDK 1.8 及以上
    compileOptions {
        targetCompatibility JavaVersion.VERSION_1_8
        sourceCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    // 设备兼容框架:https://github.com/getActivity/DeviceCompat
    implementation 'com.github.getActivity:DeviceCompat:2.3'
    // 权限请求框架:https://github.com/getActivity/XXPermissions
    implementation 'com.github.getActivity:XXPermissions:28.0'
}

Support 库兼容

  • 方案一:沿用旧版本框架的远程依赖
dependencies {
    // 设备兼容框架:https://github.com/getActivity/DeviceCompat
    implementation 'com.github.getActivity:DeviceCompat:2.3'
    // 权限请求框架:https://github.com/getActivity/XXPermissions
    implementation 'com.github.getActivity:XXPermissions:26.8'
}
  • 方案二:如果你的项目仍处于 Support 阶段,目前不方便转到 AndroidX 中来,但又想用最新版本的框架,可以使用 Google 提供的 JetifierStandalone 工具将已发布版本 Release 中的 aar 包通过反向模式转成 Support 版本的 aar 包来使用。

  • 上述两种方案任选其一即可,但是仍旧不推荐你那样做,因为这些只是权宜之计,并非长久之计,框架后续的版本已不再支持 Support 项目,最好的方案是将项目迁移到 AndroidX

  • 将项目从 Support 迁移 AndroidX 相关的教程:AndroidX 踩坑指南

分区存储

  • 如果项目已经适配了 Android 10 分区存储特性,请在 AndroidManifest.xml 中加入
<manifest>

    <application>

        <!-- 告知 XXPermissions 当前项目已经适配了分区存储特性 -->
        <meta-data
            android:name="ScopedStorage"
            android:value="true" />

    </application>

</manifest>
  • 如果当前项目没有适配这特性,那么这一步骤可以忽略

  • 需要注意的是:这个选项是框架用于判断当前项目是否适配了分区存储,需要注意的是,如果你的项目已经适配了分区存储特性,可以使用 READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE 来申请权限,如果你的项目还没有适配分区特性,就算申请了 READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE 权限也会导致无法正常读取外部存储上面的文件,如果你的项目没有适配分区存储,请使用 MANAGE_EXTERNAL_STORAGE 来申请权限,这样才能正常读取外部存储上面的文件,你如果想了解更多关于 Android 10 分区存储的特性,可以点击此处查看和学习

框架混淆规则

  • 框架已经在内部自动帮你添加了框架的混淆规则,在你添加框架的依赖远程库的时候,框架的混淆规则也会一同携带到你的项目中,你无需自己手动添加,具体的混淆规则内容 可点击此处查看

一句代码搞定权限请求,从未如此简单

  • Java 用法示例
XXPermissions.with(this)
    // 申请多个权限
    .permission(PermissionLists.getRecordAudioPermission())
    .permission(PermissionLists.getCameraPermission())
    // 设置不触发错误检测机制(局部设置)
    //.unchecked()
    .request(new OnPermissionCallback() {

        @Override
        public void onResult(@NonNull List<IPermission> grantedList, @NonNull List<IPermission> deniedList) {
            boolean allGranted = deniedList.isEmpty();
            if (!allGranted) {
                // 判断请求失败的权限是否被用户勾选了不再询问的选项
                boolean doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList);
                // 在这里处理权限请求失败的逻辑
                ......
                return;
            }
            // 在这里处理权限请求成功的逻辑
            ......
        }
    });
  • Kotlin 用法示例

XXPermissions.with(this)
    // 申请多个权限
    .permission(PermissionLists.getRecordAudioPermission())
    .permission(PermissionLists.getCameraPermission())
    // 设置不触发错误检测机制(局部设置)
    //.unchecked()
    .request(object : OnPermissionCallback {
        
        override fun onResult(grantedList: MutableList<IPermission>, deniedList: MutableList<IPermission>) {
            val allGranted = deniedList.isEmpty()
            if (!allGranted) {
                // 判断请求失败的权限是否被用户勾选了不再询问的选项
                val doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList)
                // 在这里处理权限请求失败的逻辑
                // ......
                return
            }
            // 在这里处理权限请求成功的逻辑
            // ......
        }
    })

框架其他 API 介绍

// 判断一个或多个权限是否全部授予了
XXPermissions.isGrantedPermission(@NonNull Context context, @NonNull IPermission permission);
XXPermissions.isGrantedPermissions(@NonNull Context context, @NonNull IPermission[] permissions);
XXPermissions.isGrantedPermissions(@NonNull Context context, @NonNull List<IPermission> permissions);

// 从权限列表中获取已授予的权限
XXPermissions.getGrantedPermissions(@NonNull Context context, @NonNull IPermission[] permissions);
XXPermissions.getGrantedPermissions(@NonNull Context context, @NonNull List<IPermission> permissions);

// 从权限列表中获取没有授予的权限
XXPermissions.getDeniedPermissions(@NonNull Context context, @NonNull IPermission[] permissions);
XXPermissions.getDeniedPermissions(@NonNull Context context, @NonNull List<IPermission> permissions);

// 判断两个权限是否相等
XXPermissions.equalsPermission(@NonNull IPermission permission, @NonNull IPermission permission2);
XXPermissions.equalsPermission(@NonNull IPermission permission, @NonNull String permissionName);
XXPermissions.equalsPermission(@NonNull String permissionName1, @NonNull String permissionName2);

// 判断权限列表中是否包含某个权限
XXPermissions.containsPermission(@NonNull List<IPermission> permissions, @NonNull IPermission permission);
XXPermissions.containsPermission(@NonNull List<IPermission> permissions, @NonNull String permissionName);

// 判断某个权限是否为健康权限
XXPermissions.isHealthPermission(@NonNull IPermission permission);

// 判断一个或多个权限是否被勾选了《不再询问》的选项(一定要在权限申请的回调方法中调用才有效果)
XXPermissions.isDoNotAskAgainPermission(@NonNull Activity activity, @NonNull IPermission permission);
XXPermissions.isDoNotAskAgainPermissions(@NonNull Activity activity, @NonNull IPermission[] permissions);
XXPermissions.isDoNotAskAgainPermissions(@NonNull Activity activity, @NonNull List<IPermission> permissions);

// 跳转到权限设置页(Context 版本)
XXPermissions.startPermissionActivity(@NonNull Context context);
XXPermissions.startPermissionActivity(@NonNull Context context, @NonNull IPermission... permissions);
XXPermissions.startPermissionActivity(@NonNull Context context, @NonNull List<IPermission> permissions);

// 跳转到权限设置页(Activity 版本)
XXPermissions.startPermissionActivity(@NonNull Activity activity);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull IPermission... permissions);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull List<IPermission> permissions);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull List<IPermission> permissions, @IntRange(from = 1, to = 65535) int requestCode);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull IPermission permission, @Nullable OnPermissionCallback callback);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull List<IPermission> permissions, @Nullable OnPermissionCallback callback);

// 跳转到权限设置页(Android Fragment 版本)
XXPermissions.startPermissionActivity(@NonNull Fragment fragment);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull IPermission... permissions);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull List<IPermission> permissions);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull List<IPermission> permissions, @IntRange(from = 1, to = 65535) int requestCode);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull IPermission permission, @Nullable OnPermissionCallback callback);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull List<IPermission> permissions, @Nullable OnPermissionCallback callback);

// 跳转到权限设置页(AndroidX Fragment 版本)
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment);
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment, @NonNull IPermission... permissions);
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment, @NonNull List<IPermission> permissions);
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment, @NonNull List<IPermission> permissions, @IntRange(from = 1, to = 65535) int requestCo
View on GitHub
GitHub Stars6.7k
CategoryDevelopment
Updated6d ago
Forks891

Languages

Java

Security Score

100/100

Audited on Mar 23, 2026

No findings