之前因为一直做TV开发,目前国内TV盒子系统基本都在4.4以下,所以一直很少接触新系统的特性。最近又回归到手机开发,所以也补补课,写点东西就当给自己补课了。
Android6.0相较于之前的版本最直观的变化应该就是关于权限的管理了。6.0以前权限申请写到AndroidManifest.xml中就万事大吉,但是6.0之后对于一些高危权限,比如读取通讯录,读写sdcard分区等,不仅需要写到清单文件中,而且需要在使用之前向用户主动提出申请,否则即使在清单文件中申请了相应权限,但是依旧会报错。
首先,我们来看一下都有哪些权限需要运行时进行申请:
//联系人
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
//手机信息
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
//日历
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
//相机
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
//传感器
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
//定位
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
//外部存储(即sdcard分区 )
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
//麦克风
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
//短信
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
对于同一个权限组的权限,只要申请了其中一个,你也是可以使用其他权限的,实际上Android系统对于申请权限时的描述也是针对于整个权限组的。
当然首先在申请权限之前,我们可以先判断一下我们是否获取到了用户的授权,这里就以读写sdcard分区为例,判断代码如下:
int code = ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_EXTERNAL_STORAGE);
if (code== PackageManager.PERMISSION_GRANTED){
//表示通过授权
}
如果没有通过授权,那么我们就要来进行权限申请,申请代码如下:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
1);
这里的三个参数分别是Context对象,权限组(这个权限组的意思是多个权限),权限申请码(这个和startActivity中的requestCode同理)。调用这个方法之后,我们需要在Activity中的覆写onRequestPermissionsResult
方法。范例如下:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode==1){
if (grantResults[0]==PackageManager.PERMISSION_GRANTED){
//读写sdcard权限通过
}else if (grantResults[0]!=PackageManager.PERMISSION_GRANTED){
//读写sdcard权限没有通过
}
}
}
但是如果用户已经拒绝过我们的权限申请怎么办呢?这个时候我们需要使用到另外一个api:shouldShowRequestPermissionRationale
这个API的作用是告诉我们是否应该给用户展示一个关于对权限使用的提示说明,这样我们可以在用户永久拒绝了权限申请的时候,通过这个引导用户来重新开启权限。
所以完整的流程应该是下面这样的:
int code = ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_EXTERNAL_STORAGE);
if (code== PackageManager.PERMISSION_GRANTED){
//表示通过授权
}else{
if(ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_EXTERNAL_STORAGE)){
//展示提示说明
Toast.makeText(this,"我们需要这项权限才能为您提供更好的服务",Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}else{
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode==1){
if (grantResults[0]==PackageManager.PERMISSION_GRANTED){
//读写sdcard权限通过
}else if (grantResults[0]!=PackageManager.PERMISSION_GRANTED){
//读写sdcard权限没有通过
}
}
}