美文网首页
Android 6.0 RuntimePermission

Android 6.0 RuntimePermission

作者: l_genius | 来源:发表于2017-02-14 15:41 被阅读0次

android6.0棉花糖,app将不会在安装的时候授予权限。取而代之的是,app不得不在运行时一个一个询问用户授予权限。

android {
    compileSdkVersion 23
    ...
  
    defaultConfig {
        ...
        targetSdkVersion 23
        ...
    }
}

如何app/build.gradle是23的话,在6.0上运行一些权限,没有做处理,会直接崩溃:

...
Caused by: java.lang.SecurityException: Permission Denial: 
opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord
{c3b3c66 16712:com.wuxiaolong.apksample/u0a62} (pid=16712, uid=10062)
requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS
...

如果targetSdkVersion 22,就不会发生这样的错误,下面就来实践下这个6.0运行的权限。
效果预览
按照惯例,先上效果图:


说明:第一次请求授权,是没有“不再询问”,拒绝后,再次请求授权,就会出现“不再询问”。

实践

AndroidManifest.xml
<uses-permission android:name="android.permission.READ_CONTACTS" />
代码调用

在需要使用到权限之前调用以下代码:

private void mayRequestContacts() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            switch (checkSelfPermission(Manifest.permission.READ_CONTACTS)) {
                case PackageManager.PERMISSION_GRANTED:
                    // 已有授权
                    Log.i("wxl", "已有授权");
                    break;
                case PackageManager.PERMISSION_DENIED:
                    // 没有权限:尚未请求过权限,
                    // 或者请求授权被拒绝,
                    // 或者曾经授权过,但被用户在设置中禁用权限
                    Log.i("wxl", "没有权限:尚未请求过权限,或者请求授权被拒绝," +
                            "或者曾经授权过, 但被用户在设置中禁用权限");
                    /**
                     * 如果用户勾上了“不再询问”,这时候就不应弹请求权限的对话框,
                     * 可以在请求权限之前用
                     * shouldShowRequestPermissionRationale判断用户是否拒绝过,
                     * 如果返回true,表示用户拒绝过。
                     */
                    Log.i("wxl", "shouldShowRequestPermissionRationale==" 
                    + shouldShowRequestPermissionRationale(READ_CONTACTS));
                    if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
                        Snackbar.make(mEmailView, 
                        R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
                                .setAction(android.R.string.ok, new View.OnClickListener() {
                                    @Override
                                    @TargetApi(Build.VERSION_CODES.M)
                                    public void onClick(View v) {
                                        requestPermissions(new String[]{READ_CONTACTS}, 
                                        REQUEST_READ_CONTACTS);
                                    }
                                }).show();
                    } else {
                        requestPermissions(new String[]{READ_CONTACTS}, 
                        REQUEST_READ_CONTACTS);
                    }
                    break;
                default:
                    break;
            }
        }
    }

checkSelfPermission:检查权限
requestPermissions:请求权限
shouldShowRequestPermissionRationale:判断用户是否拒绝过

授权回调

不管是允许或拒绝,都会回调:

@Override
   public void onRequestPermissionsResult(int requestCode,
    @NonNull  String[] permissions,@NonNull  int[] grantResults) {
       if (requestCode == REQUEST_READ_CONTACTS) {
           if (grantResults.length == 1 &&
                   grantResults[0] == PackageManager.PERMISSION_GRANTED) {
               // 授权请求被通过,读取通讯录
               Log.i("wxl", "授权请求被通过,读取通讯录");
           } else {
               Log.i("wxl", "授权请求不被通过");
           }
       }
   }
多个权限
@TargetApi(Build.VERSION_CODES.M)
   private void checkPermissions() {
       List<String> permissionsNeeded = new ArrayList<>();
       final List<String> permissionsList = new ArrayList<>();
       if (deniedPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
           permissionsNeeded.add("GPS");
       if (deniedPermission(permissionsList, Manifest.permission.READ_CONTACTS))
           permissionsNeeded.add("Read Contacts");
       if (permissionsList.size() > 0) {
           if (permissionsNeeded.size() > 0) {
               // Need Rationale
               String message = "You need to grant access to " + permissionsNeeded.get(0);
               for (int i = 1; i < permissionsNeeded.size(); i++)
                   message = message + ", " + permissionsNeeded.get(i);
               requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_PERMISSIONS);
           }
       }
   }
   @TargetApi(Build.VERSION_CODES.M)
   private boolean deniedPermission(List<String> permissionsList, String permission) {
       if (checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED) {
           permissionsList.add(permission);
           // true,表示用户拒绝过
           if (shouldShowRequestPermissionRationale(permission)) {
               return true;
           }
       }
       return false;
   }
   /**
    * Callback received when a permissions request has been completed.
    */
   @Override
   public void onRequestPermissionsResult(int requestCode,
                                          String[] permissions, int[] grantResults) {       
       if (requestCode == REQUEST_PERMISSIONS) {
           Map<String, Integer> perms = new HashMap<String, Integer>();
           // Initial
           perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
           perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
           // Fill with results
           for (int i = 0; i < permissions.length; i++)
               perms.put(permissions[i], grantResults[i]);
           // Check for ACCESS_FINE_LOCATION
           if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                   && perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
               // All Permissions Granted
               Log.i("wxl", "授权请求被通过");
           } else {
               // Permission Denied
               Log.i("wxl", "授权请求不被通过");
           }
       }
   }

权限分组
权限那么多,如果一个个判断,岂不是会疯掉,如图:

同一组的任何一个权限被授权了,其他权限也自动被授权。例如,一旦WRITE_CONTACTS被授权了,app也有READ_CONTACTS和GET_ACCOUNTS了。

附录

Android M 新的运行时权限开发者需要知道的一切
Android Runtime Permission测试

相关文章

网友评论

      本文标题:Android 6.0 RuntimePermission

      本文链接:https://www.haomeiwen.com/subject/rcgxwttx.html