Android动态请求权限的工具类

Android 6.0(SDK 23)以上才需要用到动态权限。

之前已经写过好多次关于Android动态权限的文章,但是后期发现每次都要进行复制粘贴,还要修改,

还不如写一个自己的工具类,那就方便多了!

网上也有很多关于动态权限的工具类,还有一些框架,
但是我发现有些使用还是挺麻烦,我感觉还是自己这个动态权限的工具类是非常好的。

一.我的动态权限工具类PermissionsUtils使用方法:

1.定义权限数组

 //比如:两个日历权限和一个数据读写权限 String[] permissions = new String[]{Manifest.permission.WRITE_CALENDAR, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_EXTERNAL_STORAGE};

一个或者多个权限都是可以的。

2.创建监听权限的接口对象

  //创建监听权限的接口对象    PermissionsUtils.IPermissionsResult permissionsResult = new PermissionsUtils.IPermissionsResult() {        @Override        public void passPermissons() {            Toast.makeText(MainActivity.this, "权限通过,可以做其他事情!", Toast.LENGTH_SHORT).show();        }        @Override        public void forbitPermissons() {//            finish();            Toast.makeText(MainActivity.this, "权限不通过!", Toast.LENGTH_SHORT).show();        }    };

这里权限禁止,也可以自己写得详细一些,比如还有什么权限没有通过,但是我感觉没有必要。

3.在Activity重写onRequestPermissionsResult方法

在重写的方法中需要调用工具类的onRequestPermissionsResult方法,这个方法需要传入Activity对象

   @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        //就多一个参数this        PermissionsUtils.getInstance().onRequestPermissionsResult(this, requestCode, permissions, grantResults);    }

4.调用checkPermissions方法

这个方法一般在onCreate使用,或者在执行某个事件前使用,在回调方法中觉得是否执行后续的动作!

 //这里的this不是上下文,是Activity对象! PermissionsUtils.getInstance().chekPermissions(this, permissions, permissionsResult);

5.属性showSystemSetting

showSystemSetting是一个静态属性,可以设置true和false,表示是否可以跳转到系统设置权限的窗口。

这个属性的作用是如果用户在勾选不再提示权限的情况下,可以帮助用户跳转到系统权限的窗口去设置这个属性。
防止这个权限可能一直没有得到允许的情况。

这个属性默认是true,在权限没有通过的情况,提示用户是否跳转到系统设置权限的窗口。

二.PermissionsUtils工具类的代码

package com.huawei.calendar.myapplication;import android.app.Activity;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.PackageManager;import android.net.Uri;import android.os.Build;import android.provider.Settings;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AlertDialog;import java.util.ArrayList;import java.util.List;/** * 权限工具类 */public class PermissionsUtils {    private final int mRequestCode = 100;//权限请求码    public static boolean showSystemSetting = true;    private PermissionsUtils() {    }    private static PermissionsUtils permissionsUtils;    private IPermissionsResult mPermissionsResult;    public static PermissionsUtils getInstance() {        if (permissionsUtils == null) {            permissionsUtils = new PermissionsUtils();        }        return permissionsUtils;    }    public void chekPermissions(Activity context, String[] permissions, @NonNull IPermissionsResult permissionsResult) {        mPermissionsResult = permissionsResult;        if (Build.VERSION.SDK_INT < 23) {//6.0才用动态权限            permissionsResult.passPermissons();            return;        }        //创建一个mPermissionList,逐个判断哪些权限未授予,未授予的权限存储到mPerrrmissionList中        List mPermissionList = new ArrayList<>();        //逐个判断你要的权限是否已经通过        for (int i = 0; i < permissions.length; i++) {            if (ContextCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {                mPermissionList.add(permissions[i]);//添加还未授予的权限            }        }        //申请权限        if (mPermissionList.size() > 0) {//有权限没有通过,需要申请            ActivityCompat.requestPermissions(context, permissions, mRequestCode);        } else {            //说明权限都已经通过,可以做你想做的事情去            permissionsResult.passPermissons();            return;        }    }    //请求权限后回调的方法    //参数: requestCode  是我们自己定义的权限请求码    //参数: permissions  是我们请求的权限名称数组    //参数: grantResults 是我们在弹出页面后是否允许权限的标识数组,数组的长度对应的是权限名称数组的长度,数组的数据0表示允许权限,-1表示我们点击了禁止权限    public void onRequestPermissionsResult(Activity context, int requestCode, @NonNull String[] permissions,                                           @NonNull int[] grantResults) {        boolean hasPermissionDismiss = false;//有权限没有通过        if (mRequestCode == requestCode) {            for (int i = 0; i < grantResults.length; i++) {                if (grantResults[i] == -1) {                    hasPermissionDismiss = true;                }            }            //如果有权限没有被允许            if (hasPermissionDismiss) {                if (showSystemSetting) {                    showSystemPermissionsSettingDialog(context);//跳转到系统设置权限页面,或者直接关闭页面,不让他继续访问                } else {                    mPermissionsResult.forbitPermissons();                }            } else {                //全部权限通过,可以进行下一步操作。。。                mPermissionsResult.passPermissons();            }        }    }    /**     * 不再提示权限时的展示对话框     */    AlertDialog mPermissionDialog;    private void showSystemPermissionsSettingDialog(final Activity context) {        final String mPackName = context.getPackageName();        if (mPermissionDialog == null) {            mPermissionDialog = new AlertDialog.Builder(context)                    .setMessage("已禁用权限,请手动授予")                    .setPositiveButton("设置", new DialogInterface.OnClickListener() {                        @Override                        public void onClick(DialogInterface dialog, int which) {                            cancelPermissionDialog();                            Uri packageURI = Uri.parse("package:" + mPackName);                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);                            context.startActivity(intent);                            context.finish();                        }                    })                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {                        @Override                        public void onClick(DialogInterface dialog, int which) {                            //关闭页面或者做其他操作                            cancelPermissionDialog();                            //mContext.finish();                            mPermissionsResult.forbitPermissons();                        }                    })                    .create();        }        mPermissionDialog.show();    }    //关闭对话框    private void cancelPermissionDialog() {        if (mPermissionDialog != null) {            mPermissionDialog.cancel();            mPermissionDialog = null;        }    }    public interface IPermissionsResult {        void passPermissons();        void forbitPermissons();    }}

三.调用工具类的示例代码

package com.huawei.calendar.myapplication;import android.Manifest;import android.support.annotation.NonNull;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.Toast;import java.security.Permission;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //两个日历权限和一个数据读写权限        String[] permissions = new String[]{Manifest.permission.WRITE_CALENDAR, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_EXTERNAL_STORAGE};//        PermissionsUtils.showSystemSetting = false;//是否支持显示系统设置权限设置窗口跳转        //这里的this不是上下文,是Activity对象!        PermissionsUtils.getInstance().chekPermissions(this, permissions, permissionsResult);    }    //创建监听权限的接口对象    PermissionsUtils.IPermissionsResult permissionsResult = new PermissionsUtils.IPermissionsResult() {        @Override        public void passPermissons() {            Toast.makeText(MainActivity.this, "权限通过,可以做其他事情!", Toast.LENGTH_SHORT).show();        }        @Override        public void forbitPermissons() {//            finish();            Toast.makeText(MainActivity.this, "权限不通过!", Toast.LENGTH_SHORT).show();        }    };    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        //就多一个参数this        PermissionsUtils.getInstance().onRequestPermissionsResult(this, requestCode, permissions, grantResults);    }}

记得在AndroidManifest中添加权限

    <uses-permission android:name="android.permission.READ_CALENDAR" />    <uses-permission android:name="android.permission.WRITE_CALENDAR" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

使用效果图

1.申请权限的时候

Android动态请求权限的工具类(可请求多个,并且功能完善)_第1张图片

2.有权限没有通过的情况

Android动态请求权限的工具类(可请求多个,并且功能完善)_第2张图片

3.点击跳转到系统权限设置页面的时候

Android动态请求权限的工具类(可请求多个,并且功能完善)_第3张图片
showSystemSetting属性为true的情况才会提示这个对话框!
我看了其他人动态权限的写法,都没有跳转到设置系统权限的对话框的,但是我感觉这个在需要的时候还是比较管用的。

四.其他的

这个工具类还是比较完善的了,如果需要修改一些字符串或者逻辑可以自己修改,工具类的逻辑应该也是比较清晰的。

android6.0后,仅在manifest.xml清单中配置相关权限时,如果将targetSdkVersion设置为23及以上,部分敏感权限需要动态申请后才能使用;
如果不想处理6.0以上的适配,请将targetSdkVersion设置为22或以下;但是低版本的SDK可能没有高版本的一些属性或者类。

但是注意一点,无论版本高低,需要的权限一定要写在AndroidManifest中,如果在动态权限中申请的权限在Manife中没有写,你会发现他不会询问你这个权限。
所有你不可能获取到这个权限。

如果你在AndroidManifest中写了多个需要动态申请的权限,在动态权限申请的时候可以只申请一个或者一部分。没有问题的。
如果你跳转到这个程序的系统设置权限界面,你会发现AndroidManifest中所有申明的权限都显示在这里,可以对任何一个权限进行禁止或者允许。

1.敏感权限也是危险权限Dangerous-Permisson,能够获取到用户的隐私;

共9类/组

权限组 名称
CALENDAR 日历
CAMERA 相机
CONTACTS 联系人
LOCATION 定位
MICROPHONE 麦克相关,比如录音
PHONE 手机状态
SENSORS 传感器
SMS 短信
STORAGE 存储权限

2.详细敏感权限

1 group:android.permission-group.CONTACTS    permission:android.permission.WRITE_CONTACTS    permission:android.permission.GET_ACCOUNTS        permission:android.permission.READ_CONTACTS2  group:android.permission-group.PHONE    permission:android.permission.READ_CALL_LOG    permission:android.permission.READ_PHONE_STATE     permission:android.permission.CALL_PHONE    permission:android.permission.WRITE_CALL_LOG    permission:android.permission.USE_SIP    permission:android.permission.PROCESS_OUTGOING_CALLS    permission:com.android.voicemail.permission.ADD_VOICEMAIL3  group:android.permission-group.CALENDAR    permission:android.permission.READ_CALENDAR    permission:android.permission.WRITE_CALENDAR4  group:android.permission-group.CAMERA    permission:android.permission.CAMERA5  group:android.permission-group.SENSORS    permission:android.permission.BODY_SENSORS6  group:android.permission-group.LOCATION    permission:android.permission.ACCESS_FINE_LOCATION    permission:android.permission.ACCESS_COARSE_LOCATION7  group:android.permission-group.STORAGE    permission:android.permission.READ_EXTERNAL_STORAGE    permission:android.permission.WRITE_EXTERNAL_STORAGE8  group:android.permission-group.MICROPHONE    permission:android.permission.RECORD_AUDIO9  group:android.permission-group.SMS    permission:android.permission.READ_SMS    permission:android.permission.RECEIVE_WAP_PUSH    permission:android.permission.RECEIVE_MMS    permission:android.permission.RECEIVE_SMS    permission:android.permission.SEND_SMS    permission:android.permission.READ_CELL_BROADCASTS 

如果需要不妨收藏记下。

共勉:生命太短没有时间留给遗憾,若不是终点,请努力一直前行。

更多相关文章

  1. Android adb bugreport工具分析和使用
  2. Systrace 分析性能工具使用方法详解
  3. 下一代Android渠道打包工具
  4. Android 9.0 关于ACTION_CALL无权限导致闪退的问题
  5. Android操作系统安全(分层结构、应用沙盒、安全进程通信、Android
  6. Android原理揭秘系列之动态墙纸
  7. 【Android】动态注册广播接收器
  8. Android 6.0 运行时权限的处理

随机推荐

  1. 关于onConfigurationChanged
  2. 2012.06.28(2)——— android onMeasure
  3. android五种布局模式
  4. android thread handler timertask
  5. Android的TextView的双击事件监听
  6. Android一次刷机
  7. Android(安卓)编译系统分析
  8. Android(安卓)webkit 事件传递流程
  9. Android如何平移一个View
  10. android:launchMode="singleTask" 与 onN