Android动态权限申请实现步骤分解

 更新时间:2023年04月03日 08:52:47   作者:别偷我的猪_09  
对于一些危险权限在AndroidManifest清单文件中申请之后,还需要得到用户的许可并打开,才算是真正的开启了这个权限。所以可以使用动态申请权限,对于某个功能,如果需要开启某个权限,在用户使用它之前,弹窗提示用户是否要开启这个权限

Google 在 Android 6.0 开始引入了权限申请机制,将所有权限分成了正常权限和危险权限。App 每次在使用危险权限时需要动态的申请并得到用户的授权才能使用。

权限分类

系统权限分为两类:正常权限和危险权限。

正常权限:不会直接给用户隐私带来危险。如果你在其清单中列出了正常权限,系统将自动授予该权限。

危险权限:授予应用访问用户机密数据的权限。如果你在清单文件中列出了危险权限,则用户必须明确批准你的应用使用这些权限。那么危险权限有那些?日历(CALENDAR)、相机(CAMERA)、通讯录(CONTACTS)、位置(LOCATION)、拨号(PHONE)、短信(SMS)和存储(STORAGE)等。

<!-- 权限组:CALENDAR == 日历读取的权限申请 -->
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<!-- 权限组:CAMERA == 相机打开的权限申请 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 权限组:CONTACTS == 联系人通讯录信息获取/写入的权限申请 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<!-- 权限组:LOCATION == 位置相关的权限申请 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 权限组:PHONE == 拨号相关的权限申请 -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 权限组:SMS == 短信相关的权限申请 -->
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<!-- 权限组:STORAGE == 读取存储相关的权限申请 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

申请以上权限时,除了要在清单文件中添加权限,还需要通过代码动态申请。

动态权限核心函数

1. 检测权限

checkSelfPermission(@NonNull String permission)

2. 申请权限

requestPermissions(@NonNull String[] permissions, int requestCode)

3. 处理结果回调

onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)

4. 是否需要显示 UI 界面提示用户为什么需要这个权限

shouldShowRequestPermissionRationale(@NonNull String permission)

简易实现案例

步骤1:在 AndroidManifest.xml 添加要申请的权限。这里以存储权限为例

<!-- STORAGE == 读取存储相关权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

步骤2:封装一个 requestPermission 方法来动态检测和申请权限

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

requestPermission() 函数里会先检测存储权限,如果没开启则动态申请存储权限。

private void requestPermission() {
        // checkSelfPermission() 检测权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
            //TODO 申请存储权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    PERMISSION_REQUEST_CODE);
        }
    }

注意:这个 demo 里只申请了一个权限,当我们需要申请多个权限时,可以往requestPermissions 里的第二个参数添加其它需要的权限,因为它本就是一个 String 数组,且也要在 AndroidManifest里添加。

new String[]{Manifest.permission.READ_EXTERNAL_STORAGE
                    ,Manifest.permission.CAMERA}

步骤3:处理用户选择的结果(“允许” / “拒绝”),重写 onRequestPermissionsResult()方法。

//TODO 处理权限结果回调
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            //用户点击了“确定” == grantResults[0] == PackageManager.PERMISSION_GRANTED)
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.i("TAG", "onRequestPermissionsResult granted");
            } else {
                Log.i("TAG", "onRequestPermissionsResult denied");
                // TODO 用户拒绝权限申请,则弹出警示框
                showWaringDialog();
            }
        }
    }

步骤4:当用户拒绝权限,则弹出警示框,并在用户点击“确定”后直接退出页面。因为没有存储权限肯定不能使用该应用的。

/**
     * 用户拒绝权限的警示
     */
    private void showWaringDialog() {
        new AlertDialog.Builder(this)
                .setTitle("警告!")
                .setMessage("请前往设置->应用->权限管理->打开存储权限,否则无法正常使用!")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //TODO 一般情况下如果用户不授权的话,功能时无法运行的,则直接退出
                        finish();
                    }
                }).show();
    }

完整代码

MainActivity.java

package com.example.dynamicauthority;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
    private static final int PERMISSION_REQUEST_CODE = 999;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        requestPermission();
    }
    private void requestPermission() {
        // checkSelfPermission() 检测权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
            //TODO 申请存储权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    PERMISSION_REQUEST_CODE);
        }
    }
    //TODO 处理权限结果回调
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            //用户点击了“确定” == grantResults[0] == PackageManager.PERMISSION_GRANTED)
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.i("TAG", "onRequestPermissionsResult granted");
            } else {
                Log.i("TAG", "onRequestPermissionsResult denied");
                // TODO 用户拒绝权限申请,则弹出警示框
                showWaringDialog();
            }
        }
    }
    /**
     * 用户拒绝权限的警示
     */
    private void showWaringDialog() {
        new AlertDialog.Builder(this)
                .setTitle("警告!")
                .setMessage("请前往设置->应用->权限管理->打开存储权限,否则无法正常使用!")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //TODO 一般情况下如果用户不授权的话,功能时无法运行的,则直接退出
                        finish();
                    }
                }).show();
    }
}

到此这篇关于Android动态权限申请实现步骤分解的文章就介绍到这了,更多相关Android动态权限申请内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android简单实现无限滚动自动滚动的ViewPager

    Android简单实现无限滚动自动滚动的ViewPager

    这篇文章主要介绍了Android简单实现无限滚动自动滚动的ViewPager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底。所以试着封装一个比较好用的ViewPager,实现思路一起通过本文学习吧
    2016-12-12
  • Android提高之BLE开发Android手机搜索iBeacon基站

    Android提高之BLE开发Android手机搜索iBeacon基站

    这篇文章主要介绍了BLE开发Android手机搜索iBeacon基站,需要的朋友可以参考下
    2014-08-08
  • Android Studio 中的Gradle构建系统示例

    Android Studio 中的Gradle构建系统示例

    这篇文章主要介绍了Android Studio 中的Gradle构建系统示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • Android实现沉浸式状态栏

    Android实现沉浸式状态栏

    这篇文章主要为大家详细介绍了Android沉浸式状态栏的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • 安卓(Android)应用版本更新方法

    安卓(Android)应用版本更新方法

    Android 开发中对版本进行检查并更新的需求基本是所有应用必须有的功能,可是在实际开发中有些朋友就容易忽略一些细节。本文章提供解决方案,希望对大家有所帮助
    2016-07-07
  • Android Bitmap的加载优化与Cache相关介绍

    Android Bitmap的加载优化与Cache相关介绍

    这篇文章主要介绍了Android中性能优化之Bitmap的加载优化与Cache相关内容介绍,文中介绍的很详细,对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
    2017-02-02
  • Android水波纹载入控件CircleWaterWaveView使用详解

    Android水波纹载入控件CircleWaterWaveView使用详解

    这篇文章主要为大家详细介绍了Android水波纹载入控件CircleWaterWaveView使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • 实例详解Android文件存储数据方式

    实例详解Android文件存储数据方式

    总体的来讲,数据存储方式有三种:一个是文件,一个是数据库,另一个则是网络。下面通过本文给大家介绍Android文件存储数据方式,对android文件存储数据相关知识感兴趣的朋友一起学习吧
    2016-01-01
  • Flutter Http分块下载与断点续传的实现

    Flutter Http分块下载与断点续传的实现

    这篇文章主要介绍了Flutter Http分块下载与断点续传的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Kotlin学习教程之函数的默认参数

    Kotlin学习教程之函数的默认参数

    这篇文章主要给大家介绍了关于Kotlin学习教程之函数的默认参数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11

最新评论