动态获取权限

这是一个老生常谈的问题,在Android6.0之前,只要同意安装应用,所有在Manifest文件里声明的权限都能被获取到,而从6.0开始,加入了动态权限,权限被分为normal permission 和 dangerous permission,dangrous permission都是一些可能会侵犯到使用者隐私的权限,所以这些权限都必须在应用需要使用该权限时对用户进行询问是否授予权限。
下面就以一个打电话的权限来演示。在布局文件中写一个button,并给这个button设置点击事件为call()方法。
首先在Manifest文件中加入<uses-permission android:name="android.permission.CALL_PHONE" />
然后写了下面两个方法,我们开始分析这两个方法。

private void call() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, PERMISSIONS_REQUEST_CALL_PHONE);
            } else {
                callPhone();
            }
        }
        callPhone();
    }


    public void callPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:" + "10086");
        intent.setData(data);
        try {
            startActivity(intent);
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

callPhone()方法是我们封装好的一个给10086打电话的方法(雾,没有什么难点,就不解释了。
重点来看call()方法,首先我们要对当前手机的SDK的版本进行判断,如果是Android6.0及以上才去进行权限的判断和获取,否则就直接执行callPhone()方法。当确定SDK版本在6.0及以上时,首先要去确认一下是否已经获取到了权限,如果已经获取到了权限则直接执行callPhone(),没有的话去执行ActivityCompat.requestPermissions(Activity activity,String[] permissions, int requestCode)方法来获取权限。这个方法一共要传入三个参数,第一个是一个activty,第二个是以字符串形式保存的权限名的数组,这里我这只需要申请一个权限,所以就直接在方法里初始化了这个数组,第三个是一个int型的requesetcode,因为我在全局变量里加入了private static final int PERMISSIONS_REQUEST_CALL_PHONE = 1;,所以这里实际上相当于传的是一个1。这个值在我们后边会说到的onRequestPermissionsResult()方法里会用到。

以上我们已经实现了动态权限的获取,但是如果只按以上的代码来写在用户体验上有一些小小的不友好,比如在获取权限时,不论能否获取到权限,用户都不能得到一个有效的反馈,我们希望在申请完权限后,如果用户给了这个权限,就直接运行我们的方法,而当没有获取到时就弹出一个Toast来提示用户没有获取到权限。想要达到这样的效果,我们就需要重写onRequestPermissionsResult方法。

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == PERMISSIONS_REQUEST_CALL_PHONE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                callPhone();
            } else {
                Toast.makeText(this, "需要权限", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

在这个方法里,我们用到了上面提到的requestcode,我们需要对每个requestcode进行独立的判断,当获取到的结果为PackageManager.PERMISSION_GRANTED时,说明权限获取成功了,这里的数组grantResults是与上面发送请求时的String数组一一对应的。当权限获取成功时我们直接运行callPhone()方法,没有成功时弹出一个Toast,这样我们就达到了我们想要的效果。