Android(安卓)6.0运行时权限处理与封装(一)
Android 6.0运行时权限处理与封装
众所周知,在Android 6.0之后,Android对一些用户的敏感权限进行了进一步加强,需要用户去动态授予权限。
前言
在API23之前,只要在AndroidManifest.xml中注册过的权限,程序运行时都会自动获取到。但是到了23及更高,危险的权限就需要我们自己来动态的申请了,而此时用户也就有了拒绝我们需要的权限的权力,这当然会导致我们程序的运行不正常,甚至是造成程序的崩溃。所以我们就需要尽可能的提示用户同意我们的权限申请。
说明
系统权限分为几个保护级别。需要了解的两个最重要保护级别是正常权限和危险权限。 首先,你必须得知道哪些是需要动态申请的权限,也就是我前面所提到的危险权限,并且危险权限也分组,所以到底哪些是危险权限呢?
这里我们涉及到9大组危险权限,但是可喜可贺的是我们只需要申请每组中的一个权限,就能获取到全组权限的授权。
1、关于日历的权限: <uses-permission android:name="android.permission.READ_CALENDAR"/> <uses-permission android:name="android.permission.WRITE_CALENDAR"/> 2、关于相机的权限: <uses-permission android:name="android.permission.CAMERA"/> 3、关于联系人的权限: <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <uses-permission android:name="android.permission.GET_CONTACTS"/> 4、关于位置的权限: <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 5、关于电话的权限: <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.READ_CALL_LOG"/> <uses-permission android:name="android.permission.WRITE_CALL_LOG"/> <uses-permission android:name="android.permission.USE_SIP"/> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/> 6、关于传感器的权限: <uses-permission android:name="android.permission.BODY_SENSORS"/> 7、关于短信的权限: <uses-permission android:name="android.permission.SEND_SMS"/> <uses-permission android:name="android.permission.RECEIVE_SMS"/> <uses-permission android:name="android.permission.READ_SMS"/> <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/> <uses-permission android:name="android.permission.RECEIVE_MMS"/> <uses-permission android:name="android.permission.READ_CELL_BROADCASTS"/> 8、关于SD卡的权限 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 9、关于录音的权限 <uses-permission android:name="android.permission.RECORD_AUDIO"/>
案例
这里我们通过一个打电话的案例进行说明
我们在6.0之前写打电话功能
第一步:在清单文件中申明打电话权限:
<uses-permission android:name="android.permission.CALL_PHONE"/>
第二步:
Intent intent = new Intent(Intent.ACTION_CALL); Uri data = Uri.parse("tel:" + mPhoneNumber); intent.setData(data); startActivity(intent);
之前这两步就可以实现一个打电话的功能,但是现在不行了,现在回程序运行会崩溃,因为你没有动态申请用户打电话权限。
我们在6.0之后写打电话功能
现在我们需要去检测该权限有没有背用户授予过,如果没有则需要申请打电话权限,如果有授予过可以直接拨打电话。
ContextCompat.checkSelfPermission:检测权限
ActivityCompat.requestPermissions:申请权限
第一步:检测用户用没有授权打电话,如果没有就需要申请权限
findViewById(R.id.btn_call).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission .CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { // 没有该权限 申请打电话权限 // Context , // 第二个参数是用户需要申请的权限字符串数组, // 第三个参数是请求码 主要用来处理用户选择的返回结果 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE); } else { callPhone(); } } });
是的,就是这么简单。不过,如果你就这样子用在了你的项目里,会有坑!!!
如果你本身就是Android用户,细心的你一定会发现,App在向你申请权限的时候,你会有几个选项:
1.允许
2.拒绝
3.还可以拒绝并不再提示!(坑就出现在这里了)
如果按上面的代码,你会永远得到一个答案:用户拒绝!!(如果用户是不小心点错,或者出于好奇心尝试,那很容易就懵逼了)
所以我们还需要对第一步做个调整
findViewById(R.id.btn_call).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission .CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { // 没有该权限 申请打电话权限 // Context , // 第二个参数是用户需要申请的权限字符串数组, // 第三个参数是请求码 主要用来处理用户选择的返回结果 // 1、此时还没有权限! if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CALL_PHONE)) { // 2、用户还没选择或选择了但没选择拒绝并不再提示 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE); } else { // 3、用户点选了不再提示 //(正经的告诉用户这个功能必须给权限啊,求权限啊!最好告诉他怎么去设置!) showTipsDialog(MainActivity.this); } } else { // 有权限了,去做该做的事情吧! callPhone(); } } });
优化部分:还可以拒绝并不再提示!,我们添加了一个可以让用户设置的跳转
/** * 显示提示对话框(这个提示款适用于点击按钮请求权限的问题) * 如果需要强制获取权限,需要自定义对话框 */ public static void showTipsDialog(final Context context) { new AlertDialog.Builder(context) .setTitle("提示信息") .setMessage("当前应用缺少必要权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。") .setNegativeButton("取消", null) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startAppSettings(context); } }).show(); } /** * 启动当前应用设置页面 */ private static void startAppSettings(Context context) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + context.getPackageName())); context.startActivity(intent); }
第二步: 处理回调 如果用户同意或是拒绝那么会回调onRequestPermissionsResult()
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(requestCode == CALL_PHONE_REQUEST_CODE){ if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission Granted 通过 打电话 callPhone(); } else { // Permission Denied 被拒绝 Toast.makeText(this,"权限被拒绝了",Toast.LENGTH_SHORT).show(); } } super.onRequestPermissionsResult(requestCode, permissions, grantResults); }
至此,这个功能算是可用了!!!但是,还不完美!!!必须稍微封装一下让自己用起来更方便嘛!那么接下来就带大家来一个更加完美的封装。
源码下载
更多相关文章
- Android的Activity一打开就出现讨嫌的软键盘,怎样将其关闭?
- Google Android(安卓)P之后,Android(安卓)工程师将何去何从?
- Android包管理机制
- Android应用程序设计策略
- Android(安卓)API Guides---System Permissions
- 为Android开发者整理的Google I/O开发者大会第一弹
- android:apk版本的的比对、下载、安装
- Android开发指南-用户界面-对话框
- Android(安卓)浏览器打开本地APK