Android PermissionUtils:运行时权限工具类及申请权限的正确姿势
Android PermissionUtils:运行时权限工具类及申请权限的正确姿势
PermissionUtil
经常写Android运行时权限申请代码,每次都是复制过来之后,改一下权限字符串就用,把代码搞得乱糟糟的,于是便有了封装工具类的想法,话不多说,先看怎么用:
工具类及Demo:github
简洁版申请权限
申请一个权限:
    PermissionUtils.checkAndRequestPermission(mContext, PERMISSION_CAMERA, REQUEST_CODE_CAMERA,
                new PermissionUtils.PermissionRequestSuccessCallBack() {
            @Override
            public void onHasPermission() {
                // 权限已被授予
                toCamera();
            }
        });
然后在onRequestPermissionsResult中:
if(PermissionUtils.isPermissionRequestSuccess(grantResults))
                {
                    // 权限申请成功
                    toCamera();
                }
什么?要同时申请多个权限?
    PermissionUtils.checkAndRequestMorePermissions(mContext, PERMISSIONS, REQUEST_CODE_PERMISSIONS,
                new PermissionUtils.PermissionRequestSuccessCallBack() {
            @Override
            public void onHasPermission() {
                // 权限已被授予
                toCamera();
            }
        });
当然上面这些都不是申请权限的正确姿势,理想的姿势应该是:
- 第一次申请权限:按照正常流程走;
- 如果用户第一次拒绝了权限申请,第二次申请时应向用户解释权限用途;
- 如果用户勾选了“不再询问”选项,应引导用户去设置页手动开启权限。
如图:
于是,引申出了复杂版的权限申请方法:
自定义权限申请:
PermissionUtils.checkPermission(mContext, PERMISSION_CAMERA,
                new PermissionUtils.PermissionCheckCallBack() {
            @Override
            public void onHasPermission() {
                // 已授予权限
                toCamera();
            }
            @Override
            public void onUserHasAlreadyTurnedDown(String... permission) {
                // 上一次申请权限被拒绝,可用于向用户说明权限原因,然后调用权限申请方法。
            }
            @Override
            public void onUserHasAlreadyTurnedDownAndDontAsk(String... permission) {
                // 第一次申请权限或被禁止申请权限,建议直接调用申请权限方法。
            }
        });
然后在onRequestPermissionsResult中:
PermissionUtils.onRequestPermissionResult(mContext, PERMISSION_CAMERA, grantResults, new PermissionUtils.PermissionCheckCallBack() {
                    @Override
                    public void onHasPermission() {
                        toCamera();
                    }
                    @Override
                    public void onUserHasAlreadyTurnedDown(String... permission) {
                        Toast.makeText(mContext, "我们需要"+Arrays.toString(permission)+"权限", Toast.LENGTH_SHORT).show();
                    }
                    @Override
                    public void onUserHasAlreadyTurnedDownAndDontAsk(String... permission) {
                        Toast.makeText(mContext, "我们需要"+Arrays.toString(permission)+"权限", Toast.LENGTH_SHORT).show();
                        // 显示前往设置页的dialog
                        showToAppSettingDialog();
                    }
                });
基本使用就是这些了,包括前往应用设置页的方法,也在工具类里面,具体使用可以看demo。
工具类及Demo:github
贴一下工具类代码:
package com.fadai.library;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import java.util.ArrayList;
import java.util.List;
/**
 * <pre>
 *     author : FaDai
 *     e-mail : i_fadai@163.com
 *     time   : 2017/06/13
 *     desc   : xxxx描述
 *     version: 1.0
 * </pre>
 */
public class PermissionUtils {
    /**
     * 检测权限
     *
     * @return true:已授权; false:未授权;
     */
    public static boolean checkPermission(Context context, String permission) {
        if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED)
            return true;
        else
            return false;
    }
    /**
     * 检测多个权限
     *
     * @return 未授权的权限
     */
    public static List<String> checkMorePermissions(Context context, String[] permissions) {
        List<String> permissionList = new ArrayList<>();
        for (int i = 0; i < permissions.length; i++) {
            if (!checkPermission(context, permissions[i]))
                permissionList.add(permissions[i]);
        }
        return permissionList;
    }
    /**
     * 请求权限
     */
    public static void requestPermission(Context context, String permission, int requestCode) {
        ActivityCompat.requestPermissions((Activity) context, new String[]{permission}, requestCode);
    }
    /**
     * 请求多个权限
     */
    public static void requestMorePermissions(Context context, List permissionList, int requestCode) {
        String[] permissions = (String[]) permissionList.toArray(new String[permissionList.size()]);
        requestMorePermissions(context, permissions, requestCode);
    }
    /**
     * 请求多个权限
     */
    public static void requestMorePermissions(Context context, String[] permissions, int requestCode) {
        ActivityCompat.requestPermissions((Activity) context, permissions, requestCode);
    }
    /**
     * 判断是否已拒绝过权限
     *
     * @return
     * @describe :如果应用之前请求过此权限但用户拒绝,此方法将返回 true;
     * -----------如果应用第一次请求权限或 用户在过去拒绝了权限请求,
     * -----------并在权限请求系统对话框中选择了 Don't ask again 选项,此方法将返回 false。
     */
    public static boolean judgePermission(Context context, String permission) {
        if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, permission))
            return true;
        else
            return false;
    }
    /**
     * 检测权限并请求权限:如果没有权限,则请求权限
     */
    public static void checkAndRequestPermission(Context context, String permission, int requestCode) {
        if (!checkPermission(context, permission)) {
            requestPermission(context, permission, requestCode);
        }
    }
    /**
     * 检测并请求多个权限
     */
    public static void checkAndRequestMorePermissions(Context context, String[] permissions, int requestCode) {
        List<String> permissionList = checkMorePermissions(context, permissions);
        requestMorePermissions(context, permissionList, requestCode);
    }
    /**
     * 检测权限
     *
     * @describe:具体实现由回调接口决定
     */
    public static void checkPermission(Context context, String permission, PermissionCheckCallBack callBack) {
        if (checkPermission(context, permission)) { // 用户已授予权限
            callBack.onHasPermission();
        } else {
            if (judgePermission(context, permission))  // 用户之前已拒绝过权限申请
                callBack.onUserHasAlreadyTurnedDown(permission);
            else                                       // 用户之前已拒绝并勾选了不在询问、用户第一次申请权限。
                callBack.onUserHasAlreadyTurnedDownAndDontAsk(permission);
        }
    }
    /**
     * 检测多个权限
     *
     * @describe:具体实现由回调接口决定
     */
    public static void checkMorePermissions(Context context, String[] permissions, PermissionCheckCallBack callBack) {
        List<String> permissionList = checkMorePermissions(context, permissions);
        if (permissionList.size() == 0) {  // 用户已授予权限
            callBack.onHasPermission();
        } else {
            boolean isFirst = true;
            for (int i = 0; i < permissionList.size(); i++) {
                String permission = permissionList.get(i);
                if (judgePermission(context, permission)) {
                    isFirst = false;
                    break;
                }
            }
            String[] unauthorizedMorePermissions = (String[]) permissionList.toArray(new String[permissionList.size()]);
            if (isFirst)// 用户之前已拒绝过权限申请
                callBack.onUserHasAlreadyTurnedDownAndDontAsk(unauthorizedMorePermissions);
            else       // 用户之前已拒绝并勾选了不在询问、用户第一次申请权限。
                callBack.onUserHasAlreadyTurnedDown(unauthorizedMorePermissions);
        }
    }
    /**
     * 检测并申请权限
     */
    public static void checkAndRequestPermission(Context context, String permission, int requestCode, PermissionRequestSuccessCallBack callBack) {
        if (checkPermission(context, permission)) {// 用户已授予权限
            callBack.onHasPermission();
        } else {
            requestPermission(context, permission, requestCode);
        }
    }
    /**
     * 检测并申请多个权限
     */
    public static void checkAndRequestMorePermissions(Context context, String[] permissions, int requestCode, PermissionRequestSuccessCallBack callBack) {
        List<String> permissionList = checkMorePermissions(context, permissions);
        if (permissionList.size() == 0) {  // 用户已授予权限
            callBack.onHasPermission();
        } else {
            requestMorePermissions(context, permissionList, requestCode);
        }
    }
    /**
     * 判断权限是否申请成功
     */
    public static boolean isPermissionRequestSuccess(int[] grantResults) {
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            return true;
        else
            return false;
    }
    /**
     * 用户申请权限返回
     */
    public static void onRequestPermissionResult(Context context, String permission, int[] grantResults, PermissionCheckCallBack callback) {
        if (PermissionUtils.isPermissionRequestSuccess(grantResults)) {
            callback.onHasPermission();
        } else {
            if (PermissionUtils.judgePermission(context, permission)) {
                callback.onUserHasAlreadyTurnedDown(permission);
            } else {
                callback.onUserHasAlreadyTurnedDownAndDontAsk(permission);
            }
        }
    }
    /**
     * 用户申请多个权限返回
     */
    public static void onRequestMorePermissionsResult(Context context, String[] permissions, PermissionCheckCallBack callback) {
        boolean isBannedPermission = false;
        List<String> permissionList = checkMorePermissions(context, permissions);
        if (permissionList.size() == 0)
            callback.onHasPermission();
        else {
            for (int i = 0; i < permissionList.size(); i++) {
                if (!judgePermission(context, permissionList.get(i))) {
                    isBannedPermission = true;
                    break;
                }
            }
            // 已禁止再次询问权限
            if (isBannedPermission)
                callback.onUserHasAlreadyTurnedDownAndDontAsk(permissions);
            else // 拒绝权限
                callback.onUserHasAlreadyTurnedDown(permissions);
        }
    }
    /**
     * 跳转到权限设置界面
     */
    public static void toAppSetting(Context context) {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= 9) {
            intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
            intent.setData(Uri.fromParts("package", context.getPackageName(), null));
        } else if (Build.VERSION.SDK_INT <= 8) {
            intent.setAction(Intent.ACTION_VIEW);
            intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
            intent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
        }
        context.startActivity(intent);
    }
    public interface PermissionRequestSuccessCallBack {
        /**
         * 用户已授予权限
         */
        void onHasPermission();
    }
    public interface PermissionCheckCallBack {
        /**
         * 用户已授予权限
         */
        void onHasPermission();
        /**
         * 用户已拒绝过权限
         *
         * @param permission:被拒绝的权限
         */
        void onUserHasAlreadyTurnedDown(String... permission);
        /**
         * 用户已拒绝过并且已勾选不再询问选项、用户第一次申请权限;
         *
         * @param permission:被拒绝的权限
         */
        void onUserHasAlreadyTurnedDownAndDontAsk(String... permission);
    }
}
工具类及Demo:github
Android PermissionUtils:运行时权限工具类及申请权限的正确姿势的更多相关文章
- Android之运行时相机权限和联系人权限获取
		原文:Android之运行时相机权限和联系人权限获取 本文链接:http://blog.csdn.net/qq_16628781/article/details/61623502 Android之运行 ... 
- Android ART运行时无缝替换Dalvik虚拟机的过程分析
		Android ART运行时无缝替换Dalvik虚拟机的过程分析 分类: Android2014-01-13 00:59 42722人阅读 评论(66) 收藏 举报 AndroidARTDalvikV ... 
- Rhino+envjs-1.2.js 在java运行网站js 工具类
		java爬虫遇到个页面加密的东西,找了些资料学习学习 做了个java运行js的工具类,希望对大家有用,其中用到client(获取js)可以自行换成自己的client.主要是用了 Rhino就是Java ... 
- Android开发之常用必备工具类图片bitmap转成字符串string与String字符串转换为bitmap图片格式
		作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ... 
- Android 请求运行时权限
		写文件到sd卡中,会报权限问题,需要动态申请申请运行时权限 1. MainActivity.java public class MainActivity extends Activity { priv ... 
- Android之SharedPreferences两个工具类
		相信Android的这个最简单的存储方式大家都很熟悉了,但是有一个小小技巧,也许你没有用过,今天就跟大家分享一下,我们可以把SharedPreferences封装在一个工具类中,当我们需要写数据和读数 ... 
- JAVA运行时问题诊断-工具应用篇
		该BLOG内容是之前在部门组织讨论运行时问题时自己写的PPT内容,内容以点带面,主要是方便以后自己回顾查看. 大纲包括:1.运行时问题分类 2.服务器自带工具 3.其他工具 4.例子 5.实际情况 运 ... 
- Android加载网络图片的工具类
		ImageView加载网络的图片 HttpUtil.java package com.eiice.httpuimagetils; import java.io.ByteArrayOutputStrea ... 
- Android—关于自定义对话框的工具类
		开发中有很多地方会用到自定义对话框,为了避免不必要的城府代码,在此总结出一个工具类. 弹出对话框的地方很多,但是都大同小异,不同无非就是提示内容或者图片不同,下面这个类是将提示内容和图片放到了自定义函 ... 
随机推荐
- .Net Core/Framework之Nginx反向代理后获取客户端IP等数据探索
			公司项目最近出现获取访问域名.端口.IP错误现象,通过排查发现, 之前项目一直通过Nginx自定义Headers信息来获取,但最近运维人员失误操作造成自定义Header信息丢失,造成项目拿不到对应的数 ... 
- Javaweb学习笔记——(十二)——————JSP指令:page指令、include指令、taglib指令,JavaBean,内省,EL表达式
			JSP指令JSP指令分类 JSP有三大指令: *page指令 *include指令 *taglib指令 在JSP中没有任何指令是必须的. 但基本上每个JSP都是使用page指令============ ... 
- mysql5.7安装(正确安装)实战
			一.二进制免编译包安装 参考:http://www.apelearn.com/bbs/forum.php?mod=viewthread&tid=10105&highlight=mys ... 
- 【SRM-06 D】五色战队&&【codeforces 788E】 New task
			原题链接:788E - New task Description 游行寺家里人们的发色多种多样,有基佬紫.原谅绿.少女粉.高级黑.相簿白等. 日向彼方:吾令人观其气,气成五彩,此天子气也. 琉璃:我们 ... 
- web api HttpResponseMessage的简单使用
			using Lemon.Common; using Lemon.WeChat.Model; using Lemon.WeChat.Services; using Newtonsoft.Json; us ... 
- dbms_redefinition在线重定义表结构
			dbms_redefinition在线重定义表结构 (2013-08-29 22:52:58) 转载▼ 标签: dbms_redefinition 非分区表转换成分区表 王显伟 在线重定义表结构 在线 ... 
- pyqt5-QWidget坐标系统和大小
			获取坐标和尺寸: 坐标的获取视频教程:https://v.qq.com/x/page/t085892mzh9.html x() y() 返回控件的坐标 相对于父控件的坐标(窗口框架左上角) ... 
- Flume配置Multiplexing Channel Selector
			1 官网内容 上面配置的是根据不同的heder当中state值走不同的channels,如果是CZ就走c1 如果是US就走c2 c3 其他默认走c4 2 我的详细配置信息 一个监听http端口 然后 ... 
- Codeforces #662C Binary Table
			听说这是一道$ Tourist$现场没出的题 Codeforces #662C 题意: 给定$n*m的 01$矩阵,可以任意反转一行/列($0$变$1$,$1$变$0$),求最少$ 1$的数量 $ n ... 
- $(function() {....}) ,(function($){...})(jQuery)
			$(function() {....}) 是 jQuery 中的经典用法,等同于 $(document).ready(function() {....}),即在页面加载完成后才执行某个函数,如果函数中 ... 
 
			
		