zoukankan      html  css  js  c++  java
  • 【Android 应用开发】动态权限管理示例 ( 使用原生代码实现 | 申请权限 | 判定权限申请结果 | 判定 “ 不再询问 “ 情况 )及代码示例

    一、申请权限

    首先 , 判定权限是否已经通过 , 如果没有通过再进行申请 ;
    如果下面函数返回值为 PackageManager.PERMISSION_GRANTED , 说明权限申请通过 ;
    如果返回值为 PackageManager.PERMISSION_DENIED , 说明权限没有被授予 ;

    ContextCompat.checkSelfPermission(mActivity, mRequestPermissions[i]);

    然后 , 申请没有通过的权限 ;
    第 2个参数是 String 数组 , 内容是权限字符串 ;

       /**
         * 需要申请的权限
         */
        protected String[] mRequestPermissions = new String[]{
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
        
        ActivityCompat.requestPermissions(mActivity, mRequestPermissions, REQUEST_CODE);

    完整过程 :
    在 Build.VERSION_CODES.M , Android 6.0 ( API 23 ) 才启用动态权限申请 ;
    只要有 任何 1 个权限没有通过 , 就需要权限申请 ;

     /**
         * 请求动态权限
         *
         * @return
         */
        public boolean requestPermission() {
            // Android 6.0 ( API 23 ) 才启用动态权限申请
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                // 用户是否不同意权限, 只要有 1 个不同意, 则为 true, 默认 false
                boolean isDisagree = false;
    
                // 判定是否有权限未获取
                for (int i = 0; i < mRequestPermissions.length; i++) {
                    if (ContextCompat.checkSelfPermission(
                            mActivity,
                            mRequestPermissions[i]) != PackageManager.PERMISSION_GRANTED) {
                        isDisagree = true;
                    }
                }
    
                if (isDisagree) {
                    // 存在权限没有通过,需要申请
                    ActivityCompat.requestPermissions(mActivity, mRequestPermissions, REQUEST_CODE);
                    return false;
                } else {
                    // 所有权限都已同意
                    return true;
                }
            } else {
                // 6.0 以下默认有动态权限
                return true;
            }
        }

    二、判定权限申请结果

    在 Activity 的 onRequestPermissionsResult 回调方法中 , 可以获取到权限是否授予 ;

       @Override
        public void onRequestPermissionsResult(
                int requestCode,
                @NonNull String[] permissions,
                @NonNull int[] grantResults) {
        }

    遍历第 3个参数 grantResults 数组 , 如果指定索引的元素值为 − 1 , 说明 permissions 数组中指定的权限没有授予通过 , 被用户拒绝了 ;

    如果 grantResults 数组中所有的值都为 0 , 说明所有权限授予通过 , 可以继续执行后续操作 ;

    public void onRequestPermissionsResult(
                int requestCode,
                @NonNull String[] permissions,
                @NonNull int[] grantResults) {
    
            if (REQUEST_CODE != requestCode) {
                return;
            }
    
            // 权限是否赋予完毕, 如果有任意一个没有同意, 则判定权限申请失败
            boolean allAgree = true;
    
            // 遍历 grantResults 数组, 判定哪个权限被拒绝了
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] == -1) {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permissions[i])) {
                        // 被用户拒绝了, 但是还可以申请, 说明没有设置 "不再询问" 选项
                    } else {
                        // 被用户拒绝了, 不能弹出, 说明用户设置了 "不再询问" 选项
                        showDialog();
                    }
                    allAgree = false;
                }
            }
    
            // 如果都同意, 则执行相关操作
            if (allAgree) {
                Toast.makeText(mActivity, "权限设置完毕, 执行相关操作", Toast.LENGTH_LONG).show();
            }
        }

    三、判定 " 不再询问 " 情况

    使用 ActivityCompat.shouldShowRequestPermissionRationale 方法判定用户是否选择了 " 不再询问 " 选项 ;

    ActivityCompat.shouldShowRequestPermissionRationale(mActivity, 权限字符串) ;

    shouldShowRequestPermissionRationale 方法的含义是当前是否 提示用户进行权限申请 , 指的是显示给用户申请权限的理由 ;

    是否显示申请权限的原理 , 也就是 显示给用户 " 为什么应用需要你授予这个权限 " , 要想方设法劝用户授予这个权限 , 以及说明不授予权限不能使用的哪些功能 ;

    如果该方法 返回 true , 则显示 ; 如果该方法返回 false , 则不显示 ;

    分为四种情况 :

    ① 首次申请 : 由于是第 1 1 1 次申请权限 , 直接申请即可 , 不需要给用户显示申请权限的理由 , 返回 false ;

    ② 用户拒绝了申请 : 如果用户拒绝了权限的申请 , 开发者需要给用户显示 " 为什么申请该权限 , 要使用权限做那些事 " , 因此需要给用户提示 , 返回 true ;

    ③ 用户拒绝申请并选择 " 不再询问 " : 用户已经明确拒绝 , 就不要再骚扰用户了 , 不用给出进一步的提示信息 , 返回 false ;

    ④ 用户同意权限申请 : 用户已经同意了 , 也不用给用户进行原理提示 , 返回 false ;

    Google 的意思是如果用户选择了 " 不再询问 " , 那开发者就不能在提及与该权限相关的事了 ;
    但是我们开发时总想把用户引导到权限设置界面 , 让用户自己设置 , 因此这里就有了这个 " 不再询问 " 判定问题 ;

    有点反直觉 ;

    判定 " 不再询问 " 情况 :

    在 Activity 的 onRequestPermissionsResult 方法中 ,

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

    在用户拒绝权限的前提下 , 如果

    ActivityCompat.shouldShowRequestPermissionRationale(mActivity, 权限字符串)

    方法返回 false , 此时就是用户点击了 " 不再询问 " 选项 ;

    只能在上述情况下判定 , 其它情况都判定不了 ;

    四、完整代码示例



    1、权限管理代码

    权限管理代码 :

    package com.example.permission;
    
    import android.Manifest;
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.os.Build;
    import android.provider.Settings;
    import android.widget.Toast;
    
    import androidx.annotation.NonNull;
    import androidx.core.app.ActivityCompat;
    import androidx.core.content.ContextCompat;
    
    public class PermissionManager {
    
        /**
         * 申请权限的 Activity 界面
         */
        private Activity mActivity;
    
        /**
         * "不再询问" 后的引导对话框
         */
        private AlertDialog mAlertDialog;
    
        /**
         * 申请权限的请求码, 要求必须 >0
         */
        public final int REQUEST_CODE = 100;
    
        /**
         * 需要申请的权限
         */
        protected String[] mRequestPermissions = new String[]{
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
    
        public PermissionManager(Activity activity) {
            this.mActivity = activity;
        }
    
        /**
         * 请求动态权限
         *
         * @return
         */
        public boolean requestPermission() {
            // Android 6.0 ( API 23 ) 才启用动态权限申请
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                // 用户是否不同意权限, 只要有 1 个不同意, 则为 true, 默认 false
                boolean isDisagree = false;
    
                // 判定是否有权限未获取
                for (int i = 0; i < mRequestPermissions.length; i++) {
                    if (ContextCompat.checkSelfPermission(
                            mActivity,
                            mRequestPermissions[i]) != PackageManager.PERMISSION_GRANTED) {
                        isDisagree = true;
                    }
                }
    
                if (isDisagree) {
                    // 存在权限没有通过,需要申请
                    ActivityCompat.requestPermissions(mActivity, mRequestPermissions, REQUEST_CODE);
                    return false;
                } else {
                    // 所有权限都已同意
                    return true;
                }
            } else {
                // 6.0 以下默认有动态权限
                return true;
            }
        }
    
        public void onRequestPermissionsResult(
                int requestCode,
                @NonNull String[] permissions,
                @NonNull int[] grantResults) {
    
            if (REQUEST_CODE != requestCode) {
                return;
            }
    
            // 权限是否赋予完毕, 如果有任意一个没有同意, 则判定权限申请失败
            boolean allAgree = true;
    
            // 遍历 grantResults 数组, 判定哪个权限被拒绝了
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] == -1) {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permissions[i])) {
                        // 被用户拒绝了, 但是还可以申请, 说明没有设置 "不再询问" 选项
                    } else {
                        // 被用户拒绝了, 不能弹出, 说明用户设置了 "不再询问" 选项
                        showDialog();
                    }
                    allAgree = false;
                }
            }
    
            // 如果都同意, 则执行相关操作
            if (allAgree) {
                Toast.makeText(mActivity, "权限设置完毕, 执行相关操作", Toast.LENGTH_LONG).show();
            }
        }
    
        /**
         * 用户选择 "不再询问" 后的提示方案
         */
        protected void showDialog() {
            // 不管同意/拒绝 , 只弹出一次
            if (mAlertDialog != null){
                return;
            }
    
            mAlertDialog = new AlertDialog.Builder(mActivity)
                    .setMessage("手动设置权限")
                    .setPositiveButton("设置", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // 跳转到设置界面
                            Intent intent = new Intent(
                                    Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                                    Uri.parse("package:com.example.permission")
                            );
                            mActivity.startActivity(intent);
    
                            mAlertDialog.cancel();
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            mAlertDialog.cancel();
                        }
                    })
                    .create();
            mAlertDialog.show();
        }
    }

    主界面代码

    package com.example.permission;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.view.View;
    
    import com.example.permission.databinding.ActivityMainBinding;
    
    public class MainActivity extends AppCompatActivity {
    
        /**
         * 权限管理
         */
        private PermissionManager mPermissionManager;
    
        /**
         * 视图绑定
         */
        private ActivityMainBinding binding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            binding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(binding.getRoot());
    
            binding.button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mPermissionManager = new PermissionManager(MainActivity.this);
                    mPermissionManager.requestPermission();
                }
            });
        }
    
        @Override
        public void onRequestPermissionsResult(
                int requestCode,
                @NonNull String[] permissions,
                @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            mPermissionManager.onRequestPermissionsResult(requestCode,
                    permissions, grantResults);
        }
    }

    五  博客源码 

    GitHub : https://github.com/han1202012/PermissionManager

    文章出处:感谢这篇文章很直接很清晰的反映了安卓6及以上的版本申请权限的过程,过程非常清晰明了,特注明出处,如有侵权,请作者联系,第一时间删除。感谢作者的好文分享

    【Android 应用开发】动态权限管理示例 ( 使用原生代码实现 | 申请权限 | 判定权限申请结果 | 判定 “ 不再询问 “ 情况 ) (136.la)

    半斤八两开始写BLOG了
  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/freewsf/p/15576570.html
Copyright © 2011-2022 走看看