Android 动态申请应用权限

一、概述

Android 6.0 (API 23) 之前应用的权限在安装时全部授予,运行时应用不再需要询问用户。在 Android 6.0 或更高版本对权限进行了分类,对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予。

Android 6.0以下,在AndroidManifest.xml文件中注册权限即可。
Android 6.0及其以后,既要在AndroidManifest.xml文件中注册,又要动态申请危险权限。

二、Android系统权限

两个最重要保护级别是 正常权限危险权限

(1)正常权限:涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域。这些权限在应用安装时授予,运行时不再询问用户。例如: 网络访问、WIFI状态、音量设置等。完整的正常权限列表参考官网 正常权限

(2)危险权限:涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域。例如: 读取通讯录、读写存储器数据、获取用户位置等。如果应用声明需要这些危险权限,则必须在运行时明确告诉用户,让用户手动授予。

权限组名 权限名称
CALENDAR(日历) READ_CALENDAR
WRITE_CALENDAR
CAMERA(相机) CAMERA
CONTACTS(联系人) READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION(位置) ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE(麦克风) RECORD_AUDIO
PHONE(手机) READ_PHONE_STATE
CALL_PHONE
ERAD_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORS(传感器) BODY_SENSORS
SMS(短信) SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE(存储卡) READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

PS: 在 AndroidManifest.xml 声明过的危险权限对应的权限组可以在系统 “设置” -> “应用” -> “应用信息” -> “权限” 中查看,可以手动授权和取消授权。

权限组和权限在Android代码中以 字符串常量 来表示,分别定义在以下两个 静态内部类 的字段中:

  • android.Manifest.permission_group(权限组):
    • Manifest.permission_group.CALENDAR
    • Manifest.permission_group.STORAGE
    • ......
  • android.Manifest.permission(权限):
    • Manifest.permission.READ_CALENDAR
    • Manifest.permission.READ_EXTERNAL_STORAGE
    • ......

三、动态申请权限

首先,需要在AndroidManifest.xml清单中静态申请权限,否则无法动态申请权限

AndroidManifest.xml

<manifest ...>

    <uses-permission android:name="android.permission.READ_CALENDAR"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

    <application ...>
        ...
    </application>
</manifest>

然后,在java代码中写动态申请权限的逻辑代码

MainActivity.java

import android.Manifest;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {

    /**
     * 读取日历
     * 相机
     * 读取手机联系人
     */
    private String[] permissions = new String[]{
            Manifest.permission.READ_CALENDAR,
            Manifest.permission.CAMERA,
            Manifest.permission.READ_CONTACTS
    };

    private final int MY_REQUEST_CODE = 1000;
    private String TAG = "zhumeng";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PackageManager packageManager = this.getPackageManager();

        PermissionInfo permissionInfo = null;
//        PermissionGroupInfo permissionGroupInfo = null;

        for (int i = 0; i < permissions.length; i++) {
            try {
                permissionInfo = packageManager.getPermissionInfo(permissions[i], 0);
//                permissionGroupInfo = packageManager.getPermissionGroupInfo(permissions[i], 0);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            CharSequence permissionName = permissionInfo.loadLabel(packageManager);
//            CharSequence permissionnGropName = permissionGroupInfo.loadLabel(packageManager);
            if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED){
                // 未获取权限
                Log.i(TAG, "您未获得【" + permissionName + "】的权限 ===>");
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])){
                    // 这是一个坑,某些手机弹出提示时没有永不询问的复选框,点击拒绝就默认勾上了这个复选框,而某些手机上即使勾选上了永不询问的复选框也不起作用
                    Log.i(TAG, "您勾选了不再提示【" + permissionName + "】权限的申请");
                } else {
                    ActivityCompat.requestPermissions(this, permissions, MY_REQUEST_CODE);
                }
            } else {
                Log.i(TAG, "您已获得了【" + permissionName + "】的权限");
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PackageManager packageManager = this.getPackageManager();
        PermissionInfo permissionInfo = null;
        for (int i = 0; i < permissions.length; i++) {
            try {
                permissionInfo = packageManager.getPermissionInfo(permissions[i], 0);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            CharSequence permissionName = permissionInfo.loadLabel(packageManager);
            if (grantResults[i] == PackageManager.PERMISSION_GRANTED){
                Log.i(TAG, "您同意了【" + permissionName + "】权限");
            } else {
                Log.i(TAG, "您拒绝了【" + permissionName + "】权限");
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_57542177/article/details/124538279