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();
		}
	}
}
相關文章
相關標籤/搜索