RunTimePermission

运行时权限

简介

Android从6.0(API23)开始采用运行时权限机制,以往的版本是在安装应用的时候赋予权限,而6.0以后的权限是在应用运行时,需要此权限的时候去申请这个权限。

在6.0之前的版本调用像拨打电话、插入联系人等功能的时候,如果没有权限系统默认不做任何处理,而在6.0之后,如果调用了没有权限的功能,应用会异常退出。

用到的api

权限检查:
    // Context类提供抽象方法 方法在ContextWrapper类中实现
    public abstract int checkSelfPermission(@NonNull String permission);
    // Fragment中存在同名方法

是否被拒绝过检查:
    // Activity和Fragment都有此方法,都是调用了PackageManager的同名方法
    public boolean shouldShowRequestPermissionRationale(@NonNull String permission)

权限请求:
    // v4兼容包中ActivityCompat提供静态方法
    public static void requestPermissions(final @NonNull Activity activity,
            final @NonNull String[] permissions, final int requestCode) 
    // Activity类提供的方法
    public final void requestPermissions(@NonNull String[] permissions, int requestCode)
    // Fragment中存在同名方法


权限请求结果返回:
    // Activity和Fragment都存在相同方法
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults)


    以上方法在Activity和Fragment中都存在同名和相同方法签名的方法。下面以Activity为例,Fragment只需要修改为继承自Fragment即可使用

单个权限请求

单个权限请求较为简单,比较适合初学者来理顺思路逻辑。

  1. 检查是否拥有权限,如果没有此权限进入第二步,如果拥有权限直接进行业务处理
  2. 检查权限是否被拒绝过,如果没有被拒绝过,进入第三步,如果被拒绝过,做出处理,给用户一个提示
  3. 申请权限,权限申请会有两种结果,用户通过或者用户拒绝

/**
 * Created by ztt on 2016/11/18.
 * 
 * 权限检查回调接口,包含三个方法:
 * 分别对应权限检查的成功,失败以及权限被拒绝之后再次点击的回调
 */
public interface IRunTimePermission {

    /**
     * 权限请求通过
     * @param requestCode 权限请求码
     */
    void onPermissionsGranted(int requestCode);

    /**
     * 权限请求拒绝
     * @param requestCode 权限请求码
     */
    void onPermissionsDenied(int requestCode);

    /**
     * 权限请求被拒绝过,显示请求权限的的原因
     * @param requestCode 权限请求码
     */
    void onShowRequestRationale(int requestCode);

}
/**
 * Created by ztt on 2016/11/18.
 * 
 * 带权限申请的Activity基类
 */

public abstract class BasePermissionActivityI extends Acticity implements
        IRunTimePermission {

    /**
     * 检查权限
     * @param requestCode 没有权限要去申请,权限请求码
     * @param permission  需要检查的权限
     * @return 是否有权限
     */
    protected boolean checkPermission(int requestCode, String permission) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {
                return true;
            } else {
                // 此处检查权限是否被拒绝过,拒绝过的不能再次申请,可以给用户提示信息
                if (shouldShowRequestPermissionRationale(permission)) {
                    onShowRequestRationale(requestCode);
                } else {
                    requestPermissions(new String[]{permission}, requestCode);
                }
                return false;
            }
        } else {
            return true;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            onPermissionsGranted(requestCode);
        } else {
            onPermissionsDenied(requestCode);
        }
    }
}

多个权限检查请求

官方都拥有同时请求多个权限的方法,这个功能也要实现哈。

当同时有ABCD四个权限需要检查申请,A权限已经被授权,B权限已经被拒绝过一次,C权限在本次申请中被拒绝,D权限在本次申请中通过。而我们的业务需要同时拥有此四个权限才能实现。此时如果要对每一个权限进行详细的处理,逻辑会变得复杂,饭要一口一口吃,权限要一个一个申请。
(申请多个权限,当一个权限被拒绝过之后将不再继续申请其他权限简化逻辑,当申请权限时,有一个权限被拒绝,将进入权限拒绝回调,简化逻辑)

先修改接口,当权限通过,就直接业务逻辑就好了。如果权限异常,可能需要对异常的权限进行处理,所以添加权限数组参数

为了更好的复用,将接口拿到Activity类里面,然后让项目原有的BaseActivity继承此类,为项目所有的Activity添加此功能。

修改权限检查申请和权限申请结果处理逻辑

/**
 * Created by ztt on 2016/11/18.
 * <p>
 * 带权限申请的Activity基类
 */
public abstract class BasePermissionActivity extends FragmentActivity {

    private OnRunTimePermissionListener onRunTimePermissionListener;

    public void setOnRunTimePermissionListener(OnRunTimePermissionListener
                                                       onRunTimePermissionListener) {
        this.onRunTimePermissionListener = onRunTimePermissionListener;
    }

    /**
     * 检查权限
     *
     * @param requestCode 没有权限要去申请,权限请求码
     * @param permissions 需要检查的权限
     * @return 是否有所有权限
     */
    protected boolean checkPermission(int requestCode, String... permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }
        // 存放被拒绝过的权限
        List<String> rationalePermissions = new ArrayList<>();
        // 存放未申请的权限
        List<String> noPermissions = new ArrayList<>();
        for (String permission : permissions) {
            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                if (shouldShowRequestPermissionRationale(permission)) {
                    rationalePermissions.add(permission);
                } else {
                    noPermissions.add(permission);
                }
            }
        }

        if (noPermissions.isEmpty() && rationalePermissions.isEmpty()) {
            return true;
        } else {
            // 当未申请的权限不为空并且被拒绝权限为空时(所有未通过权限都处于询问状态)申请权限
            if (!noPermissions.isEmpty() && rationalePermissions.isEmpty()) {
                requestPermissions(noPermissions.toArray(new String[0]), requestCode);
            } else {
                // 存在被拒绝权限
                if (onRunTimePermissionListener != null) {
                    onRunTimePermissionListener.onShowRequestRationale(requestCode,
                            rationalePermissions.toArray(new String[0]));
                }
            }
            return false;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // 被拒绝权限
        List<String> deniedPermissions = new ArrayList<>();
        for (int i = 0; i < permissions.length; i++) {
            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                deniedPermissions.add(permissions[i]);
            }
        }
        // 如果被拒绝权限为空,权限全部获取
        if (deniedPermissions.isEmpty()) {
            if (onRunTimePermissionListener != null) {
                onRunTimePermissionListener.onPermissionsGranted(requestCode);
            }
        } else {
            // 如果存在被拒绝权限
            if (onRunTimePermissionListener != null) {
                onRunTimePermissionListener.onPermissionsDenied(requestCode, deniedPermissions
                        .toArray(new String[0]));
            }
        }
    }


    /**
     * 权限检查回调接口
     * 包含三个方法,分别对应权限检查的成功,失败以及权限被拒绝之后再次点击
     */
    public interface OnRunTimePermissionListener {

        /**
         * 权限请求通过
         *
         * @param requestCode 权限请求码
         */
        void onPermissionsGranted(int requestCode);

        /**
         * 权限请求拒绝
         *
         * @param requestCode 权限请求码
         * @param permissions 被拒绝的权限
         */
        void onPermissionsDenied(int requestCode, String[] permissions);

        /**
         * 权限请求被拒绝过,显示请求权限的的原因
         *
         * @param requestCode 权限请求码
         * @param permissions 被拒绝过的权限
         */
        void onShowRequestRationale(int requestCode, String[] permissions);

    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值