1. 程式人生 > >Pro Android學習筆記 六六 安全和許可權 3 Provider許可權

Pro Android學習筆記 六六 安全和許可權 3 Provider許可權

訪問其他應用的content provider

我們在ProPermission中提供了一個content provider,成為PrivProvider,然後在ProPermissionClient中對呼叫這個provider介面。在ProPermission的AndroidManifest.xml中,對provider宣告如下:

<provider android:name=".PrivProvider"     android:authorities="cn.wei.flowingflying.propermission.PrivProvider"     android:exported="true"

/>

android:exported屬性非常重要。這個屬性用於指示該服務是否能夠被其他應用程式元件呼叫或跟它互動。如果設定為true,則能夠被呼叫或互動,否則不能。設定為false時,只有同一個應用程式的元件或帶有相同使用者ID的應用程式才能啟動或繫結該服務。如果content provider允許其他應用呼叫,即允許其他程序呼叫,需要將該屬性設定為true。如果,我們設定該屬性,會報下面的錯誤:

Provider的讀寫許可權

Provider可以提供讀許可權,寫許可權,或者許可權,例如:

<permission android:name="wei.permission.READ_CONTENTPROVIDER"     android:label="Allow read content provider"     android:protectionLevel="normal" />      …… <provider android:name=".PrivProvider"     android:authorities="cn.wei.flowingflying.propermission.PrivProvider"     android:readPermission="wei.permission.READ_CONTENTPROVIDER"

    android:exported="true" > </provider>

設定寫許可權屬性為android:writePermission,讀寫許可權為android:permission。我們仍使用ProPermissionClient來訪問provider介面,則出現許可權錯誤:

我們在ProPermissionClient的AndroidManifest.xml中加上許可權宣告即可:

<uses-permission android:name="wei.permission.READ_CONTENTPROVIDER" />

Provider的URI許可權

前面,我們定義的整個provider的許可權,但實際使用中,provider可以只開放部分URI的許可權,例如本例,我們可以只開發content://cn.wei.flowingflying.propermission.PrivProvider/hello路徑下許可權,不允許訪問其他路徑,如下宣告:

<provider android:name=".PrivProvider"     android:authorities="cn.wei.flowingflying.propermission.PrivProvider"     android:readPermission="wei.permission.READ_CONTENTPROVIDER"     android:exported="true" >     <path-permission android:pathPrefix="/hello" android:readPermission="READ_HELLO_CONTENTPROVIDER" /></provider>

我們可以針對其中某個或某部分URI,單獨進行許可權設定。除了android:pathPrefix,還可以有android:path和android:pathPatten,例如android:pathPattern="/hello/.*"(注意,萬用字元*之前有個‘.’)。

在ProPermissionClient如果要讀取content:content://cn.wei.flowingflying.propermission.PrivProvider/hello/1則需要宣告整個provider的許可權wei.permission.READ_CONTENTPROVIDER或者該路徑的許可權READ_HELLO_CONTENTPROVIDER。

Provider的granting

全域性granting

ProPermissionClient具有讀取content provider的許可權,它去呼叫另一個應用C的activity,例子中這個另一個應用C為ProPermissionGrant,但是這個例子沒有讀取content provider的許可權,ProPermissionClient可以將自己的許可權通過intent傳遞給應用C,讓其也具有訪問content provider的許可權。

對於應用A,相關的content provider為:

<provider android:name=".PrivProvider"      android:authorities="cn.wei.flowingflying.propermission.PrivProvider"      android:readPermission="wei.permission.READ_CONTENTPROVIDER"      android:grantUriPermissions="true"      android:exported="true" />

對於應用B,其具有wei.permission.READ_CONTENTPROVIDER的許可權,而應用C不具備,應用B通過intent呼叫應用C的程式碼如下:

Intent intent = new Intent(this,ReadProvider.class); intent.setClassName("com.example.propermissiongrant", "com.example.propermissiongrant.MainActivity");intent.setData(Uri.parse("content://cn.wei.flowingflying.propermission.PrivProvider/world/1"));intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);  //傳遞許可權 startActivity(intent);

所呼叫的C的activity具備訪問content provider的許可權。

如果我們將provider的屬性android:grantUriPermissions設定為false,則不允許通過接受傳遞的許可權方式進行訪問,即B所呼叫的C的activity不能讀content provider,報錯如下:

部分URI的granting

有時候,我們只希望部分的URI允許grant許可權訪問,而不是開放整個provider,如下:

<provider android:name=".PrivProvider"      android:authorities="cn.wei.flowingflying.propermission.PrivProvider"      android:readPermission="wei.permission.READ_CONTENTPROVIDER"      android:exported="true" >       <grant-uri-permission android:pathPrefix="/hello" /></provider>

我們將之允許字首為hello的部分URI訪問。一旦我們設定了grant-uri-permission,則全域性的android:grantUriPermissions屬性將無效,無論設定true還是flase,也都是隻允許grant-uri-permission是宣告的部分uri可以被grant許可權訪問。