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

权限的保护级别

  • 自定义权限分为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 中定义权限:  
<permission android:name="com.yyter.systempermission.DangerousActivityPermissionTest"  
        android:label="@string/dangerous_activity_permission_label"  
        android:description="@string/dangerous_activity_permission_desc"  
        android:protectionLevel="dangerous"/>  
        
app B 中也作相似的定义: 
<permission android:name="com.yyter.systempermission.DangerousActivityPermissionTest"/>
  • 这样定义以后,不管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如下版本由于安装次序不一样致使可能获取不到权限的问题的方法,其实不太好,由于其实不肯定这个权限是由谁定义的,不知道还有没有好的办法?

一个使用自定义权限的例子

  • 利用权限,咱们能够限定广播的接收者
例如
<permission android:name="${your_package_name} + xxxxx"  
	android:protectionLevel="signature"/>

这样定义权限以后,能够经过sendBroadcast(Intent intent,String receiverPermission)来过滤广播接收者,使得只有本身app自己以及使用相同签名的app才能够收到广播,经常使用于push SDK.java

备注

  • 能够经过下面的方式查看是否得到某个权限:
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();
		}
	}
}
相关文章
相关标签/搜索