2019独角兽企业重金招聘Python工程师标准>>>
权限的保护级别
- 自定义权限分为4个级别
normal
,最常用的级别,只要在AndroidManifest.xml
中申请,系统会自动授权dangerous
,系统对这个级别的权限处理方式跟系统的Api版本和app的targetSDKVersion
的值有关,当系统的Api版本低于23或者targetSDKVersion
低于23,那么会自动授予权限,否则在Android6.0以后,每次使用dangerous
权限时,都需要检查signature
,当申请权限的app和定义权限的app使用的是相同的签名时,系统自动授权,否则权限申请失败.通常在同一个公司有多个app,且一个app需要调用另一个的某个组件(例如ContentProvider),且不希望被外部app调用时,可以定义这种类型的权限.signatureOrSystem
,和signature
类似,只是系统应用也能获得授权(很少用)
可能会遇到的问题
- 假设
app B
申请app A
定义的权限P
,但是用户先安装的B
,后安装的A
,那么B
是无法获得权限P
的,因此使用的时候会crash.解决方案是B
也定义一个同样名字的权限即可(只需要定义权限的名字,label,description,protectionLevel等都不需要定义)- dangerous权限在6.0以上不需要这样预定义,因为权限都是动态授予的,但是在6.0以下的版本中dangerous和normal的处理是一样的,都是安装的时候授权,因此如果
app B
没有定义权限P
,那么在Android 6.0以下的系统中,仍然不能获得权限P
,所以解决方法和上面一样,也是在app B
中定义权限P
- dangerous权限在6.0以上不需要这样预定义,因为权限都是动态授予的,但是在6.0以下的版本中dangerous和normal的处理是一样的,都是安装的时候授权,因此如果
例如
app A 中定义权限:
app B 中也做类似的定义:
- 这样定义之后,无论
app B
和app A
谁先安装,app B
都能获得"com.yyter.systempermission.DangerousActivityPermissionTest"权限,并且能够启动app A
中的DangerousActivityPermissionTest Activity. - 但是在Android 6.0上,两者的安装顺序不同,表现也是不同的
- 如果先安装
app A
,那么当app B
申请权限时,将会弹出授权框,因为它在申请app A
定义的权限 - 如果先安装
app B
,那么当app B
申请权限时,将直接获得授权,不会弹框,因为它申请的是自己定义的权限,也就是说这种情况下,app A
中的DangerousActivityPermissionTest Activity实际上是由app B
所定义的权限P
来保护的.所以如果再安装一个app C
,那么在安装界面看到的实际上是app B
中的权限P
的描述,以及app B
的logo
- 如果先安装
- 这种使多个app都定义相同的权限来解决Android 6.0以下版本因为安装次序不同导致可能获取不到权限的问题的方法,其实不太好,因为其实不确定这个权限是由谁定义的,不知道还有没有好的办法?
一个使用自定义权限的例子
- 利用权限,我们可以限定广播的接收者
例如
这样定义权限之后,可以通过sendBroadcast(Intent intent,String receiverPermission)
来过滤广播接收者,使得只有自己app本身以及使用相同签名的app才可以收到广播,常用于push SDK.
备注
- 可以通过下面的方式查看是否获得某个权限:
String permissionName = "XXX";//要检测的权限名称
/**
* 此处使用的是ContextCompat,当然也可以使用PackageManager或者Context中的对应方法
*/
int res = ContextCompat.checkSelfPermission(context, permissionName);
if(res == PackageManager.PERMISSION_GRANTED) {
//获得了权限
} else if(res == PackageManager.PERMISSION_DENIED) {
//未获得权限
}
- 申请权限
if(ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
callPhone();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, xxx);
}
- 处理回调
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == xxx) {
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
xxxxx;
} else {
Toast.makeText(this, "oops!", Toast.LENGTH_LONG).show();
}
}
}