Content Provider
1、Content Provider
Content Providers屬於Android應用程序的組件之一,作爲應用程序之間唯一的共享數據的途徑,Content Provider主要的功能就是存儲並檢索數據以及向其他應用程序提供訪問數據的接口。
Android系統爲一些常見的數據類型(如音樂、視頻、圖像、手機通信錄聯繫人信息等)內置了一系列的Content Provider,這些都位於android.provider包下。持有特定的許可,可以在自己開發的應用程序中訪問這些Content Provider。
讓自己的數據和其他應用程序共享有兩種方式:創建自己的Content Provider(即繼承ContentProvider的子類)或者是講自己的數據添加到已有的Content
Provider中去,後者需要保證現有的Content Provider和自己的數據類型相同且具有該Content Provider的寫入權限。對於Content Provider,最重要的就是數據模型和URI。
F 數據模型
Content Provider將其存儲的數據以數據表的形式提供給訪問者,在數據表中
每一行爲一條記錄,每一列爲具有特定類型和意義的數據。每一條數據記錄都包括一個”_ID”數值字段,該字段唯一標識一條數據。
F URI
URI,每一個Content Provider都對外提供一個能夠唯一標識自己數據集的公
開URI,如果一個Content Provider管理多個數據集,其將會爲每個數據集分配一個獨立的URI。所有的Content Provider的URI都以”content://”開頭,其中”content:”是用來標識數據是由Content Provider管理的schema。
首先來介紹如何訪問Content Provider中的數據,訪問Content Provider中的
數據主要通過ContentResolver對象,ContentResolver類提供了訪問了成員方法可以用來對Content Provider中的數據進行查詢、插入、修改和刪除等操作,以查詢爲例,查詢一個Content Provider需要掌握如下的信息:
² 唯一標識Content Provider的URI
² 需要訪問的數據字段名稱
² 該數據字段的數據類型
查詢Content Provider的方法有兩個:ContentResolver的query()和Actuvuty
對象的managedQuery(),二者接收的參數均相同,返回的都是Cursor對象,唯一不同的是使用managedQuery方法可以讓Activty來管理Cursor的生命週期。
被管理的Cursor會在Activity進入暫停狀態的時候調用自己的deactivate方
法自行卸載,而在Activity回到運行狀態時會調用自己的requery方法重新查詢生成的Cursor對象。如果一個未被管理的Cursor對象被Activity管理,可以調用Activity的startManagingCursor方法來實現。
Android有一個獨特之處就是,數據庫只能被它的創建者所使用,其他的應用是不能訪問到的,所以如果你想實現不同應用之間的數據共享,就不得不用Content provider了。它提供了一套標準的接口來獲取以及操作數據。並且,android自身也提供了幾個現成的content provider:Contacts,Broswer,CallLog,Settings,MediaStore。
應用可以通過一個唯一的ContentResolver interface來使用具體的某個content provider.
2、Content Provider介紹
F 基本概念
Content Provider爲存儲和讀取數據提供了統一的接口。
使用Content Provider,應用程序可以實現數據共享。
Android內置的許多數據都是使用Content Provider形式,供開發者調用的(如視頻,音頻,圖片,通訊錄等)。
F Uri
每一個Content Provider都擁有一個公共的Uri,這個Uri用於表示這個Content Provider提供的數據
Android所提供的Content Provider都存放在android.provider這個包裏面
F 提供的函數
query()查詢
insert()插入
update()更新
delete()刪除
getType()得到數據類型
onCreate()創建時的回調函數
F 實現過程
定義一個CONTENT_URI常量
定義一個類,繼承Content Provider
實現query(),delete(),update(),insert(),onCreate(),getType()方法
在AndroidManifest.xml中聲明
F 數據查詢
URI有兩種形式:一種現實某些數據類型的所有的值(比如,所有的個人聯
系信息),還有一種顯示某種數據類型的一個特定的記錄。
content://contacts/people/是第一種形式的URI,它會返回設備上所有的聯繫人的名字
content://contacts/people/23是第二種形式的URI,只返回ID=23的那行
content://media/images 返回設備上所有圖片的列表
雖然說有一種一般的形式,但是查詢URI還是有點隨意和讓人迷惑。因
此,Android在android.provider包中提供了一系列的輔助類,它們定義了這些查詢字符串,所以不必知道不同數據類型真正的URI值。這些輔助類定義了一個叫CONTENT_URI的字符串。比如android.provider.contacts.People.CONTENT_URI定義了用於在android自帶的people content provider中查找聯繫人的查詢字符串。
3、創建一個Content Provider
下面是如何創建自己的Content Provider,將它作爲公共資源用於讀取和寫入一個數據類型的步驟:
@ 繼承Content Provider
@ 定義一個public static Uri,取名叫做CONTENT_URI。這個字符串代表了你的Content Provider要處理的”content://”。你必須爲這個值定義一個唯一的字符串;最好的解決方法是使用類名,像這樣:
publicstatic final Uri CONTENT_URI=Uri.parse(“content://com.google.tprovide”;)
@ 創建你存儲數據的系統。大多數的Content Provider使用Android的文件存儲方法或者SQLite數據庫來存儲數據,但是你可以用你想要的任何方法來存儲數據,只要你遵循調用和返回值的慣例。如果你使用SQLite,Android提供了DatabaseContentProvider和SQLiteOpenHelper類來幫助你。
@ 定義你返回給客戶端的列的名字。如果你使用一個後臺的數據庫,這些列的名字通常和SQL數據庫裏的列的名字一樣。在任何情況下,你都應該包含一個整數的叫_id的列。用來定義一個特定的記錄號。如果使用SQLite數據庫。它應該是這種類型:INTEFER PRIMARY KEYAUTOINCREMENT。AUTOINCREMENT描述符是可選的,但是默認情況下,SQLite自動遞增ID域到下一個大於表中現已存在的最大的ID的值。如果你刪除了最後一行,那麼新加入的下一行會和被刪除的那行具有相同的ID。W爲了避免這種情況下,讓SQLite的遞增到下一個最大值不論刪除與否,那麼給你的ID列賦予接下來的那個類型。Android提供了SQLiteOpenHelper方法來幫助你創建和管理你的數數據庫的版本。
@ 如果你要處理字節數據,比如點陣圖文件,存儲這個數據的域實際上應該是一個包含那個文件的content://URI的字符串。用戶會用這個域來檢索數據。對於這種類型的數據,Content Provider(可以是同一個Content Provider也可以是另外一個Content Provider——比如,如果你存儲一張照片你會使用media content provider)應該爲那個記錄實現一個叫_data的域。這個_data域列出了文件的在設備上的確切路徑。這個域並不是讓客戶端來讀取的,是給ContentResolver的。客戶端會調用ContentResolver.openOutputStream()方法,用URI作爲參數(比如,名叫photo的列可能會有一個值:content://media/images/4453)。ContentResolver會請求記錄的_data域,而且因爲它有比客戶端更高的權限,它能直接訪問那個文件並且返回給客戶端一個那個文件的讀取包。
@ 聲明客戶端可以用來指定哪些列可以返回的public static的字符串。或者從遊標(Cursor)來指定域名。文本域,像音頻,點陣圖域,一般返回路徑字符串值。
@ 對於一個查詢,返回一個結果集合的Cursor對象。這意味着要實現查詢,更新,插入和刪除方法。
@ 加入一個<provider>標籤到AndroidManifest.xml
@ 如果你處理的是一種新的數據類型,你必須定義一個新的MIME。
在應用成功程序的AndroidManifest.xml文件中聲明Content Provider組件,否則該Content Provider對於Android系統將是不可見的。如果有一個名爲MyProvider的類擴展了Content Provider類,聲明該組件的代碼如下:
其中name屬性爲Content Provider子類的全稱類名,authorities屬性唯一標識了一個Content Provider。還可以通過setReadPermission()和serWritePermission()來設置其操作權限。當然也可以在上面的xml中加入android:readPermission或者android:writePermisson屬性來控制其權限。