Android M 开始,App不会在安装的时候授予权限,而是在运行时一个一个的询问用户授予权限。html
1. 运行时权限仅当咱们设置targetSdkVersion >= 23才起做用,固然还要是M系统的手机。app在6.0以前的设备依然使用旧的权限系统。java
2. 若是app的targetSdkVersion < 23,或者手机版本 < 6.0 ,那将被认为app没有用23新权限测试过,那将被继续使用旧有规则:用户在安装的时候不得不接受全部权限,安装后app就有了那些权限咯!android
注意,此时用户依然能够取消已经赞成的受权!用户取消受权时,android 6.0系统会警告,但这不妨碍用户取消受权。app
当咱们在targetSdkVersion 低于23的App调用一个须要权限的函数时,这个权限若是被用户取消受权了的话,不抛出异常。可是他将啥都不干,结果致使函数返回值是null或者0。ide
2、官网流程翻译函数
官网:https://developer.android.com/training/permissions/index.html测试
在AndroidManifest.xml中声明this
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.snazzyapp"> <uses-permission android:name="android.permission.SEND_SMS"/> <application ...> ... </application> </manifest>
权限分正常和危险两种,正常的权限和之前同样,只须要在Manifest.xml中声明便可,在App安装时,自动分配权限,且用户也不能够在设置中取消权限;危险权限须要运行时申请。spa
权限组,将危险权限分组,同一个组里的任何一个权限被受权了,其余权限也自动被受权。翻译
下面是权限表格
Permission Group | Permissions |
---|---|
CALENDAR |
|
CAMERA |
|
CONTACTS |
|
LOCATION |
|
MICROPHONE |
|
PHONE |
|
SENSORS |
|
SMS |
|
STORAGE |
(1) 检测是否已经受权
/** * Determine whether <em>you</em> have been granted a particular permission. * * @param permission The name of the permission being checked. * * @return {@link PackageManager#PERMISSION_GRANTED} if you have the * permission, or {@link PackageManager#PERMISSION_DENIED} if not. * * @see PackageManager#checkPermission(String, String) * @see #checkCallingPermission(String) */ checkSelfPermission(String)
(2) 请求权限
shouldShowRequestPermissionRationale()
判断是否须要为权限申请向用户友好提示
返回true,上次申请权限,用户选择拒绝。
返回false
第一次申请,或上次申请权限,用户选择拒绝,并选择了“不在提醒”的选项;
设备的策略禁止当前应用获取这个权限的受权。
注意:第二次请求权限时,才会有“不在提醒”的选项,若是用户一直拒绝,并无选择“不在提醒”的选项,下次请求权限时,会继续有“不在提醒”的选项。
显示权限说明:是根据你的应用中使用的权限分类来的:
1.用户容易知道应用须要获取的权限:如一个拍照应用,须要摄像头的权限,是很正常,不用提示。
2.一些用户感受困惑的一些权限:如:分享图片,还须要获取位置的权限,这个须要提示用户:为何须要这个权限。
若是用户拒绝某受权。下一次弹框,用户会有一个“再也不提醒”的选项的来防止app之后继续请求受权。
若是这个选项在拒绝受权前被用户勾选了。下次为这个权限请求requestPermissions时,对话框就不弹出来了,结果就是,app啥都不干。
这将是不好的用户体验,用户作了操做却得不到响应。这种状况须要好好处理一下。
final private int REQUEST_CODE_ASK_PERMISSIONS = 123; private void insertDummyContactWrapper() { int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS); if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) { if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) { showMessageOKCancel("You need to allow access to Contacts", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_ASK_PERMISSIONS); } }); return; } requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_ASK_PERMISSIONS); return; } insertDummyContact(); }
(3) 处理请求返回结果
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // if request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! // Do the contacts-related task you need to do. } else { // permission denied, boo! // Disable the functionality that depends on this permission. } return; } // other 'case' lines to check for other // permissions this app might request } }
3. Permissions Best Practices 权限申请最佳实践
1. 若是不须要对数据有特别的控制权的话,能够采起用Intent呼起系统应用的方式来避免申请权限,好比Camera、contacts、phone call,都是能够直接调用系统app的。
注意打电话操做虽然是用的Intent方式,若是是这样的写法context.startActivity(new Intent("android.intent.action.CALL", Uri.parse(formatter.format(tel)))); 也要申请权限;若是是用的 android.intent.action.DIAL来调起的话,就不须要。
2. 只申请须要的权限,且只在须要的时候申请。