Android动态获取权限
- 概述
- 动态获取权限
- 具体实现
- layout布局代码
- 回调函数onRequestPermissionsResult
- 权限判断工具类
- 清单文件
- 方式一:懒汉式
- 方式二:饿汉式
概述
如果是android6.0以下的版本,只需要在manifest声明对应的权限即可。但是这样会大大降低系统的安全性。所以在android6.0及其以后,app获取权限需要得到用户的反馈才可以。
动态获取权限
动态获取权限,可以分为两种情况。情况一,操作到app特定的功能,需要某些权限时进行动态获取,这种情况即为“懒汉式”获取。情况二,在初始情况时(在onCreate中获取),直接获取到所有需要的权限,这种情况即为“饿汉式”。
具体实现
比如某个app在使用的时候需要获取到到通讯录的读写权限,短信的读取发送权限。
注意:读通讯录是一个权限,写通讯录是一个权限。这是两个权限。
短信的读取是一个权限,短信的发送是操作短信的另一个权限。
layout布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_contact"
android:text="获取通讯录的读写权限"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_sms"
android:text="获取短信的查看发送权限"/>
</LinearLayout>
获取通讯录的读写权限按钮的id是:btn_contact
获取短信的查看发送权限按钮的id是:btn_sms
回调函数onRequestPermissionsResult
该回调函数会在用户点击完动态获取权限的弹窗后执行。当弹出动态获取权限的窗口后,用户在该窗口进行选择“允许”或“不允许”,当选择完后,即可在该回调函数中进行相应的判断,判断用户是否允许了权限。
该函数在MainActivity类中
//点击申请权限弹框后的回调函数
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
权限判断工具类
public class PermissionUtil {
//检查某个功能的多个权限,返回true表示已完全启用权限,返回false表示未完全启用权限
//比如通讯录这个功能,需要获取它有的多个权限[读权限,写权限]
//act:当前的Activity
//permissions:某个功能的权限集合,如通讯录的[读,写]
//requestCode:标识一下“某个功能”
public static boolean checkPermission(Activity act, String[] permissions, int requestCode){
//判断android的版本
//Build.VERSION.SDK_INT:当前android的版本
//Build.VERSION_CODES.M:android6.0
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){//安卓版本在6.0及以后才需要判断 M就是6.0
//check的含义:权限是否开启
//这里给了默认值PackageManager.PERMISSION_GRANTED,意思是开启权限
int check = PackageManager.PERMISSION_GRANTED;//默认授权的值
for (String permission:permissions){
//返回结果为是否授权
check = ContextCompat.checkSelfPermission(act, permission);
//如果没有授权,则退出
if (check!=PackageManager.PERMISSION_GRANTED){
break;
}
}
//未开启该权限,则请求系统弹窗,好让用户选择是否立即开启权限
if (check!=PackageManager.PERMISSION_GRANTED){
//弹窗,用户操作
ActivityCompat.requestPermissions(act,permissions,requestCode);
return false;
}
}
return true;
}
//grantResults:是用户点“授权”完弹窗后的授权结果数组
//检查权限结果数组,返回true表示都已经获得授权。返回false表示至少有一个未获得授权
public static boolean checkGrant(int[] grantResults) {
if (grantResults!=null){
//遍历权限结果数组中的每条选择结果
for (int grant:grantResults){
//未获得授权
if (grant!=PackageManager.PERMISSION_GRANTED){
return false;
}
}
return true;
}
return false;
}
}
清单文件
声明权限权限(必须声明)
<!-- 声明读写通讯录权限-->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<!--声明读发短信权限-->
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
方式一:懒汉式
上面说过,懒汉式,是在app操作到特定功能时从获取相应权限,在这里的“特定功能”就是在点击按钮时,动态获取权限。
定义权限数组
//通信录的读写权限
private static final String[] PERMISSIONS_CONTACTS=new String[]{
Manifest.permission.READ_CONTACTS,//读通讯录
Manifest.permission.WRITE_CONTACTS//写通讯录
};
//短信的发送、读取权限
private static final String[] PERMISSIONS_SMS=new String[]{
Manifest.permission.SEND_SMS,//发送短信
Manifest.permission.READ_SMS//读取短信
};
标识码
//标识通讯录
private static final int REQUEST_CODE_CONTACTS=1;
//标识短信
private static final int REQUEST_CODE_SMS=2;
点击事件监听
实现View.OnClickListener,并实现onClick方法
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_contact:
PermissionUtil.checkPermission(this,PERMISSIONS_CONTACTS,REQUEST_CODE_CONTACTS);
break;
case R.id.btn_sms:
PermissionUtil.checkPermission(this,PERMISSIONS_CONTACTS,REQUEST_CODE_SMS);
break;
}
}
我们可以看到,如果没有授权就会执行到工具类PermissionUtil中的如下语句:
ActivityCompat.requestPermissions(act,permissions,requestCode);
它会出现弹窗,给用户选择是否获取所有权限
用户选择完后就会回调Activity中的,所以我们可以在该函数中进行是否授权的判断
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
MainActivity完整代码
package com.example.demo8;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.example.demo8.util.PermissionUtil;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
//通信录的读写权限
private static final String[] PERMISSIONS_CONTACTS=new String[]{
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS
};
//短信的发送、读取权限
private static final String[] PERMISSIONS_SMS=new String[]{
Manifest.permission.SEND_SMS,
Manifest.permission.READ_SMS
};
//标识通讯录
private static final int REQUEST_CODE_CONTACTS=1;
//标识短信
private static final int REQUEST_CODE_SMS=2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置监听事件
findViewById(R.id.btn_contact).setOnClickListener(this);
findViewById(R.id.btn_sms).setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_contact:
//上下文、权限数组、标识
PermissionUtil.checkPermission(this,PERMISSIONS_CONTACTS,REQUEST_CODE_CONTACTS);
break;
case R.id.btn_sms:
PermissionUtil.checkPermission(this,PERMISSIONS_SMS,REQUEST_CODE_SMS);
break;
}
}
//点击申请权限弹框后的回调函数
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case REQUEST_CODE_CONTACTS:
if (PermissionUtil.checkGrant(grantResults)){
Toast.makeText(this, "通讯录权限获取成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "获取通讯录读写权限获取失败", Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_CODE_SMS:
if (PermissionUtil.checkGrant(grantResults)){
Toast.makeText(this, "收发短信权限获取成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "收发短信权限获取失败", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
方式二:饿汉式
饿汉式,是在“onCreate”的时候就进行权限的申请,一次性到位。
我们将所有需要申请的权限放到一个数组中
//将权限放到一个数组中
private static final String[] PERMISSIONS=new String[]{
//通信录的读写权限
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS,
//短信的发送、读取权限
Manifest.permission.SEND_SMS,
Manifest.permission.READ_SMS
};
在oncreate中进行权限的申请
其余原理与懒汉式相同,只是申请权限的时间不同而已。
通讯录
短信
MainActivity代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
//将权限放到一个数组中
private static final String[] PERMISSIONS=new String[]{
//通信录的读写权限
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS,
//短信的发送、读取权限
Manifest.permission.SEND_SMS,
Manifest.permission.READ_SMS
};
private static final int REQUEST_CODE=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/初始获取权限
PermissionUtil.checkPermission(this,PERMISSIONS,REQUEST_CODE);
//设置监听事件
findViewById(R.id.btn_contact).setOnClickListener(this);
findViewById(R.id.btn_sms).setOnClickListener(this);
}
//饿汉式这里无用
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_contact:
break;
case R.id.btn_sms:
break;
}
}
//点击申请权限弹框后的回调函数
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case REQUEST_CODE:
if (PermissionUtil.checkGrant(grantResults)){
Toast.makeText(this, "权限获取成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "权限获取失败", Toast.LENGTH_SHORT).show();
}
break;
}
}
}