Android 6.0动态权限大总结

6.0动态权限这个问题,面试官很喜欢问这个。还有5.0、7.0新特性。
22以前的api,都是在AndroidManifest文件中注册权限即可,用户在安装apk的时候会有权限提示,但是哪个用户会看呢?google为了提高用户的安全性,在23(6.0)以后,app使用某一个敏感操作时,还需要用户的允许才行,否则这个功能无法使用。
动态权限就这么回事。


先贴一下我的工具类吧:

/**
 * @Author: duke
 * @DateTime: 2017-03-30 15:51
 * @Description: 权限检测工具类
 */
public class PermissionManager {

    private PermissionManager() {
    }

    /**
     * 是否需要动态申请权限 <br/>
     *
     * @return 需要:true,不需要:false
     */
    public static final boolean isNeedDynamicPermissions() {
        //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {}
        if (Build.VERSION.SDK_INT >= 23) {
            // 23 (Android 6.0)以上
            return true;
        }
        return false;
    }

    /**
     * 向用户弹出解释对话框 <br/>
     * *******************************************************************************
     * ** 应用安装后第一次访问,直接返回false;                                     **
     * ** 第一次请求权限时用户拒绝了,下一次返回 true,                             **
     * ** 这时候可以显示一些为什么需要这个权限的说明;                              **
     * ** 第二次请求权限时,用户拒绝了,并选择了“不再提醒”的选项时,返回 false;  **
     * ** 设备的系统设置中禁止当前应用获取这个权限的授权,返回false;             **
     * ** 注意:第二次请求权限时,才会有“不再提醒”的选项,                        **
     * ** 如果用户一直拒绝,并没有选择“不再提醒”的选项,                          **
     * ** 下次请求权限时,会继续有“不再提醒”的选项,并且会一直返回true            **
     * *******************************************************************************
     *
     * @param activity   上下文
     * @param permission 需要提示解释的权限申请
     * @return 需要提示:true,不需要:false
     */
    public static final boolean shouldShowRequestPermissionRationale(Activity activity, String permission) {
        return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
    }

    /**
     * 检查当前是否已被赋予权限 <br/>
     *
     * @param context     上下文
     * @param permissions 待判断权限集合
     * @return 授权:true,缺少授权:false
     */
    public static final boolean checkSelfPermission(Context context, String... permissions) {
        if (null == permissions || permissions.length == 0) {
            return false;
        }
        for (String permission : permissions) {
            if (TextUtils.isEmpty(permission)) {
                return false;
            }
            /**
             * 检测权限核心方法
             */
            if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED) {
                //如果其中某一个未授权
                return false;
            }
        }
        //权限参数合法,且全部都授权过
        return true;
    }

    /**
     * 正式请求用户授权 <br/>
     *
     * @param context     activity上下文
     * @param permissions 待权限的权限集合
     * @param requestCode 本次授权请求码
     */
    public static final void requestPermissions(Activity context, String[] permissions, int requestCode) {
        ActivityCompat.requestPermissions(context, permissions, requestCode);
    }

    /**
     * 检查授权结果,是否为“成功授权” <br/>
     *
     * @param grantResults 权限结果集合
     * @return 授权成功:true,授权失败:false
     */
    public static final boolean checkPermissionsResult(int[] grantResults) {
        if (grantResults == null || grantResults.length == 0) {
            return false;
        }
        for (int grantResult : grantResults) {
            if (grantResult == PackageManager.PERMISSION_DENIED) {
                //其中一个未授权,立即返回false授权失败
                return false;
            }
        }
        return true;
    }
}

代码很简单,都有注释。
如果你不确定那些是敏感的权限,可以使用下面命令cmd进行查看:

//adb shell pm list permissions -d -g

在使用到敏感权限时,需要判断当前的版本是不是23以上。
如果不是,那就好办了,直接调用相关功能的方法即可。
如果需要呢?还得判断某权限是否已经授权。授权了也就不用再申请了。否则需要申请。
传递对应权限的参数,申请权限。然后在回调方法里面接受授权结果。根据结果再做处理即可。


看Activity用法。

/**
 * 拨打电话
 */
public class CallActivity extends Activity {
    private String phone;

    public static final int PERMISSION_REQUEST_CODE_CALL_PHONE = 1900;
    public static final String[] NEED_PERMISSIONS = {Manifest.permission.CALL_PHONE};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_call);
        phone = getIntent().getStringExtra("phone");

        //检查6.0动态权限-拨打电话权限
        check6Permission();
    }

    private void check6Permission() {
        //判断权限
        if (PermissionManager.isNeedDynamicPermissions()) {
            //需要动态申请权限,判断是否授权
            if (!PermissionManager.checkSelfPermission(getApplicationContext(), NEED_PERMISSIONS)) {
                //申请授权
                PermissionManager.requestPermissions(CallActivity.this, NEED_PERMISSIONS, PERMISSION_REQUEST_CODE_CALL_PHONE);
            } else {
                //已授权
                callPhone();
            }
        } else {
            //不需要动态权限
            callPhone();
        }
    }

    public void callPhone(){
        if(TextUtils.isEmpty(phone)){
            return;
        }
        Uri uri = Uri.parse("tel:" + phone);
        Intent intent = new Intent();
        intent.setData(uri);
        intent.setAction(Intent.ACTION_CALL);
        startActivity(intent);
        finish();
    }

    /**
     * 权限申请回调
     *
     * @param requestCode  请求码
     * @param permissions  申请的权限字符串集合
     * @param grantResults 申请的权限结果集合
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //PERMISSION_REQUEST_CODE_CALL_PHONE 权限请求
        if (requestCode == PERMISSION_REQUEST_CODE_CALL_PHONE) {
            if (PermissionManager.checkPermissionsResult(grantResults)) {
                //授权成功
                callPhone();
            } else {
                //授权失败
                if (null == permissions || permissions.length == 0) {
                    return;
                }
                //当此拒绝后,这儿立马为true
                boolean isNeedShowExplainToUser = PermissionManager.shouldShowRequestPermissionRationale(this, permissions[0]);
                if (isNeedShowExplainToUser) {
                    //需要向用户解释
                    DialogUtils.alertDialogTwo(this, 0, false, "没有此权限,将无法拨打电话",
                            "提示", "取消", "去设置",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    //取消授权
                                    CallActivity.this.finish();
                                }
                            }, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    //应用程序详情页面
                                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                    intent.setData(Uri.parse("package:" + getPackageName()));
                                    startActivity(intent);
                                    CallActivity.this.finish();
                                }
                            }).show();
                }
                finish();
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}


都很简单,唯一需要特别说明的是:shouldShowRequestPermissionRationale(this, permissions[0]);方法。
个人觉得这个方法需要放在回调里面,即当用户拒绝后立即显示提示框。放在其他的地方无意义。


还有点需要特别说明的是,这个方法在某些厂商的系统中永远都为false,把人给坑死了,比喻小米系统。在测试这个功能的时候还是建议使用原版系统或者模拟器实验。


6.0动态权限就这点东西,不多说了。












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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值