安卓基础之《(16)—内容提供者(2)使用内容组件获取通讯信息》

一、运行时动态申请权限

1、Android系统为了防止某些App滥用权限,从6.0开始引入了运行时权限管理机制,允许App在运行过程中动态检查是否拥有某些权限,一旦发现缺少某种必需的权限,则系统会自动弹出小窗提示用户去开启该权限

二、动态申请权限的步骤

1、检查App是否开启了指定权限

调用ContextCompat的checkSelfPermission方法

public static int checkSelfPermission(@NonNull Context context, @NonNull String permission)

说明:

(1)context:传所在的Activity

(2)permission:权限

2、请求系统弹窗,以便用户选择是否开启权限

调用ActivityCompat的requestPermissions方法,即可命令系统自动弹出权限申请窗口

public static void requestPermissions(final @NonNull Activity activity, final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode)

说明:

(1)activity:传所在的Activity

(2)permissions:权限数组

(3)requestCode:标识符,表示请求的是什么类型的权限

3、判断用户的权限选择结果

重写Activity页面的权限请求回调方法onRequestPermissionsResult,在该方法内部处理用户的权限选择结果

public void onRequestPermissionsResult(requestCode, permissions, grantResults)

说明:

(1)requestCode:申请权限的时候,传递进去,回调方法使用这个来进行判断

(2)permissions:权限的数组列表(读、写)

(3)grantResults:用户操作后返回的授权结果

4、在清单文件里定义权限

老版本只要在清单文件里定义就好了,新版本不仅要在清单文件里定义,还需要动态去申请权限

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

<uses-permission android:name="android.permission.WRITE_CONTACTS"/>

<uses-permission android:name="android.permission.SEND_SMS"/>

<uses-permission android:name="android.permission.READ_SMS"/>

三、运行时动态申请权限-懒汉模式

1、懒汉模式,就是点击按钮时申请权限

2、例子

PermissionLazyActivity.java

java 复制代码
package com.example.chapter07_client;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;

import com.example.chapter07_client.util.PermissionUtil;
import com.example.chapter07_client.util.ToastUtil;

/**
 * 懒汉式
 */
public class PermissionLazyActivity 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.READ_SMS,
            Manifest.permission.SEND_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_permission_lazy);

        findViewById(R.id.btn_contact).setOnClickListener(this);
        findViewById(R.id.btn_sms).setOnClickListener(this);


    }

    @Override
    public void onClick(View view) {
        boolean result;
        if (view.getId() == R.id.btn_contact) {
            // 点击按钮后,首先检查有没有权限
            result = PermissionUtil.checkPermission(this, PERMISSIONS_CONTACTS, REQUEST_CODE_CONTACTS);
            if (result) {
                ToastUtil.show(this, "通讯录权限已获取");
            }
        } else if (view.getId() == R.id.btn_sms) {
            result = PermissionUtil.checkPermission(this, PERMISSIONS_SMS, REQUEST_CODE_SMS);
            if (result) {
                ToastUtil.show(this, "收发短信权限已获取");
            }
        }
    }

    /**
     *
     * @param requestCode 申请权限的时候,传递进去,回调方法使用这个来进行判断
     * @param permissions
     * @param grantResults
     */
    @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)) {
                    Log.d("sam", "通讯录权限获取成功");
                } else {
                    ToastUtil.show(this, "获取通讯录读写权限失败");
                    jumpToSettings();
                }
                break;
            case REQUEST_CODE_SMS:
                if (PermissionUtil.checkGrant(grantResults)) {
                    Log.d("sam", "收发短信权限获取成功");
                } else {
                    ToastUtil.show(this, "获取收发短信权限失败");
                    jumpToSettings();
                }
                break;
        }
    }

    /**
     * 拒绝多了,就不会弹窗了
     * 所以跳转到应用设置界面,让用户手工设置
     */
    private void jumpToSettings() {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.fromParts("package", getPackageName(), null));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
}

工具类PermissionUtil.java

java 复制代码
package com.example.chapter07_client.util;

import android.app.Activity;
import android.content.pm.PackageManager;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class PermissionUtil {

    // 检查多个权限,返回true表示已完全启用权限,返回false表示未完全启用权限
    public static boolean checkPermission(Activity act, String[] permissions, int requestCode) {
        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;
    }

    // 检查权限结果数组,返回true表示都已经获得授权,返回false表示至少有一个未获得授权
    public static boolean checkGrant(int[] grantResults) {
        // 遍历权限结果数组中的每条选择结果
        for (int grant : grantResults) {
            if (grant != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }
}

布局文件activity_permission_lazy.xml

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".PermissionLazyActivity">

    <Button
        android:id="@+id/btn_contact"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="读写通讯录"/>

    <Button
        android:id="@+id/btn_sms"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="收发短信"/>

</LinearLayout>

清单文件

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <queries>
        <package android:name="com.example.chapter07_server" />
    </queries>

    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication">

        <activity
            android:name=".PermissionLazyActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

四、运行时动态权限申请-饿汉模式

1、饿汉模式,就是当我们打开Activity的时候,上来就申请通讯录读写权限、收发短信权限

2、

相关推荐
·云扬·2 小时前
ClickHouse常用管理语句汇总:会话、磁盘、性能与复制管理
android·clickhouse
游戏开发爱好者82 小时前
2025年iOS应用上架App Store全指南,开发者必看
android·ios·小程序·https·uni-app·iphone·webview
a3158238062 小时前
Android CardView修改背景阴影
android·cardview·修改背景
kk哥88993 小时前
Android UI 优化指南:流畅度与体验双提升
android·ui
摘星编程4 小时前
Flutter for OpenHarmony 实战:SliverList 滑动列表详解
android·javascript·flutter
abbiz4 小时前
30 个 Android 面试高频问题及答案
android·面试·职场和发展
冬奇Lab4 小时前
【Kotlin系列04】类与对象基础:从Java Bean到Data Class的优雅蜕变
android·kotlin·编程语言
笔夏4 小时前
【安卓学习之webRTC】学习相关资料
android·学习·webrtc
_李小白4 小时前
【Android 美颜相机】第三天:初识GPUImageView
android·数码相机