Android权限篇 Android 6.0动态权限申请

Posted 彭老希

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android权限篇 Android 6.0动态权限申请相关的知识,希望对你有一定的参考价值。

一、前言

android6.0之前只需在AndroidManifest.xml文件写明权限即可

Android 6.0 版本之后【SDK >= 23】,一些隐私权限需要动态申请,而且在用户同意授权之后App才能拥有该权限。

二、处理思路

在每个Activity界面显示前把该界面所需的权限全部申请允许了,再进入正常的流程。如果有权限未被允许,开发者可以在接口中自己处理,可以直接提示并退出,或者提示权限的作用后重新发起权限申请。或者提供浏览的界面,Android10之后,谷歌官方不允许用户拒绝权限后,应用被退出

三、官方API - 监测权限是否被授予

1、checkSelfPermission检查是否已被授予
2、requestPermissions申请权限
3、自动回调onRequestPermissionsResult 根据请求权限结果
4、shouldShowRequestPermissionRationale 应该显示请求许可理由

ContextCompat.checkSelfPermission(): 检查权限是否已经授权

ActivityCompat.requestPermissions():动态申请权限,并弹出对话框

onRequestPermissionsResult():在activity里面重写该方法该方法是权限申请之后的回调方法。

shouldShowRequestPermissionRationale() :当应用首次申请权限时,如果用户点击拒绝,下次再申请权限,Android允许你提示用户,你为什么需要这个权限,更好引导用户是否授权,其中在Android原生系统中:

如果应用之前请求过此权限但用户拒绝了请求,此方法将返回true

如果用户在过去拒绝了权限请求且在权限请求系统对话框中选择了 Don't ask again 选项将返回 false

如果第一次申请权限也返回false

如果设备规范禁止应用具有该权限,此方法也会返回 false,返回false则不在显示提示对话框,返回true则会显示对话框

四、运行效果图

(1) 初次进入界面,申请所需的全部权限
在这里插入图片描述
(2)申请单个权限
在这里插入图片描述
(3)拒绝授予权限,且勾选了不再提示
在这里插入图片描述
(4)拒绝权限并不再提示,告知用户该权限的作用
在这里插入图片描述
(5)提示用户开启权限
在这里插入图片描述
(6)点击“立即开启”跳到权限设置页面
在这里插入图片描述

五、实战使用

public class MainActivity extends AppCompatActivity implements View.OnClickListener, PermissionInterface {
    private int requestCode = 10000;
    private Button btn_phone;//打电话
    private Button btn_camera;//打开相机
    private PermissionHelper mPermissionHelper;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_phone = findViewById(R.id.btn_phone);
        btn_camera = findViewById(R.id.btn_camera);
        btn_phone.setOnClickListener(this);
        btn_camera.setOnClickListener(this);
        //初始化
        mPermissionHelper = new PermissionHelper(this, this);
        //发起权限申请
        mPermissionHelper.requestPermissions(new String[]{Manifest.permission.CALL_PHONE,
                Manifest.permission.CAMERA});
 
    }
 
    //点击监听
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_phone://打电话
                requestCode = 0;
                mPermissionHelper.requestPermissions(new String[]{Manifest.permission.CALL_PHONE});
 
                break;
            case R.id.btn_camera://打开相机
                requestCode = 1;
                mPermissionHelper.requestPermissions(new String[]{Manifest.permission.CAMERA});
 
                break;
        }
 
    }
 
    /**
     * 可设置请求权限请求码
     */
    @Override
    public int getPermissionsRequestCode() {
        //设置权限请求requestCode,只有不跟onRequestPermissionsResult方法中的其他请求码冲突即可。
        return requestCode;
    }
 
 
    /**
     * 请求权限成功回调
     */
    @Override
    public void requestPermissionsSuccess() {
        //权限请求用户已经全部允许
        if (requestCode == 10000) {
 
        } else if (requestCode == 0) {
            Intent intent = new Intent(Intent.ACTION_DIAL);
            Uri data = Uri.parse("tel:" + 10086);
            intent.setData(data);
            startActivity(intent);
        } else if (requestCode == 1) {
            Intent intent1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(intent1, 0);
        }
 
    }
 
    /**
     * 请求权限失败回调
     */
    @TargetApi(Build.VERSION_CODES.M)
    @Override
    public void requestPermissionsFail() {
        //权限请求不被用户允许。可以提示并退出或者提示权限的用途并重新发起权限申请。
        if (requestCode==10000){
 
        }else if (requestCode == 0) {
            //如果拒绝授予权限,且勾选了再也不提醒
            if (!shouldShowRequestPermissionRationale(Manifest.permission.CALL_PHONE)) {
                DialogUtil.showSelectDialog(this, "说明", "需要使用电话权限,进行电话测试", "取消", "确定", new DialogUtil.DialogClickListener() {
                    @Override
                    public void confirm() {
                        //用于在用户勾选“不再提示”并且拒绝时,再次提示用户
                        DialogUtil.showSelectDialog(MainActivity.this, "电话权限不可用", "请在-应用设置-权限中,允许APP使用电话权限来测试", "取消", "立即开启", new DialogUtil.DialogClickListener() {
                            @Override
                            public void confirm() {
                                goToAppSetting();
                            }
 
                            @Override
                            public void cancel() {
 
                            }
                        }).show();
                    }
 
                    @Override
                    public void cancel() {
 
                    }
                }).show();
            } else {
                DialogUtil.showSelectDialog(MainActivity.this, "电话权限不可用", "请在-应用设置-权限中,允许APP使用电话权限来测试", "取消", "立即开启", new DialogUtil.DialogClickListener() {
                    @Override
                    public void confirm() {
                        goToAppSetting();
                    }
 
                    @Override
                    public void cancel() {
 
                    }
                }).show();
            }
 
        }else if (requestCode==1){
            //如果拒绝授予权限,且勾选了再也不提醒
            if (!shouldShowRequestPermissionRationale(Manifest.permission.CALL_PHONE)) {
                DialogUtil.showSelectDialog(this, "说明", "需要使用相机权限,进行相机测试", "取消", "确定", new DialogUtil.DialogClickListener() {
                    @Override
                    public void confirm() {
                        //用于在用户勾选“不再提示”并且拒绝时,再次提示用户
                        DialogUtil.showSelectDialog(MainActivity.this, "相机权限不可用", "请在-应用设置-权限中,允许APP使用相机权限来测试", "取消", "立即开启", new DialogUtil.DialogClickListener() {
                            @Override
                            public void confirm() {
                                goToAppSetting();
                            }
 
                            @Override
                            public void cancel() {
 
                            }
                        }).show();
                    }
 
                    @Override
                    public void cancel() {
 
                    }
                }).show();
            } else {
                DialogUtil.showSelectDialog(MainActivity.this, "相机权限不可用", "请在-应用设置-权限中,允许APP使用相机权限来测试", "取消", "立即开启", new DialogUtil.DialogClickListener() {
                    @Override
                    public void confirm() {
                        goToAppSetting();
                    }
 
                    @Override
                    public void cancel() {
 
                    }
                }).show();
            }
        }
 
 
    }
 
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (mPermissionHelper.requestPermissionsResult(requestCode, permissions, grantResults)) {
            //权限请求结果,并已经处理了该回调
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
 
    /**
     * 打开Setting
     */
    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);
    }
 
 
}

六、Dialog工具类

public class DialogUtil {
    /**
     * 创建一个选择对话框
     *
     * @param context
     * @param pContent            提示消息
     * @param dialogClickListener 点击监听
     * @return
     */
    public static Dialog showSelectDialog(Context context, String title, String pContent, String pLeftBtnStr,
                                          String pRightBtnStr,
                                          final DialogClickListener dialogClickListener) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        AlertDialog dialog = builder.setTitle(title)
                .setMessage(pContent)
                .setPositiveButton(pRightBtnStr, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialogClickListener.confirm();
                        dialog.dismiss();
                    }
                })
                .setNegativeButton(pLeftBtnStr, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialogClickListener.cancel();
                        dialog.dismiss();
//                        return;
                    }
                })
                .create();
        return dialog;
    }
 
 
    public interface DialogClickListener {
 
        public abstract void confirm();
 
        public abstract void cancel();
 
    }
}

七、权限的接口类

/**
 * 权限请求接口
 */
public interface PermissionInterface {
 
    /**
     * 可得到请求权限请求码
     */
    int getPermissionsRequestCode();
 
    /**
     * 请求权限成功回调
     */
    void requestPermissionsSuccess();
 
    /**
     * 请求权限失败回调
     */
    void requestPermissionsFail();
 
}

八、权限的帮助类

/**
 * 动态权限帮助类
 */
public class PermissionHelper {
    private Activity mActivity;
    private PermissionInterface mPermissionInterface;
 
    public PermissionHelper(@NonNull Activity activity, @NonNull PermissionInterface permissionInterface) {
        mActivity = activity;
        mPermissionInterface = permissionInterface;
    }
 
    /**
     * 开始请求权限。
     * 方法内部已经对Android M 或以上版本进行了判断,外部使用不再需要重复判断。
     * 如果设备还不是M或以上版本,则也会回调到requestPermissionsSuccess方法。
     */
    public void requestPermissions(String[] permissions) {
        String[] deniedPermissions = PermissionUtil.getDeniedPermissions(mActivity, permissions);
        if (deniedPermissions != null && deniedPermissions.length > 0) {
            PermissionUtil.requestPermissions(mActivity, deniedPermissions, mPermissionInterface.getPermissionsRequestCode());
        } else {
            mPermissionInterface.requestPermissionsSuccess();
        }
    }
 
    /**
     * 在Activity中的onRequestPermissionsResult中调用
     * @param requestCode
     * @param permissions
     * @param grantResults
     * @return true 代表对该requestCode感兴趣,并已经处理掉了。false 对该requestCode不感兴趣,不处理。
     */
    public boolean requestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == mPermissionInterface.getPermissionsRequestCode()) {
            boolean isAllGranted = true;//是否全部权限已授权
            for(int result : grantResults){
                if(result == PackageManager.PERMISSION_DENIED){
                    isAllGranted = false;
                    break;
                }
            }
            if(isAllGranted){
                //已全部授权
                mPermissionInterface.requestPermissionsSuccess();
            }else{
                //权限有缺失
                mPermissionInterface.requestPermissionsFail();
            }
            return true;
        }
        return false;
    }
    }
 

九、权限的工具类

/**
 * 动态权限工具类
 */
public class PermissionUtil {
 
    /**
     * 弹出对话框请求权限
     * @param activity
     * @param permissions
     * @param requestCode
     */
    public static void requestPermissions(Activity activity, String[] permissions, int requestCode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            activity.requestPermissions(permissions, requestCode);
        }
    }
 
    /**
     * 返回缺失的权限
     * @param context
     * @param permissions
     * @return 返回缺少的权限,null 意味着没有缺少权限
     */
    public static String[] getDeniedPermissions(Context context, String[] permissions) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ArrayList<String> deniedPermissionList = new ArrayList<>();
            for (String permission : permissions) {
                if (context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                    deniedPermissionList.add(permission);
                }
            }
            int size = deniedPermissionList.size();
            if (size > 0) {
                return deniedPermissionList.toArray(new String[deniedPermissionList.size()]);
            }
        }
        return null;
    }
 
}

以上是关于Android权限篇 Android 6.0动态权限申请的主要内容,如果未能解决你的问题,请参考以下文章

android 6.0动态权限的申请

在Android 6.0 设备上动态获取权限

Android 6.0以上动态请求权限的工具类

Android 6.0以上动态获取权限问题,百度语音识别

android 6.0+ 动态权限获取

Android 6.0: 动态权限管理的解决方案