Android6.0 运行时权限

Android6.0的改变:
http://developer.android.com/intl/zh-cn/about/versions/marshmallow/android-6.0-changes.html

Android6.0 API改变:
http://developer.android.com/intl/zh-cn/about/versions/marshmallow/android-6.0.html

讲述了6.0的变化,api的改变,方法的改变,兼容说明等。

然而对开发人员而言,最主要的就是要兼容 Android 6.0 运行时权限 :Runtime Permissions。因为你会发现当你的targetSdkVersion=23的时候程序会莫名的闪退。
比如:启动摄像头,获取联系人信息,电话短信相关,日历相关,程序都会闪退。

运行时权限:就是当你的操作是有关用户隐私的时候,就会弹出一个授权Dialog,告诉用户APP要使用该权限,然后用户授权选择允许或者拒绝。

Android中哪些是正常权限,哪些是要用户授权的权限呢?

Normal and Dangerous Permissions

Normal Permission: 用户自动授权,直接在清单文件里写就Ok

As of API level 23, the following permissions are classified as PROTECTION_NORMAL:

Dangerous Permissions:需要用户授权的权限
然而Dangerous permissions 被android 系统分成了权限组。

Dangerous permissions and permission groups 表格.

Permission GroupPermissions
CALENDAR
CAMERA
CONTACTS
LOCATION
MICROPHONE
PHONE
SENSORS
SMS
STORAGE

备注:

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

Also starting in API level 19, this permission is not required to read/write files in your application-specific directories returned by getExternalFilesDir(String) and getExternalCacheDir().

从android-19开始,getExternalFilesDir(String) and getExternalCacheDir()不再需要权限。

getExternalFilesDir(String): /Android/data/包名/files/xxx
getExternalCacheDir(): /Android/data/包名/cache

重点聊完常规权限和需要用户授权的权限,接下来看看如何声明权限,请求权限,处理请求结果等操作。

1,声明权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.snazzyapp">

    <uses-permission android:name="android.permission.SEND_SMS"/>
    <uses-permission-sdk-23 android:name="android.permission.READ_CONTACTS" />

    <application ...>
        ...
    </application>

</manifest>

2,检测权限和请求用户授权

Check For Permissions

2种情况:1,Android6.0新的api。2,v4兼容api。

新的API:
        activity.checkSelfPermission(permission)

v4兼容API:
        ActivityCompat.checkSelfPermission(context, permission)
        ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS)

ActivityCompat 和ContextCompat 是继承关系
public class ActivityCompat extends ContextCompat {}

Request Permissions 请求用户授权

新的API:
activity.requestPermissions (String[] permissions, int requestCode)
fragment.requestPermissions (String[] permissions, int requestCode)

v4兼容API:
ActivityCompat.requestPermissions(activity, permissions, requestCode);

并不是每次操作都要请求用户授权,so

Request the permissions you need 请求授权之前做逻辑判断

// checkSelfPermission  权限是否已经被允许
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) { // 没有授权

    //之前被拒绝,弹窗说明,你用这个权限干嘛。
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.
//请求用户授权
ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}else{//权限已经被允许

}

Handle the permissions request response :处理请求授权

//requestCode:用户请求授权的时候传递的参数
//permissions:权限列表
@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
    }
}

完整实例代码:xml界面就一个简单的button

package com.heaven.android6;
public class MainActivity extends Activity  implements OnClickListener{
     private Button  btn_rpermission;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         btn_rpermission=(Button)findViewById(R.id.btn_rpermission);
         btn_rpermission.setOnClickListener(this);
    }


     @Override
     public void onClick(View v) {
        switch (v.getId()) {
         case R.id.btn_rpermission:
             // 如果运行6.0,但是没有做权限处理,直接调用对应的api,程序直接闪退。


             // 权限逻辑处理。  如果清单文件没有配置权限,而去请求的话,程序直接闪退(没有配置一个权限的情况下)
            try {
//               checkSelfPermission  权限是否已经被允许
                 if (ContextCompat.checkSelfPermission(this,
                                 Manifest.permission.READ_CONTACTS)
                         != PackageManager.PERMISSION_GRANTED) {
                     // 没有被允许
System.out.println("没有被允许");
                     // Should we show an explanation?
                     if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                             Manifest.permission.READ_CONTACTS)) {
                         // 被拒绝,弹窗说明
                         // Show an expanation to the user *asynchronously* -- don't block
                         // this thread waiting for the user's response! After the user
                         // sees the explanation, try again to request the permission.
                         System.out.println("被拒绝,弹窗说明  11111111111111111");
                         Toast.makeText(this, "被拒绝,弹窗提示,让用户自己设置", 0).show();
                     } else { // 清单文件已经配置了权限,第一次请求权限
                         System.out.println("请求权限2222222222222222");
                         // No explanation needed, we can request the permission.
                         Toast.makeText(this, "请求权限", 0).show();
                         // 2种方式  1,6.0api。2,v4兼容api
                         /*requestPermissions(
                                 new String[]{Manifest.permission.READ_CONTACTS},
                                 2);*/

                         ActivityCompat.requestPermissions(this,
                                 new String[]{Manifest.permission.READ_CONTACTS},
                                 2);
                         // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                         // app-defined int constant. The callback method gets the
                         // result of the request.
                     }
                 }else{//权限已经被允许
                     System.out.println("权限已经被允许33333333");
                     Toast.makeText(this, "权限已经被允许", 0).show();
                     return;
                 }
            } catch (Exception e) {
                e.printStackTrace();
            }
            break;
        }
    }

     @Override
     public void onRequestPermissionsResult(int requestCode,
             String permissions[], int[] grantResults) {
         System.out.println("99999999999999999");
         if(grantResults.length > 0){
             int length = grantResults.length;
             for (int i = 0; i < grantResults.length; i++) {
                 System.out.println("grantResults = "+ grantResults[i]);
            }
         }
         switch (requestCode) {
             case 2: {
                 // If request is cancelled, the result arrays are empty.
                 if (grantResults.length > 0
                     && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                     System.out.println("准许获取联系人信息");
                     // permission was granted, yay! Do the
                     // contacts-related task you need to do.
                     Toast.makeText(this, "准许获取联系人信息", 0).show();
                 } else {
                     System.out.println("被拒绝");
                     Toast.makeText(this, "被拒绝,弹窗提示,让用户自己设置", 0).show();
                     // permission denied, boo! Disable the
                     // functionality that depends on this permission.
                 }
                 return;
             }
             // other 'case' lines to check for other
             // permissions this app might request
         }
     }
}

更新sdk,下载samples,运行时权限demo位置:
D:\android-sdk-windows\samples\android-23\system

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值