Android 自定义权限的使用以及遇到的问题

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

权限的保护级别

  • 自定义权限分为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
例如  
app A 中定义权限:  
  
        
app B 中也做类似的定义: 
  
  • 这样定义之后,无论app Bapp 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();
		}
	}
}

转载于:https://my.oschina.net/fengheju/blog/649158

你可能感兴趣的:(Android 自定义权限的使用以及遇到的问题)