談談ContentProvider?
2.Android框架中的一些類需要ContentProvider類型數據。如想讓數據可以使用在SyncAdapter,Loader,CursorAdapter等類上,那麼就需要為數據做一層ContentProvider封裝。
3.ContentProvider為應用間的數據交互提供了一個安全的環境。它准許你把自己的應用數據根據需求開放給其它應用進行增、刪、改、查,而不用擔心直接開放資料庫許可權而帶來的安全問題。ContentProvider提供的方法有:query:查詢ninsert:插入nupdate:更新ndelete:刪除ngetType:得到數據類型nonCreate:創建數據時調用的回調函數n
但如何上層對ContentProvider進行增、刪、改、查操作呢?答案是使用ContentResolver。
二、使用ContentResolver操作ContentProvider中的數據為什麼要用ContentResolver來操作Provider,而不是直接使用訪問Provider呢?考慮到一個手機中很多應用含有Provider,如聯繫人,圖庫等。每個Provider具體實現都不一樣,如果開發時要了解每個ContentProvider,這可是非常不可取的方式啊。因此Android提供了ContentResolver來統一管理與不同ContentProvider間的操作。可以使用context.getContentResolver()來獲得ContentProvider。但是ContentResolver又是如何操作ContentProvider的呢?URI:統一資源標識。每一個ContentProvider都擁有一個公共的URI,這個URI用於表示這個ContentProvider所提供的數據。URI的格式為:content:// 是標準前綴nAuthority:表示授權信息,是URI的標識,用於唯一標識這個ContentProvider,外部調用者可以根據這個標識來找到它。nPath:路徑名,即資料庫中的表名,用以區分ContentProvider中不同的數據表;nId:Id號,用以區別表中的不同數據;n
UriMatcher類使用
因為Uri代表了要操作的數據,所以我們經常需要解析Uri並從Uri中獲取數據。Android系統提供了兩個用於操作Uri的工具類,分別是UriMatcher和ContentUris。使用UriMatcher時,首先註冊需要匹配的Uri路徑;然後,mMatcher.match(uri)方法對輸入的Uri進行匹配,如果匹配就返回匹配碼,匹配碼是addURI()方法中傳入的第三個參數。代碼如下:UriMatcher mMatcher = new UriMatcher(UriMatcher.NO_MATCH);n//如果match()方法匹配content://com.example.procvide.personprovider/person路徑,返回匹配碼為1nmMatcher.addURI("com.example.procvide.personprovider", "person", 1);//添加需要匹配uri,如果匹配就會返回匹配碼n//如果match()方法匹配content://com.bing.provider.personprovider/person/100路徑,返回匹配碼為2nmMatcher.addURI("com.example.provider.personprovider", "person/#", 2);//#號為通配符nswitch (mMatcher.match(Uri.parse("content://com.example.provider.personprovider/person/10"))) { n case 1n break;n case 2n break;n default://不匹配n break;n}n
第一步,繼承ContentProvider並重寫insert,query,...等重要方法:
第二步,在AndroidManifest.xml使用<provider>對該ContentProvider進行配置,為了能讓其他應用找到該ContentProvider,ContentProvider需要採用了authorities(主機名/域名)對它進行唯一標識:<manifest .... > n <application android:icon="@drawable/icon" android:label="@string/app_name"> n <provider android:name=".PersonContentProvider" n android:authorities="com.example.providers.personprovider" /> n </application> n</manifest> n
然後,將數據添加到ContentProvider中。
第三步,在其它應用中通過ContentResolver使用定義的Uri訪問並操作這些被暴露的數據。2.ContentProvider如何控制數據訪問許可權?一種方法是向此應用設置一個android:sharedUserId,然後需要訪問此數據的應用也設置同一個sharedUserId,具有相同的sharedUserId的應用間可以共享數據。但是這種方法不夠安全,也無法做到對不同數據進行不同讀寫許可權的管理。另一種方法是使用ContentProvider中的數據共享規則。這裡涉及到幾個重要的標籤:android:exported 設置此provider是否可以被其他應用使用。nandroid:readPermission 該provider的讀許可權的標識nandroid:writePermission 該provider的寫許可權標識nandroid:permission provider讀寫許可權標識nandroid:grantUriPermissions 臨時許可權標識,true時,意味著該provider下所有數據均可被臨時使用;false時,則反之,但可以通過設置<grant-uri-permission>標籤來指定哪些路徑可以被臨時使用。如在啟動第三方應用時,傳入FLAG_GRANT_READ_URI_PERMISSION或FLAG_GRANT_WRITE_URI_PERMISSION來讓第三方應用臨時具有讀寫該數據的許可權。n
<permission android:name="com.example.providers.personprovider.READ" android:protectionLevel="normal"/>n<providern android:authorities="com.example.providers.personprovider"n android:name=".PersonContentProvider"n android:readPermission="com.example.providers.personprovider.READ"n android:exported="true">n</provider>n
然後在其他應用中可以使用以下許可權來對PersonContentProvider進行訪問。
<uses-permission android:name="com.example.providers.personprovider.READ"/>n
如果希望對provider里不同的表面設置不同的許可權,需要使用provider提供的子標籤<path-permission>,可以對不同path設置不同的許可權規則
path-permission包括了以下幾個標籤。<path-permission android:path=""n android:pathPrefix=""n android:pathPattern=""n android:permission=""n android:readPermission=""n android:writePermission="" />n
public class PersonContentProvider extends ContentProvider {n public Uri insert(Uri uri, ContentValues values) {n db.insert("person", "personid", values);n getContext().getContentResolver().notifyChange(uri, null);n }n}n
如果ContentProvider的訪問者需要得到數據變化通知,必須使用ContentObserver對數據(數據採用uri描述)進行監聽,當監聽到數據變化通知時,系統就會調用ContentObserver的onChange()方法:
getContentResolver().registerContentObserver(Uri.parse("content://com.example.providers.personprovider/person"),n true, new PersonObserver(new Handler()));npublic class PersonObserver extends ContentObserver{n public PersonObserver(Handler handler) {n super(handler);n }n public void onChange(boolean selfChange) {n //TODOn }n}n
推薦閱讀:
※[譯] 如何創建高度模塊化的 Android 應用
※Android 的 APK 中怎麼放置反編譯「炸彈」?
※Android學習筆記——AS中使用AIDL
※Android 開發助手 1.2.0 版
TAG:Android |