android6.0权限管理工具EasyPermissionUtil

前言

android6.0開始,权限的申请发生了改变,申请变的动态化,也就是执行时权限,和iOS相仿,动态化的意思是指,在每次使用须要危急权限的方法的时候。须要检查程序是否获得了该权限的许可。动态化的权限申请能够让用户更加清晰的知道程序须要什么权限。以及程序中哪些地方的操作须要涉及用户安全。

不再是只在程序安装的时候,一次性把所须要的普通的、危急级别的权限一次性列出来。然后展示给用户。

当project项目的target Sdk为23时,因为考虑到用户假设没有进行权限的动态检查,那么在执行到须要权限的代码时,会发生crash。而当你的target Sdk为23下面时,则不强制要求权限的动态监測,此时app不会crash。还是能够正常的使用功能。

Google官网上动态申请权限的方法分了在Activity和Fragment这两种,通过ContextCompat以及子类,ActivityCompat和FragmentCompat去进行权限的申请和权限的检查,而申请的方式是弹出一个系统的不能够改写的对话框。结果是通过Activity和Fragment的onRequestPermissionResult()方法进行返回。

详细能够參考官网

可是这样的代码会促使以前的project进行大改造或者说代码的逻辑会耦合的写在同一个方法里。显的不方便和臃肿。

所以下面的EasyPermissionUtil就是简化权限请求的方式,同一时候能够使代码的逻辑更加清晰。

EasyPermissionUtil:简化权限请求

因为权限的请求和结果的返回须要分开Activity和Fragment两种去进行操作,这样会比較麻烦,所以EasyPermissionUtil中投机取巧,通过开启一个新的activity进行权限申请和检查的操作。这样不用去区分多种情况,同一时候也能够把全部的申请过程和结果统一由EasyPermissionUtil进行处理。

接下来看一下总体的思想:

使用的方法

PermissionUtil.getInstance().request(MainActivity.this, new String[]{Manifest.permission.READ_CALENDAR}, mRequestCode,
    new PermissionResultCallBack() {
        @Override
        public void onPermissionGranted() {
            // 当全部权限的申请被用户允许之后,该方法会被调用
        }

        @Override
        public void onPermissionDenied(String... permissions) {
            // 当权限申请中的某一个或多个权限,被用户以前否定了,并确认了不再提醒时,也就是权限的申请窗体不能再弹出时,该方法将会被调用
        }

        @Override
        public void onRationalShow(String... permissions) {
            // 当权限申请中的某一个或多个权限,被用户否定了,但没有确认不再提醒时,也就是权限窗体申请时,但被否定了之后,该方法将会被调用.
        }
    });

项目源代码下载以及介绍。请看github。

项目源代码

在PermissionUtil中,要做的是:

1.进行权限检查

2.没有得到权限许可的进行权限申请

3.返回权限申请的结果

public class PermissionUtil {

    private PermissionResultCallBack mPermissionResultCallBack;
    private volatile static PermissionUtil instance;
    private int mRequestCode;
    private Context mContext;
    private Fragment mFragment;
    private List<PermissionInfo> mPermissionListNeedReq;
    private String[] mPermissions;

    public static PermissionUtil getInstance() {
        if (instance == null) {
            synchronized (PermissionUtil.class) {
                if (instance == null) {
                    instance = new PermissionUtil();
                }
            }
        }
        return instance;
    }

    /**
     * 用于fragment中请求权限
     * @param fragment
     * @param permissions
     * @param requestCode
     * @param callBack
     */
    public void request(@NonNull Fragment fragment,@NonNull String[] permissions,@NonNull int requestCode, PermissionResultCallBack callBack) {
        this.mFragment = fragment;
        this.request(fragment.getActivity(), permissions, requestCode, callBack);
    }

    /**
     * 用于activity中请求权限
     * @param context
     * @param permissions
     * @param requestCode
     * @param callBack
     */
    public void request(@NonNull Context context,@NonNull String[] permissions,@NonNull int requestCode, PermissionResultCallBack callBack) {

        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw new RuntimeException("request permission only can run in MainThread!");
        }

        if (permissions.length == 0) {
            return;
        }

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            onGranted();
            return;
        }

        this.mContext = context;
        this.mPermissions = permissions;
        this.mRequestCode = requestCode;
        this.mPermissionResultCallBack = callBack;
        this.mPermissionListNeedReq = new ArrayList<PermissionInfo>();

        if (needToRequest()) {
            requestPermissions();
        } else {
            onGranted();
        }
    }

    /**
     * 通过开启一个新的activity作为申请权限的媒介
     */
    private void requestPermissions() {

        Intent intent = new Intent(mContext, HelpActivity.class);
        intent.putExtra("permissions", mPermissions);
        intent.putExtra("requestCode", mRequestCode);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivity(intent);
    }

    /**
     * 检查是否须要申请权限
     * @return
     */
    private boolean needToRequest() {
        for (String permission : mPermissions) {
            int checkRes = ContextCompat.checkSelfPermission(mContext, permission);
            if (checkRes != PackageManager.PERMISSION_GRANTED) {
                PermissionInfo info = new PermissionInfo(permission);
                if (mContext instanceof Activity &&
                        ActivityCompat.shouldShowRequestPermissionRationale((Activity) mContext, permission)) {
                    info.setRationalNeed(true);
                }
                mPermissionListNeedReq.add(info);
            }
        }

        if (mPermissionListNeedReq.size() > 0) {
            mPermissions = new String[mPermissionListNeedReq.size()];
            for (int i = 0; i < mPermissionListNeedReq.size(); i++) {
                mPermissions[i] = mPermissionListNeedReq.get(i).getName();
            }
            return true;
        }

        return false;
    }

    /**
     * 申请权限结果返回
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @TargetApi(Build.VERSION_CODES.M)
    protected void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {

        if (requestCode == mRequestCode) {

            if (mContext != null && mContext instanceof Activity) {
                ((Activity) mContext).onRequestPermissionsResult(requestCode, permissions, grantResults);
            }

            if (mFragment != null) {
                mFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }

            boolean isAllGranted = true;
            List<PermissionInfo> needRationalPermissionList = new ArrayList<PermissionInfo>();
            List<PermissionInfo> deniedPermissionList = new ArrayList<PermissionInfo>();
            for (int i = 0; i < permissions.length; i++) {
                if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                    if (mPermissionListNeedReq.get(i).isRationalNeed()) {
                        needRationalPermissionList.add(mPermissionListNeedReq.get(i));
                    } else {
                        deniedPermissionList.add(mPermissionListNeedReq.get(i));
                    }
                    isAllGranted = false;
                }
            }

            if (needRationalPermissionList.size() != 0) {
                showRational(needRationalPermissionList);
            }

            if (deniedPermissionList.size() != 0) {
                onDenied(deniedPermissionList);
            }

            if (isAllGranted) {
                onGranted();
            }

        }
    }

    /**
     * 权限被用户许可之后回调的方法
     */
    private void onGranted() {
        if (mPermissionResultCallBack != null) {
            mPermissionResultCallBack.onPermissionGranted();
        }
    }

    /**
     * 权限申请被用户否定之后的回调方法,这个主要是当用户点击否定的同一时候点击了不在弹出,
     * 那么当再次申请权限,此方法会被调用
     * @param list
     */
    private void onDenied(List<PermissionInfo> list) {
        if(list == null || list.size() == 0) return;

        String[] permissions = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            permissions[i] = list.get(i).getName();
        }

        if (mPermissionResultCallBack != null) {
            mPermissionResultCallBack.onPermissionDenied(permissions);
        }
    }

    /**
     * 权限申请被用户否定后的回调方法,这个主要场景是当用户点击了否定,但未点击不在弹出,
     * 那么当再次申请权限的时候,此方法会被调用
     * @param list
     */
    private void showRational(List<PermissionInfo> list) {
        if(list == null || list.size() == 0) return;

        String[] permissions = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            permissions[i] = list.get(i).getName();
        }

        if (mPermissionResultCallBack != null) {
            mPermissionResultCallBack.onRationalShow(permissions);
        }
    }

}

在PermissionResutCallBack中,要做的是:

1.返回相应的结果

public interface PermissionResultCallBack {

    /**
     * 当全部权限的申请被用户允许之后,该方法会被调用
     */
    void onPermissionGranted();

    /**
     * 当权限申请中的某一个或多个权限,被用户以前否定了,并确认了不再提醒时,也就是权限的申请窗体不能再弹出时,
     * 该方法将会被调用
     * @param permissions
     */
    void onPermissionDenied(String... permissions);

    /**
     * 当权限申请中的某一个或多个权限,被用户否定了,但没有确认不再提醒时,也就是权限窗体申请时,但被否定了之后,
     * 该方法将会被调用.
     * @param permissions
     */
    void onRationalShow(String... permissions);
}

在HelpActivity中。要做的就是:

1.申请权限

2.通过onRequestPermissionUtil返回结果给PermissionUtil

当然这个activity必须是透明的,并且是没有不论什么的view的。这样看起来才不像是开了一个新的activity。

public class HelpActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            handleIntent(getIntent());
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        handleIntent(intent);
    }

    // 权限申请
    @TargetApi(Build.VERSION_CODES.M)
    private void handleIntent(Intent intent) {
        String[] permissions = intent.getStringArrayExtra("permissions");
        int requestCode = intent.getIntExtra("requestCode", 42);
        ActivityCompat.requestPermissions(this, permissions, requestCode);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    // 返回结果
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        PermissionUtil.getInstance().onRequestPermissionResult(requestCode, permissions, grantResults);
        finish();
    }
}

项目源代码下载以及介绍。请看github。

时间: 2024-12-26 21:30:25

android6.0权限管理工具EasyPermissionUtil的相关文章

Android拍照,相册选择图片以及Android6.0权限管理

概述 在android开发过程中,拍照或者从相册中选择图片是很常见的功能.下面要说得这个案例比较简单,用户点击按钮选择拍照或者打开相册选择图片,然后将选中的图片显示在手机上.android6.0后,推出了动态权限管理.以往我们将涉及到的权限全部写在清单文件中,只要用户安装了该程序,程序在运行过程中都会获得相应权限.android6.0后,对于一些特别敏感的权限,开发者必须在程序中进行声明.拍照和从相册选择图片都是涉及到用户隐私的敏感权限,必须在程序中进行声明. 大概的流程 创建布局文件,这里不多

Android6.0权限管理以及使用权限该注意的地方

Android 6.0 Marshmallow首次增加了执行时权限管理,这对用户来说,能够更好的了解.控 制 app 涉及到的权限.然而对开发人员来说却是一件比較蛋疼的事情.须要兼容适配,并保证程序功能的正常执行. 什么叫执行时权限管理呢?在Android 6.0以下的系统中,当我们在安装应用的时候,该应用就会提示我们这个应用所须要的权限,假设你要安装.那就必须允许赋予全部权限,可是假设不允许,那就仅仅能取消安装了,有点流氓.并且安装完后,你不能够收回这个权限. 而6.0就做到了执行时权限管理.

Android6.0权限申请工具类

Android6.0以上,有部分权限是需要申请的.共9组,只要一个权限申请成功默认这一组的权限也申请成功,看下图: 权限申请工具类如下: 1 package com.example.android_lianshou_as.utils; 2 3 import android.Manifest; 4 import android.app.Activity; 5 import android.content.DialogInterface; 6 import android.content.Inten

Android6.0权限管理

Android 6.0 Marshmallow首次加入了运行时权限管理,这对用户来说,可以更好的了解.控 制 app 涉及到的权限.然而对开发者来说却是一件比较蛋疼的事情,需要兼容适配,并保证程序功能的正常运行. 什么叫运行时权限管理呢?在Android 6.0以下的系统中,当我们在安装应用的时候,该应用就会提示我们这个应用所需要的权限,如果你要安装,那就必须同意赋予所有权限,但是如果不同意,那就只能取消安装了,有点流氓.而且安装完后,你不可以收回这个权限. 而6.0就做到了运行时权限管理,即使

Android开发——Android 6.0权限管理机制详解

0.前言 最近在研究所实习,我负责维护Android手机取证项目的Android客户端,有客户反映我们的APP在Android6.0无响应,经过调试发现SD卡读写权限权限被拒绝.但明明是在AndroidManifest.xml文件中声明过的.查了很多资料才知道Android6.0的很多权限申请机制发生了改变,可以说是Android6.0在安全机制上更进了一步吧,因此写下这篇文章以记录. 注:在运行程序时,对于某些权限向用户询问申请(后面会详细地讲)时因为我们知道客户在我们APP中不会点"拒绝&q

Android6.0M权限管理实战,完美轻量级封装

转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53189359 本文出自[DylanAndroid的博客] Android6.0M权限管理实战,完美轻量级封装 随着Android版本的不断更新,Android再权限管理方面的诟病越来越明显.Google的Android开发人员也意识到了Android应用在权限管理方面的各种问题,让好多用户摸不着头脑就使用了用户的隐私数据. 为了在权限这方面加强管理,给用户一个比较好的体验.A

Android_设备隐私获取,忽略6.0权限管理

1.前言 (1).由于MIUI等部分国产定制系统也有权限管理,没有相关api,故无法判断用户是否允许获取联系人等隐私.在Android 6.0之后,新增权限管理可以通过官方api判断用户的运行状态: (2).我们指定targetSdkVersion为23或者之后我们还需要在运行时请求这些所需的权限.这很重要,因为已经出现了很多开发者把targetSdkVersion飙到了最新,然后发现自己的app疯狂的崩溃,这是由于他们没有实现执行运行时权限请求的代码.当你已经把一个targeting API

Android6.0权限系统

Android6.0权限系统 Android权限系统是一个非常重要的安全问题,因为它只有在安装时会询问一次.一旦软件本安装之后,应用程序可以在用户毫不知情的情况下使用这些权限来获取所有的内容. 很多坏蛋会通过这个安全缺陷来收集用户的个人信息并使用它们来做坏事的情况就不足为奇了. Android团队也意识到了这个问题.在经过了7年后,权限系统终于被重新设置了.从Anroid 6.0(API Level 23)开始,应用程序在安装时不会被授予任何权限,取而代之的是在运行时应用回去请求用户授予对应的权

Android 6.0 权限管理

Android 6.0 权限管理 Android permission 运行时权限(Runtime permission) 旧版兼容 6.0权限弹框的两种模式 6.0之后的权限分类 Normal permissions(普通权限) Dangerous permissions(危险权限) 运行时权限请求的基本步骤 权限请求策略 运行时权限(Runtime permission) android的权限系统一直是首要的安全概念,因为这些权限只在安装的时候被询问一次.一旦安装了,app可以在用户毫不知晓