1. 权限简介
权限分级别,google 会对权限设置一个标记,如果标记为 dangerous,那么获取这个权限时,会寻求用户是否同意,如果权限相对安全,只要在 manifest 文件中设置之后,会自动添加,不需要获得用户允许。
比如,读取网络图片,需要在 manifest 中添加网络权限,网络权限相对安全,所以添加到 manifest 之后会自动获得授权而不需要用户同意;
但是,最安全的做法还是在使用权限之前判断一下权限是否获取到了,如果没获取到,会崩溃。之所以要判断一下,是因为, google 可能在下一个版本中将你使用的权限从安全标记为了危险,那么原先不需要获取用户允许的权限,现在就需要获取用户允许了,如果你没有判断,那么用户拒绝之后很有可能导致 app 功能无法使用或者崩溃。
2. 在manifest文件中添加权限
首先需要在 manifest 文件中添加有可能需要的权限。
<uses-permission android:name="android.permission.CAMERA"/>
如果不添加,则在调用 RequestPermission 时,是没有反应的。
3. 检查权限
请求权限之前先通过 ActivityCompat 来检查是否已经获取到权限,不然每次都去获取权限会很恶心:
private void handlePermission() {
// 判断当前是否有权限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
//已经获取权限则直接通过implicit intent调用相机
openCamera();
} else {
// 未获取权限,则弹窗,告知未获取权限
}
4. 请求权限
请求权限时,因为如果用户拒绝两次(有的版本上是一次),那么再次调用权限请求时,系统就不会弹窗了。或者是,弹窗中会出现“不再提醒”选项,用户勾选之后,再次调用权限请求时,app 什么都不会做。
所以为了避免这种情况,需要一个方法来判断是否用户勾选了“不再提醒”选项,如果未勾选,直接请求权限,弹出系统的提示框,如果勾选了,则弹出自定义的弹窗,提示权限被关闭,并且给与用户一个打开权限的开关来跳转到权限设置界面,上述代码补充完整逻辑如下:
private void handlePermission() {
// 判断当前是否有权限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
//已经获取权限则直接通过implicit intent调用相机
openCamera();
} else {
// 未获取权限,则弹窗,告知未获取权限
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
// 已勾选不再提醒,调用权限请求方法,app不会有任何操作,需要弹出自定义的弹窗
popSnackBar();
} else {
// 未勾选不再提醒,直接请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},1);
}
}
}
5. 跳转设置页面
private void popSnackBar() {
Snackbar.make(parent, "需要相机权限",Snackbar.LENGTH_INDEFINITE)
.setAction("开启权限", new View.OnClickListener() {
@Override
public void onClick(View v) {
// 进入app设置页面
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
// 传入具体的app路径
intent.setData(Uri.parse("package:" + getPackageName()));
// 判断是否有合适的跳转
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent,SETTING_INTENT_RESULT);
}
}
})
.show();
}
6. 获取图片回调
使用 startActivityForResult
传入 reuqestId 之后,可以在回调方法 onActivityResult
中捕获对应的 Intent 获取返回的数据,代码如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case CAMERA_INTENT_RESULT:
// 获取图片
if (resultCode == RESULT_OK && data != null) {
Bundle bundle = data.getExtras();
if (bundle != null) {
// 获取bitmap
Bitmap bitmap = (Bitmap) bundle.get("data");
// 使用glide设置图片
Glide.with(this)
.load(bitmap)
.into(imageView);
}
}
break;
case SETTING_INTENT_RESULT:
Toast.makeText(this, "从设置页面返回了", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}