Android 6.0 M
1.1 权限动态申请
在Android 6.0中谷歌摒弃了之前的install time permissions model取而代之的是runtime permissions model。先来说说install time permissions model,这个大家不陌生,就是当Android App安装的时候会向用户展示一坨权限,如果此时用户选择安装,则表示用户同意将这些权限赋予App,如果用户不同意那么这个App就会取消安装。runtime permissions model就牛逼了,在App安装的时候同样会向用户展示所需要的权限,并且在用户选择安装App的时候并不表示用户将这些权限赋予了App,而是需要App在运行阶段主动去申请这些权限。这样做的好处显而易见,App对权限的申请对于用户来说变得更加透明,而且用户对App权限的控制也更加灵活。
Android将系统权限分成了四个保护等级normal,dangerous,signature,signatureOrSystem,其中最常见的是normal permission和dangerous permission两类。
- Normal Permissions(普通权限):不涉及用户隐私,不需要用户进行授权,比如访问网络等;
- Dangerous Permission(危险权限):涉及到用户隐私,需要用户进行授权,比如相机访问、读取SD卡等。
Runtime Permissions针对的是dangerous permissions,normal permissions 还是会在App安装期间被默认赋予。举例子:
加入你在6.0中声明此权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
不做任何处理时,应用程序在运行时会出现一个惊喜那就是(Permission Denied)
那么接下来看一下怎么在代码中进行权限的申请:
public static final int EXTERNAL_STORAGE_REQ_CODE = 15 ;
public void getRuntimePermission(){
//判断当前Activity是否已经获得了该权限
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
//如果App的权限申请曾经被用户拒绝过,就需要在这里跟用户做出解释
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(this,"please give me the permission",Toast.LENGTH_SHORT).show();
} else {
//进行权限请求
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
EXTERNAL_STORAGE_REQ_CODE);
}
}
}
当进行权限申请,并且用户做出选择后会回调onRequestPermissionsResult这个方法,在这个方法中做相关处理:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case EXTERNAL_STORAGE_REQ_CODE: {
// 如果请求被拒绝,那么通常grantResults数组为空
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//申请成功
} else {
//申请失败
}
return;
}
}
}
1.2 Fragment 请求权限
//如果使用ActivityCompat.requestPermissions,不会调用onRequestPermissionsResult()
//请求权限
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
//判断是否需要 向用户解释,为什么要申请该权限
shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)
1.3 WRITE_SETTINGS特殊权限申请
Android 6.0中,除了危险权限不再在安装后授予,还有两个特殊权限:
设置悬浮窗: SYSTEM_ALERT_WINDOW
修改系统设置:WRITE_SETTINGS
修改系统设置权限的授权 WRITE_SETTINGS,与其他权限不同
而是使用startActivityForResult,启动系统设置的授权界面来申请
/**
* 申请权限
*/
private void requestWriteSettings()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
//大于等于23 请求权限
if ( !Settings.System.canWrite(getApplicationContext()))
{
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS );
}
}else{
//小于23直接设置
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_WRITE_SETTINGS)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
//Settings.System.canWrite方法检测授权结果
if (Settings.System.canWrite(getApplicationContext()))
{
T.show("获取了权限");
}else{
T.show("您拒绝了权限");
}
}
}
}