Android动态申请权限,RxPermissions

android 6.0 (API 23) 之前应用的权限在安装时全部授予,运行时应用不再需要询问用户。

在 Android 6.0 或更高版本对权限进行了分类,对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予。

这样就不需要在安装时被强迫同意某些权限。

官网的写法

   /**
     * 官网的写法
     */
    public void requestPower() {
        //判断是否已经赋予权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            //如果应用之前请求过此权限但用户拒绝了请求,没有点击不再提醒,此方法将返回 true。
            //如果应用之前请求过此权限但用户拒绝了请求,点击了不再提醒,此方法将返回 false
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
                //这里可以写个对话框之类的项向用户解释为什么要申请权限,并在对话框的确认键后续再次申请权限
            } else {
                //申请权限,字符串数组内是一个或多个要申请的权限,1是申请权限结果的返回参数,在onRequestPermissionsResult可以得知申请结果
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA,}, 1);
            }
        }
    }

android6.0动态申请权限:9组27个

group:android.permission-group.CONTACTS
  permission:android.permission.WRITE_CONTACTS
  permission:android.permission.GET_ACCOUNTS
  permission:android.permission.READ_CONTACTS

group:android.permission-group.PHONE
  permission:android.permission.READ_CALL_LOG
  permission:android.permission.READ_PHONE_STATE
  permission:android.permission.CALL_PHONE
  permission:android.permission.WRITE_CALL_LOG
  permission:android.permission.USE_SIP
  permission:android.permission.PROCESS_OUTGOING_CALLS
  permission:com.android.voicemail.permission.ADD_VOICEMAIL

group:android.permission-group.CALENDAR
  permission:android.permission.READ_CALENDAR
  permission:android.permission.WRITE_CALENDAR

group:android.permission-group.CAMERA
  permission:android.permission.CAMERA

group:android.permission-group.SENSORS
  permission:android.permission.BODY_SENSORS

group:android.permission-group.LOCATION
  permission:android.permission.ACCESS_FINE_LOCATION
  permission:android.permission.ACCESS_COARSE_LOCATION

group:android.permission-group.STORAGE
  permission:android.permission.READ_EXTERNAL_STORAGE
  permission:android.permission.WRITE_EXTERNAL_STORAGE

group:android.permission-group.MICROPHONE
  permission:android.permission.RECORD_AUDIO

group:android.permission-group.SMS
  permission:android.permission.READ_SMS
  permission:android.permission.RECEIVE_WAP_PUSH
  permission:android.permission.RECEIVE_MMS
  permission:android.permission.RECEIVE_SMS
  permission:android.permission.SEND_SMS
  permission:android.permission.READ_CELL_BROADCASTS

步骤

1.先判断有没有权限

2.有:直接进行相关操作

3.没有:申请权限

4.授予了权限:直接进行相关操作

5.拒绝:没有勾选不再提醒,下次点击重新申请;勾选了不再提醒,去设置界面主动开启权限

申请单个权限

/**
 * 申请单个权限
 * <p>
 * ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission):
 * true:应如果应用之前请求过此权限但用户拒绝了请求,没有点击不再提醒,此方法将返回 true
 * false: 如果应用之前请求过此权限但用户拒绝了请求,点击了不再提醒,此方法将返回 false
 */
public class SinglePermissionActivity extends AppCompatActivity {

    private static final int REQUESET_PERMISSIONS_CODE = 1;

    private String[] permissions = {Manifest.permission.CALL_PHONE};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single_permission);
    }

    public void requestPermission(View view) {
        //版本>=23,动态申请的权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            //检查是否有权限
            checkPermissions();
        } else {
            //有权限,直接执行操作
            callPhone();
        }
    }

    private void checkPermissions() {
        //判断是否已经赋予权限
        if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) {
            //没有授予权限,申请权限
            ActivityCompat.requestPermissions(this, permissions, REQUESET_PERMISSIONS_CODE);
        } else {
            //授予了权限,直接进行相关操作
            callPhone();
        }
    }

    /**
     * 申请权限的回调
     *
     * @param requestCode  请求权限时传入的请求码,用于区别是哪一次请求的
     * @param permissions  所请求的所有权限的数组
     * @param grantResults 权限授予结果,和 permissions 数组参数中的权限一一对应,元素值为两种情况,如下:
     *                     允许: PackageManager.PERMISSION_GRANTED
     *                     拒绝: PackageManager.PERMISSION_DENIED
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == REQUESET_PERMISSIONS_CODE) {
            //允许了权限
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                callPhone();
            } else { //拒绝了该权限
                if (ActivityCompat.shouldShowRequestPermissionRationale(SinglePermissionActivity.this, permissions[0])) {
                    //如果应用之前请求过此权限但用户拒绝了请求,没有选中不再提醒,此方法将返回 true。
                    //可以写个对话框向用户解释为什么要申请权限,并在对话框的确认键后续再次申请权限
                    //也可以弹个Toast告诉用户权限被拒绝,再次点击的时候继续申请权限
                    Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
                } else {
                    //选中了不再提醒,提示用户去应用设置界面手动开启权限
                    showGoToAppSetttingDialog();
                }
            }
        }
    }

    private void showGoToAppSetttingDialog() {
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("权限不可用")
                .setMessage("请在-应用设置-权限-中,允许该权限!")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // 跳转到应用设置界面
                        goToAppSetting();
                        dialog.dismiss();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).setCancelable(false).show();
    }

    /**
     * 跳转到应用设置界面
     */
    private void goToAppSetting() {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivityForResult(intent, 123);
    }

    /**
     * 设置界面打开权限的回调
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 123) {
            //判断是否开启了权限
            if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) {
                //没有授予权限,申请权限
                // ActivityCompat.requestPermissions(this, permissions, REQUESET_PERMISSIONS_CODE);
            } else {
                //授予了权限,直接进行相关操作
                callPhone();
            }
        }
    }

    public void callPhone() {
        Toast.makeText(this, "有权限,执行操作", Toast.LENGTH_SHORT).show();
    }
}

申请多个权限

public class MuiltPermissionActivity extends AppCompatActivity {

    private static final int REQUESET_PERMISSIONS_CODE = 1;

    //需要申请权限的集合
    private List<String> mPermissionList = new ArrayList<>();

    private String[] permissions = {
            Manifest.permission.READ_CONTACTS,
            Manifest.permission.WRITE_EXTERNAL_STORAGE

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_muilt_permission);
    }

    public void requestPermission(View view) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            checkPermissions();
        } else {
            doBackup();
        }
    }

    private void checkPermissions() {
        mPermissionList.removeAll(mPermissionList);
        for (int i = 0; i < permissions.length; i++) {
            if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                mPermissionList.add(permissions[i]);
            }
        }
        if (mPermissionList.isEmpty()) { //未授予的权限为空,表示权限都授予了
            //可以直接执行相关操作
            doBackup();
        } else {
            //申请权限
            String[] permissions = mPermissionList.toArray(new String[mPermissionList.size()]);//将List转为数组
            ActivityCompat.requestPermissions(this, permissions, REQUESET_PERMISSIONS_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == REQUESET_PERMISSIONS_CODE) {
            boolean isAllGranted = true; //权限是否全部授予
            boolean isNeedGoToSettingOpenPermisssion = false; //是否需要去设置界面开启权限

            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { //拒绝
                    isAllGranted = false;

                    if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) {
                        //点击了不再提醒,需要去设置界面开启权限
                        isNeedGoToSettingOpenPermisssion = true;
                    } else {
                        //没有点击不再提醒,不需要去设置界面开启权限
                    }
                }
            }

            //权限全部授予了,执行操作
            if (isAllGranted) {
                doBackup();
            } else {
                if (isNeedGoToSettingOpenPermisssion) {
                    showGoToAppSetttingDialog();
                } else {
                    Toast.makeText(this, "有权限被拒绝", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    private void showGoToAppSetttingDialog() {
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("权限不可用")
                .setMessage("请在-应用设置-权限-中,允许该权限!")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // 跳转到应用设置界面
                        goToAppSetting();
                        dialog.dismiss();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).setCancelable(false).show();
    }

    /**
     * 跳转到应用设置界面
     */
    private void goToAppSetting() {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivityForResult(intent, 123);
    }

    /**
     * 设置界面打开权限的回调
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 123) {
            //判断是否开启了权限
            mPermissionList.removeAll(mPermissionList);
            for (int i = 0; i < permissions.length; i++) {
                if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                    mPermissionList.add(permissions[i]);
                }
            }
            if (mPermissionList.isEmpty()) { //未授予的权限为空,表示权限都授予了
                //可以直接执行相关操作
                doBackup();
            } else {
                //申请权限
                //String[] permissions = mPermissionList.toArray(new String[mPermissionList.size()]);//将List转为数组
                //ActivityCompat.requestPermissions(this, permissions, REQUESET_PERMISSIONS_CODE);
            }
        }
    }


    private void doBackup() {
        // 本文主旨是讲解如果动态申请权限, 具体备份代码不再展示, 就假装备份一下
        Toast.makeText(this, "正在备份通讯录...", Toast.LENGTH_SHORT).show();
    }
}

PermissionUtils:动态申请权限工具类

/**
 * Cerated by xiaoyehai
 * description : 动态申请权限工具类
 */
public class PermissionUtils {

    public static final int GOTO_SEETING_CODE = 152;

    /**
     * 判断是否有权限
     *
     * @param context
     * @param perms
     * @return
     */
    public static boolean hasPermissions(@NonNull Context context, @Size(min = 1) @NonNull String... perms) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }

        if (context == null) {
            throw new IllegalArgumentException("Can't check permissions for null context");
        }

        for (String perm : perms) {
            if (ContextCompat.checkSelfPermission(context, perm) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }


    /**
     * 申请权限
     */
    public static void requestPermissions(@NonNull Activity activity, int requestCode, String[] permissions) {

        List<String> permissionList = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                permissionList.add(permission);
            }
        }

        String[] permissionsArray = permissionList.toArray(new String[permissionList.size()]);//将List转为数组
        if (permissionList.isEmpty()) {
            //不可能为空,因为我们在调用这个方法的时候会先去判断是否有权限,没有权限才会调用这个方法
        } else {
            ActivityCompat.requestPermissions(activity, permissionsArray, requestCode);
            //返回结果onRequestPermissionsResult
        }
    }

    /**
     * 申请权限的回调
     *
     * @param requestCode  请求权限时传入的请求码,用于区别是哪一次请求的
     * @param permissions  所请求的所有权限的数组
     * @param grantResults 权限授予结果,和 permissions 数组参数中的权限一一对应,元素值为两种情况,如下:
     *                     授予: PackageManager.PERMISSION_GRANTED
     *                     拒绝: PackageManager.PERMISSION_DENIED
     */
    public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                                  @NonNull int[] grantResults, @NonNull PermissionCallbacks callBack) {
        //授予的权限。
        List<String> granted = new ArrayList<>();

        //拒绝的权限
        List<String> denied = new ArrayList<>();

        for (int i = 0; i < permissions.length; i++) {
            String perm = permissions[i];
            if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                granted.add(perm);
            } else {
                denied.add(perm);
            }
        }

        if (null != callBack) {
            if (denied.isEmpty()) {
                callBack.onPermissionsAllGranted(requestCode, granted);
            }

            if (!denied.isEmpty()) {
                callBack.onPermissionsDenied(requestCode, denied);
            }
        }
    }

    /**
     * 用户是否拒绝权限,并检查“不要提醒”。
     *
     * @param activity
     * @param perms
     * @return
     */
    public static boolean somePermissionPermanentlyDenied(Activity activity, @NonNull List<String> perms) {
        for (String deniedPermission : perms) {
            if (permissionPermanentlyDenied(activity, deniedPermission)) {
                return true;
            }
        }

        return false;
    }

    public static boolean permissionPermanentlyDenied(Activity activity, @NonNull String perms) {
        if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, perms)) {
            return true;
        }
        return false;
    }


    public static void showDialogGoToAppSettting(final Activity activity) {
        AlertDialog dialog = new AlertDialog.Builder(activity)
                .setMessage("去设置界面开启权限")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // 跳转到应用设置界面
                        goToAppSetting(activity);
                        dialog.dismiss();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).setCancelable(false).show();
    }


    /**
     * 跳转到应用设置界面
     */
    public static void goToAppSetting(Activity activity) {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
        intent.setData(uri);
        activity.startActivityForResult(intent, GOTO_SEETING_CODE);
    }

    public static void showPermissionReason(final int requestCode, final Activity activity, final String[] permission, String s) {
        AlertDialog dialog = new AlertDialog.Builder(activity)
                .setMessage(s)
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        requestPermissions(activity, requestCode, permission);
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).setCancelable(false).show();
    }


    public interface PermissionCallbacks {

        /**
         * 权限全部被允许
         */
        void onPermissionsAllGranted(int requestCode, List<String> perms);

        /**
         * 有权限被拒绝
         */
        void onPermissionsDenied(int requestCode, List<String> perms);

    }
}

使用

public class PermissionUtilsActivity extends AppCompatActivity implements PermissionUtils.PermissionCallbacks {

    private static final int REQUESET_PERMISSIONS_CODE = 1;

    private String[] permissions = {Manifest.permission.CALL_PHONE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_permission_utils);
    }

    public void requestPermission(View view) {
        if (PermissionUtils.hasPermissions(this, permissions)) {
            doSomething();
        } else {
            PermissionUtils.requestPermissions(this, REQUESET_PERMISSIONS_CODE, permissions);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        //把申请权限的回调交由PermissionUtils处理
        PermissionUtils.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //设置界面打开权限的回调
        if (requestCode == PermissionUtils.GOTO_SEETING_CODE) {
            //判断是否开启了权限
            if (PermissionUtils.hasPermissions(this, permissions)) {
                doSomething();
            } else {
                //PermissionUtils.requestPermissions(this, REQUESET_PERMISSIONS_CODE, permissions);
            }
        }
    }

    @Override
    public void onPermissionsAllGranted(int requestCode, List<String> perms) {
        //全部权限允许
        doSomething();
    }

    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        //一些权限拒绝了并且点击了不再提醒,去设置界面手动打开权限
        if (PermissionUtils.somePermissionPermanentlyDenied(this, perms)) {
            PermissionUtils.showDialogGoToAppSettting(this);
        } else {
            //一些权限拒绝了没有点击了不再提醒
            Toast.makeText(this, "权限没有全部被允许", Toast.LENGTH_SHORT).show();
        }
    }


    public void doSomething() {
        Toast.makeText(this, "执行相关操作", Toast.LENGTH_SHORT).show();
    }
}

RxPermissions的使用

RxPermissions

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

   implementation 'com.github.tbruyelle:rxpermissions:0.12'

    implementation "io.reactivex.rxjava3:rxjava:3.0.7"
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'

创建 RxPermissions 实例

RxPermissions rxPermissions = new RxPermissions(this);

注意:this 参数可以是 FragmentActivity 或 Fragment。如果你在 fragment 中使用 RxPermissions,你应该传递 fragment 实例作为构造函数参数而不是 fragment.getActivity(),否则你可能抛出异常 java.lang.IllegalStateException: FragmentManager is already executing。

RxPermissions 里面的方法总结

在这里插入图片描述

request: 不支持返回权限名; 返回的权限结果:全部同意时值true,否则值为false
requestEach: 把每一个权限的名称和申请结果都列出来
requestEachCombined: 返回的权限名称:将多个权限名合并成一个; 返回的权限结果:全部同意时值true,否则值为false
ensure: 必须配合rxjava,回调结果跟request一样
ensureEach: 必须配合rxjava,回调结果跟requestEach一样
ensureEachCombined: 必须配合rxjava,回调结果跟requestEachCombined一样
 <p>
使用建议:
1. 没有选中不再提示,不需要打开设置界面开启权限可以用:request
2. 选中了不再提示,需要打开设置界面开启权限可以用(申请一个权限):requestEach  requestEachCombined
3. 选中了不再提示,需要打开设置界面开启权限可以用(申请多个权限):requestEachCombined
/**
 * RxPermissions的使用
 */
public class MainActivity extends AppCompatActivity {

    private RxPermissions mRxPermissions;

    public static final int PERMISSION_REQUEST_CODE = 10001;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRxPermissions = new RxPermissions(this);
    }

    /**
     * request: 不支持返回权限名; 返回的权限结果:全部同意时值true,否则值为false
     * requestEach: 把每一个权限的名称和申请结果都列出来
     * requestEachCombined: 返回的权限名称:将多个权限名合并成一个; 返回的权限结果:全部同意时值true,否则值为false
     * ensure: 必须配合rxjava,回调结果跟request一样
     * ensureEach: 必须配合rxjava,回调结果跟requestEach一样
     * ensureEachCombined: 必须配合rxjava,回调结果跟requestEachCombined一样
     * <p>
     * 使用建议:
     * 1. 没有选中不再提示,不需要打开设置界面开启权限可以用:request
     * 2. 选中了不再提示,需要打开设置界面开启权限可以用(申请一个权限):requestEach  requestEachCombined
     * 3. 选中了不再提示,需要打开设置界面开启权限可以用(申请多个权限):requestEachCombined
     */
    public void doClick(View view) {
        switch (view.getId()) {
            case R.id.btn1: //申请一个权限
                requestSinglePermission();
                break;
            case R.id.btn2: //申请多个权限
                requestMultiPermission();
                break;
            case R.id.btn3: //requestEach
                requestEach();
                break;
            case R.id.btn4: //requestEachCombined
                requestEachCombined();
                break;
            case R.id.btn5: //ensure
                ensure();
                break;
            case R.id.btn6: //ensureEach
                ensureEach();
                break;
            case R.id.btn7: //ensureEachCombined
                ensureEachCombined();
                break;
        }
    }

    private void requestSinglePermission() {
        mRxPermissions.request(Manifest.permission.CAMERA)
                .subscribe(granted -> {
                    if (granted) {
                        //权限被允许
                        Toast.makeText(MainActivity.this, "已获取权限", Toast.LENGTH_LONG).show();
                    } else {
                        //权限被拒绝
                        Toast.makeText(MainActivity.this, "获取被拒绝", Toast.LENGTH_LONG).show();
                    }
                });
    }

    private void requestMultiPermission() {
        mRxPermissions.request(
                Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE)
                .subscribe(granted -> {
                    if (granted) {
                        //全部同意时值true,否则值为false
                        Toast.makeText(MainActivity.this, "获取已全部允许", Toast.LENGTH_LONG).show();
                    } else {
                        //申请多个权限时,只要有一个被拒绝,就会走这里
                        Toast.makeText(MainActivity.this, "有获取被拒绝", Toast.LENGTH_LONG).show();
                    }
                });
    }

    private void requestEach() {
        mRxPermissions.requestEach(
                Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE)
                .subscribe(permission -> {
                    Log.e("xyh", "doClick: " + permission.name);
                    if (permission.granted) {
                        // 用户已经同意该权限
                        Toast.makeText(MainActivity.this, "获取被允许", Toast.LENGTH_LONG).show();
                    } else if (permission.shouldShowRequestPermissionRationale) {
                        // 该权限被拒绝,没有选中不再提示,那么下次点击时就还会弹出申请权限框
                        Toast.makeText(MainActivity.this, "获取被拒绝", Toast.LENGTH_LONG).show();
                    } else {
                        //该权限被拒绝并且选中了不再提示,那么下次点击时就不会弹出申请权限框,需要去设置界面开启权限
                        Toast.makeText(MainActivity.this, "获取被拒绝,并且点击了不再提醒", Toast.LENGTH_LONG).show();
                        showGoToAppSetttingDialog();
                    }
                });
    }

    private void requestEachCombined() {
        mRxPermissions.requestEachCombined(
                Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE)
                .subscribe(new Consumer<Permission>() {
                    @Override
                    public void accept(Permission permission) throws Throwable {
                        Log.e("xyh", "doClick: " + permission.name);
                        if (permission.granted) {
                            // 用户已经同意全部权限
                            Toast.makeText(MainActivity.this, "权限已全部允许", Toast.LENGTH_LONG).show();
                        } else if (permission.shouldShowRequestPermissionRationale) {
                            // 至少有一个权限被拒绝,没有选中不再提示,那么下次点击时就还会弹出申请权限框
                            Toast.makeText(MainActivity.this, "有获取被拒绝", Toast.LENGTH_LONG).show();
                        } else {
                            //至少有一个权限被拒绝并且选中了不再提示,那么下次点击时就不会弹出申请权限框,需要去设置界面开启权限
                            Toast.makeText(MainActivity.this, "有获取被拒绝,并且点击了不再提醒", Toast.LENGTH_LONG).show();
                            showGoToAppSetttingDialog();
                        }
                    }
                });
    }

    private void ensure() {
        Observable.timer(10, TimeUnit.MICROSECONDS)
                .compose(mRxPermissions.ensure(Manifest.permission.CAMERA))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(granted -> {
                    if (granted) {
                        //权限被允许
                        Toast.makeText(MainActivity.this, "已获取权限", Toast.LENGTH_LONG).show();
                    } else {
                        //权限被拒绝
                        Toast.makeText(MainActivity.this, "获取被拒绝", Toast.LENGTH_LONG).show();
                    }
                });
    }

    private void ensureEach() {
        Observable.timer(10, TimeUnit.MICROSECONDS)
                .compose(mRxPermissions.ensureEach(
                        Manifest.permission.CAMERA,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_EXTERNAL_STORAGE))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Permission>() {
                    @Override
                    public void accept(Permission permission) throws Throwable {
                        if (permission.granted) {
                            // 用户已经同意该权限
                            Toast.makeText(MainActivity.this, "获取被允许", Toast.LENGTH_LONG).show();
                        } else if (permission.shouldShowRequestPermissionRationale) {
                            // 该权限被拒绝,没有选中不再提示,那么下次点击时就还会弹出申请权限框
                            Toast.makeText(MainActivity.this, "获取被拒绝", Toast.LENGTH_LONG).show();
                        } else {
                            //该权限被拒绝并且选中了不再提示,那么下次点击时就不会弹出申请权限框,需要去设置界面开启权限
                            Toast.makeText(MainActivity.this, "获取被拒绝,并且点击了不再提醒", Toast.LENGTH_LONG).show();
                            showGoToAppSetttingDialog();
                        }
                    }
                });
    }

    private void ensureEachCombined() {
        Observable.timer(10, TimeUnit.MICROSECONDS)
                .compose(mRxPermissions.ensureEachCombined(
                        Manifest.permission.CAMERA,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_EXTERNAL_STORAGE))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Permission>() {
                    @Override
                    public void accept(Permission permission) throws Throwable {
                        if (permission.granted) {
                            // 用户已经同意全部权限
                            Toast.makeText(MainActivity.this, "权限已全部允许", Toast.LENGTH_LONG).show();
                        } else if (permission.shouldShowRequestPermissionRationale) {
                            // 至少有一个权限被拒绝,没有选中不再提示,那么下次点击时就还会弹出申请权限框
                            Toast.makeText(MainActivity.this, "有获取被拒绝", Toast.LENGTH_LONG).show();
                        } else {
                            //至少有一个权限被拒绝并且选中了不再提示,那么下次点击时就不会弹出申请权限框,需要去设置界面开启权限
                            Toast.makeText(MainActivity.this, "有获取被拒绝,并且点击了不再提醒", Toast.LENGTH_LONG).show();
                            showGoToAppSetttingDialog();
                        }
                    }
                });
    }

    private void showGoToAppSetttingDialog() {
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("权限不可用")
                .setMessage("请在-应用设置-权限-中,允许该权限!")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // 跳转到应用设置界面
                        goToAppSetting();
                        dialog.dismiss();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).setCancelable(false).show();
    }

    /**
     * 跳转到应用设置界面
     */
    private void goToAppSetting() {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivityForResult(intent, PERMISSION_REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            //从设置界面返回来,判断是否有权限
            requestEachCombined();
        }
    }
}

EasyPermissions的使用

github地址

dependencies {
    implementation 'pub.devrel:easypermissions:1.3.0'
}

申请一个权限

public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks,
                                                               EasyPermissions.RationaleCallbacks{

    private static final String TAG = "MainActivity";
   
    private static final int RC_CAMERA_PERM = 123;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //申请一个权限
        findViewById(R.id.button_camera).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cameraTask();
            }
        });
    }

    private boolean hasCameraPermission() {
        return EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA);
    }

//使用了该注解,当权限请求被用户同意后,会根据请求code来执行,相应的含有@AfterPermissionGranted注解的方法。不需要在EasyPermissions.onRequestPermissionsResult()的回调监听器中请求成功的方法中,再次手动调用,获取权限后需要操作的逻辑代码
    @AfterPermissionGranted(RC_CAMERA_PERM)
    public void cameraTask() {
        if (hasCameraPermission()) {
            // 有权限,执行相关操作
           Toast.makeText(this, "执行操作", Toast.LENGTH_SHORT).show();
        } else {
            // 申请权限
             /**
             * 第一个参数:Context对象
             * 第二个参数:权限弹窗上的文字提示语。告诉用户,这个权限用途。
             * 第三个参数:这次请求权限的唯一标示,code。
             * 第四个参数 : 一些系列的权限。
             */
            EasyPermissions.requestPermissions(
                    this,
                    getString(R.string.rationale_camera),
                    RC_CAMERA_PERM,
                    Manifest.permission.CAMERA);
        }
    }



    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

         //把申请权限的回调交由EasyPermissions处理
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

	//某些权限已被授予
    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        Toast.makeText(this, "执行操作", Toast.LENGTH_SHORT).show();
    }

	//某些权限已被拒绝
    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());

        //(可选)检查用户是否拒绝任何权限,并检查“不要再问”。
        //这将显示一个对话框,引导他们在应用程序设置中启用权限。
         if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            new AppSettingsDialog.Builder(this).setRationale("去设置界面开启权限").setTitle("提示").build().show();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE) {
           
          // 在用户从应用程序设置屏幕返回后做一些事情,比如展示Toast。
           
        }
    }

    @Override
    public void onRationaleAccepted(int requestCode) {
        Log.d(TAG, "onRationaleAccepted:" + requestCode);
    }

    @Override
    public void onRationaleDenied(int requestCode) {
        Log.d(TAG, "onRationaleDenied:" + requestCode);
    }
}

申请多个权限

public class EasypermissionsActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks, EasyPermissions.RationaleCallbacks {

    private static final String TAG = "EasypermissionsActivity";

    private static final String[] LOCATION_AND_CONTACTS =
            {Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_CONTACTS};

    private static final int RC_LOCATION_CONTACTS_PERM = 124;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_easypermissions);

        //申请多个权限
        findViewById(R.id.button_location_and_contacts).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                locationAndContactsTask();
            }
        });
    }

    @AfterPermissionGranted(RC_LOCATION_CONTACTS_PERM)
    public void locationAndContactsTask() {
        if (hasLocationAndContactsPermissions()) {
            Toast.makeText(this, "执行操作", Toast.LENGTH_LONG).show();
        } else {
            EasyPermissions.requestPermissions(
                    this,
                    getString(R.string.rationale_location_contacts),
                    RC_LOCATION_CONTACTS_PERM,
                    LOCATION_AND_CONTACTS);
        }
    }

    private boolean hasLocationAndContactsPermissions() {
        return EasyPermissions.hasPermissions(this, LOCATION_AND_CONTACTS);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        //把申请权限的回调交由EasyPermissions处理
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }


    /**
     * 某些权限已被授予
     *
     * @param requestCode
     * @param perms       授权成功的权限
     */
    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        //权限全部同意
        if (perms.size() == LOCATION_AND_CONTACTS.length) {
            Toast.makeText(this, "执行操作", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 某些权限已被拒绝
     *
     * @param requestCode
     * @param perms
     */
    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        //(可选)检查用户是否拒绝任何权限,并检查“不要再问”。
        //这将显示一个对话框,引导他们在应用程序设置中启用权限。
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            new AppSettingsDialog.Builder(this).setRationale("去设置界面开启权限").setTitle("提示").build().show();
        }
    }

    @Override
    public void onRationaleAccepted(int requestCode) {
        Toast.makeText(this, "onRationaleAccepted", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRationaleDenied(int requestCode) {
        Toast.makeText(this, "onRationaleDenied", Toast.LENGTH_SHORT).show();
    }
}

@AfterPermissionGranted注解:

@AfterPermissionGranted注解为了提供方便,但可以添加也可以不添加,是可选的。

好处:

使用了该注解,当权限请求被用户同意后,会根据请求code来执行,相应的含有@AfterPermissionGranted注解的方法。

简化了请求成功操作流程,不需要在EasyPermissions.onRequestPermissionsResult()的回调监听器中请求成功的方法中,再次手动调用,获取权限后需要操作的逻辑代码。

其他权限申请框架

AndPermission

PermissionsDispatcher

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值