关于Android动态权限的一些疑问
Android 6.0开始,对敏感权限需要动态申请,首先我们需要引入android.support.v4的兼容包,然后使用ActivityCompat这个类来处理权限。
比如最常用的
ActivityCompat.checkSelfPermission(...)ActivityCompat.requestPermissions(...)ActivityCompat.shouldShowRequestPermissionRationale(...)
第一个是检查某个权限是否授权
第二个是申请权限
第三个是判断是否需要合理显示授权对话框。具体含义参考文末。
Activity也有这些方法,为什么要使用ActivityCompat来检查权限和申请权限?
有两个原因
第一,如果应用的minSdkVersion小于23,那么IDE会提示你这些方法在6.0以下不存在,编译会不通过。
第二,ActivityCompat处理了一些兼容性判断,比如requestPermissions的实现里加了判断api 23。
Android 23以下如何检查权限呢?
一种方法是使用ActivityCompat或ContextCompat,调用checkSelfPermission方法。
另一种方法使用Activity提供的方法:checkPermission(String permission, int pid, int uid),需要传入当前进程id和uid。
checkSelfPermission方法其实也是调用checkPermission(String permission, int pid, int uid)。
动态权限示例代码:
package com.devnn.testdemo;import android.Manifest;import android.app.Activity;import android.content.pm.PackageManager;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.widget.Toast;public class MainActivity extends Activity { String permission = Manifest.permission.READ_EXTERNAL_STORAGE; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{permission}, 100); }else{ Toast.makeText(this, "已有读SDK卡权限", Toast.LENGTH_SHORT).show(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode==100){ if(grantResults[0]==PackageManager.PERMISSION_GRANTED){ Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show(); }else if(ActivityCompat.shouldShowRequestPermissionRationale(this,permission)==false){ Toast.makeText(this, "拒绝并勾选了不再提醒,不会弹了,需要引导用户去设置页", Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(this, "拒绝了授权,下次还会再弹", Toast.LENGTH_SHORT).show(); } } }}
记得先要在AndroidManifest.xml里声明权限。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
在弹出系统的权限对话框前,弹出自已的对话框,用来说明权限用途,会更加友好一点。直接使用Materia风格的Dialog。
public void showPermissionDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth); builder.setMessage("需要读SD卡权限,用来获取照片\n需要获取手机状态权限,用来获取设备号\n需要获取联系人权限,用来..."); builder.setTitle("权限说明"); builder.setCancelable(true); builder.setPositiveButton("申请", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, 100); } }); builder.show(); }
对话框效果:
只有危险权限(或叫敏感权限)才需要申请,而且危险权限组中的某一个权限授权了,组内其它权限也被同时授权。
危险权限组:
关于 ActivityCompat.shouldShowRequestPermissionRationale(...)
方法的含义,有必要说明。从字面意思理解,即是否需要合理显示申请权限对话框,那么什么时候显示才是合理的呢?我们发现以下规律。
在第一次申请权限时,它返回了false
用户选择拒绝并没有勾选不再提醒时,它返回true
而用户选择拒绝并勾选不再提醒(永久拒绝),它返回了false
因此这个方法并不能用来判断是否需要显示自已的权限说明对话框。它只能在权限回调里用来判断是否要引导用户到设置页打开权限。
更多相关文章
- Android非UI线程访问UI线程的方法总结
- android 9.0 SD卡权限问题 文件管理器没有权限
- 查看基于Android 系统单个进程内存、CPU使用情况的几种方法
- 对话框式activity
- android 调试方法
- 整理android环境离线安装搭建方法——支持android 2.3.3和androi
- Android电话拨号器实现方法