1. 程式人生 > >Pro Android學習筆記(一)——ContentProvider(上)

Pro Android學習筆記(一)——ContentProvider(上)

ContentProvider,Android四大元件之一。他是系統提供的一種抽象的資料服務。Android Developer對她的概述為:


  大概意思就是說ContentProvider(內容提供者)就是為應用程式提供資料。他壓縮資料並通過ContentResolver介面提供給應用程式。當我們需要在多個應用程式之間共享資料的時候,我們才考慮使用ContentProvider,否則我們可以直接使用SQLiteDataBase。當一個URI形式的請求通過ContentResolver並且通過註冊的Authority請求ContentProvider的時候,ContentProvider可以把URI解釋成它想要的(這一段話我也不太會翻譯,有不對的地方還望斧正)。

 我們看看這裡面涉及到了哪些概念:

(1)ContentProvider,內容提供者。

(2)ContentResolver,用於資料操作的抽象類。

(3)URI,代表了要操作的資料,類似於HTTP URI。

(4)UriMatcher,Uri匹配器,對傳遞過來的URI進行分析匹配。

以後,還會涉及到

(5)ContentValue,儲存鍵值對用於ContentResolver處理。

(6)Cursor,游標,可以想象成文字編輯器中的游標。

 官方的概述還是很難理解,我們慢慢來看。

(一)檢視Android內建ContentProvider

  使用adb可以檢視裝置內部的ContentProvider。將手機(此處手機應為root之後)連線電腦或者開啟模擬器,命令列開啟adb。

使用adb devices可以檢視所連線裝置


在這裡我使用的是Genymotion的模擬器,號稱最快的模擬器。

然後鍵入adb shell就可以進入android裝置的shell。


在這裡我們就能進行一些linux命令的操作,但是,但是,對linux的命令支援並不全面,很多都沒有。可以使用“ls /system/bin”命令檢視可以執行哪些命令。


太多就不截了。

OK,通過命令"ls -l /data/data/"我們能夠檢視/data/data/目錄下的檔案,這裡面就儲存了應用程式的資料檔案,包括資料庫。

來看下聯絡人示例,聯絡人儲存在"/data/data/com.android.providers.cantacts/"下,通過命令“ls /data/data/com.android.providers.contacts/”檢視該檔案下的資料


可以看到其中都儲存了些什麼,我們只關心database,所以執行“ls /data/data/com.android.providers.contacts/databases”


裡面以資料庫的格式儲存了我們的聯絡人。

我們可以使用sqlite3對資料庫進行操作,執行“sqlite3  /data/data/com.android.proviers.contacts/databases/contacts.db”


注意此處,由shell環境進入到了sqlite的操作環境。

執行".help"可以檢視可執行命令了,在此不多說了。我們通過命令列檢視資料庫總是不方便,我們可以匯出檔案到本地電腦,然後通過圖形化工具檢視。首先,回退到windows的cmd環境底下,執行命令“adb pull /data/data/com.android.providers/contacts/contacts.db D:/”,這裡我匯出到了我本地磁碟D盤。

然後就可以用資料庫工具查看了,Pro Android中使用的是Sqliteman。

記錄一些常用資料庫語言:

select * from table1; 
select count(*) from table1; 
select col1, col2 from table1; 
select distinct col1 from table1; 
select count(col1) from (select distinct col1  from table1); 
select count(*), col1 from table1 group by col1; 
select * from table1 t1, table2 t2 where t1.col1 = t2.col1; 
select * from table t1 left outer join table2 t2 on t1.col1 = t2.col1 where ....
    以上是我們檢視Android裝置中的ContentProvider,因為ContentProvider主要使用資料庫儲存,所以我們基本是檢視的資料庫。

(二)ContentProvider的架構

    我們在程式中使用ContentProvider的時候,首先需要註冊,提供授權(Authority),
vnd.android.cursor.dir/vnd.<yourcompanyname.contenttype>

在AndroidManifest檔案中進行註冊
<provider android:name="SomeProvider"  android:authorities="com.your-company.SomeProvider" /> 
    其中,name即自定義ContentProvider的類名,可以省略包名;authorities即是為我們提供可使用的URI。     註冊之後,我們就可以使用content://com.your-company.SomeProvider/來進行訪問了。     在Android中,對於系統級程式我們可以使用簡寫的URI來進行訪問,比如聯絡人可以直接使用contracts。然而對於我們自己的程式,則需要使用全稱,否則無法使用。     以下提供了系統的contacts的註冊
<provider android:name="ContactsProvider2" 
    android:authorities="contacts;com.android.contacts" 
    android:label="@string/provider_label" 
    android:multiprocess="false" 
    android:readPermission="android.permission.READ_CONTACTS" 
    android:writePermission="android.permission.WRITE_CONTACTS"> 
    <path-permission 
            android:pathPrefix="/search_suggest_query" 
            android:readPermission="android.permission.GLOBAL_SEARCH"/> 
    <path-permission 
            android:pathPrefix="/search_suggest_shortcut" 
            android:readPermission="android.permission.GLOBAL_SEARCH"/> 
    <path-permission 
            android:pathPattern="/contacts/.*/photo"                                                                                                                                                                                                                                                                       
            android:readPermission="android.permission.GLOBAL_SEARCH"/> 
    <grant-uri-permission android:pathPattern=".*" /> 
</provider>
    URI:上面提到的“content://com.your-company.SomeProvider/”就是一個URI,有沒有一種很眼熟的感覺,對,他就像HTTP一樣,因為ContentProvider才用了REST和Web服務的抽象機制。
uri的格式如下:
content://<authority-name>/<path-segment1>/<path-segment2>/etc… 
例子:content://com.google.provider.NotePad/notes/23
    其中,notes就是path-segment,而23,就是我們要訪問資源的ID。

    MIME Type:我們進行了一次URI請求之後就會返回資料,這類資料的型別就用MIME來表示。Android遵循了一定的約定來定義MIME型別。

    對於單條記錄:

vnd.android.cursor.item/vnd.<yourcompanyname.contenttype>
    對於記錄或行的集合:

vnd.android.cursor.dir/vnd.<yourcompanyname.contenttype>

    其中,vnd表示這些型別和子型別具有非標準的、供應商特定的形式。對於Android,本質上能識別項是“單個”還是“集合”項,作為程式設計師,我們只關心子型別,即
vnd.<yourcompanyname.contenttype>

    Cursor:遊標是一個行集合,在讀取資料之前,我們需要使用moveToFirst(),將遊標放置第一行。使用遊標的時候,需要知道列型別和列名稱,在訪問之前,需要將列名稱轉化為列編號,通過遊標,可以獲取行計數。

    以下示例演示瞭如何使用URI從ContentProvider獲取一個遊標

// An array specifying which columns to return
Sting[] projection = new String[] {
	Contacts._ID,
	Contacts.DISPLAY_NAME_PRIMARY
};
Uri mContactsUri = ContactsContract.Contacts.CONTENT_URI;

// Best way to retrieve a query; returns a managed query
Cursor managedCursor = managedQuery(mContactsUri,
				projection, // which columns to return
				null,       // where clause
				Contacts.DISPLAY_NAME_PRIMARY + " ASC"); // Order-by clause
    Where條件語句的用法:ContentProvider提供了兩種方式來傳遞where字句

1、通過URI

Activity somActivity
// ..intialize someActivity
String moteUri = "content://com.google.provider.NotePad/notes/23";
Cursor managedCursor = someActivity.managedQuery(noteUri,
			projection, // Which columns to return.
			null,       // WHERE clause
			null);      // Order-by clause
2、通過string字句與一組可替換的字串資料引數的組合

public final Cursor managedQuery(Uri uri,
	String[] projection,
	String selection,
	String[] seleciontArgs,
	String sortOrder)