>Content Provider 簡介
Android應用程式的四個核心組件是:Activity、Service、Broadcast Receiver 和 Content Provider。那麼這個Content Provider到底是什麼呢?它和SQLite又有什麼區別呢?
我們知道如果用SQLite來儲存資料的話,只能在本應用程式之間進行增、刪、改、查,絕對訪問不到別的應用程式的資料。因為在Android中,應用程式彼此之間相互獨立的,它們都運行在自己獨立的虛擬機器中。
那麼怎麼訪問別的應用程式的資料呢?那麼我們就要用到Content Provider了。
同樣可以把Content Provider看成一個關係型資料庫,只不過那比SQLite多了一個功能:Content Provider是所有應用程式之間資料存放區和檢索的橋樑,它使得各個應用程式之間實現資料共用。
>Content Provider的常用方法
//查詢 query(Uri, String[], String, String[], String); //插入 insert(Uri, ContentValues); //更新 update(Uri, ContentValues, String, String[]); //刪除 delete(Uri, String, String[]); //獲得MIME資料類型 getType(Uri);
>Content Provider的表結構
Content Provider 將其儲存的資料以資料表的形式提供給訪問者,在資料表中每一行為一條記錄,每一列為具有特定類型和意義的資料。每一條資料記錄都包括一個 "_ID" 數值欄位,改欄位唯一標識一條資料。
_ID |
NUMBER |
NUMBER_KEY |
LABEL |
NAME |
TYPE |
13 |
(425) 555 6677 |
425 555 6677 |
Kirkland office |
Bully Pulpit |
TYPE_WORK |
44 |
(212) 555-1234 |
212 555 1234 |
NY apartment |
Alan Vain |
TYPE_HOME |
45 |
(212) 555-6657 |
212 555 6657 |
Downtown office |
Alan Vain |
TYPE_MOBILE |
53 |
201.555.4433 |
201 555 4433 |
Love Nest |
Rex Cars |
TYPE_HOME |
>使用現成的Content Provider
有些資料是很常用的,會被很多應用程式訪問。於是Android為這些常用的資料提供了Content Provider,這些常用的資料包括:音頻、視頻、圖片和通訊錄等等。我們不需要自己實現Content
Provider,直接使用現成的Content Provider就OK了。Android所提供的Content
Provider都存放在android.provider包當中。
>Content
Provider的統一操作介面:URI
Content
Provider實現應用程式之間資料共用的簡單原理:一個程式可以使用Content Provider 定義一個URI,提供統一的操作介面,其他程式可以通過此URI訪問指定的資料,進行資料的增、刪、改、查。
何謂URI?請往下看:
每一個Content
Provider 都對外提供一個能夠唯一標識自己資料集(data set)的URI, 如果一個Content Provider管理多個資料集,其將會為每個資料集分配一個獨立的URI。Content Provider就是通過URI對象來共用其資料的。
URI的格式圖如下:
各個部分的組成:
A:標準首碼,是固定的,"content://"是用來標識資料是由Content Provider管理的 schema。
B:URI的標識,它定義了是哪個Content Provider提供這些資料。對於第三方應用程式,為了保證URI標識的唯一性,它必須是一個完整的、小寫類名。這個標識在 元素的 authorities屬性中說明:一般是定義該ContentProvider的包.類的名稱
C:需要訪問的資料欄位名稱。
D:如果URI中包含表示需要擷取的記錄的_ID;如何有D部分,則就返回該_ID對應的資料,否則表示返回整張表的資料
>實現讀取Android系統通訊錄提供的Content
Provider的簡單的例子
1、建立一個ContentProvider項目。
2、res/layout/main.xml內容省略,就是製作一個查詢按鈕。
3、ContentProviderActivity.java的內容如下:
import android.app.Activity;import android.content.ContentResolver;import android.database.Cursor;import android.os.Bundle;import android.provider.ContactsContract;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;public class ContentProviderActivity extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button);OnClickListener onClickListener = new OnClickListener() {@Overridepublic void onClick(View v) {// 在Content Provider使用過程中,還需要借用ContentResolver對象間接來操作ContentProvider來擷取資料。// ContentResolver通過應用程式的getContentResolver()方法獲得。一般情況下,ContentResolver是單一實例的,// 但是可以有多個ContentResolver在不用的應用程式和不同的進程之間和ContentResolver互動。ContentResolver contentResolver = getContentResolver();// 獲得所有的連絡人// 參數1:詞表的內容URI// 參數2:指定取哪個欄位的內容,null表示select *// 參數3:where條件// 參數4:where條件的參數// 參數5:排序方式Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null,null, null);// 迴圈遍曆if (cursor.moveToFirst()) {// 獲得id列的列indexint idColumn = cursor.getColumnIndex(ContactsContract.Contacts._ID);// 獲得displayName列的列indexint displayNameColumn = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);do {// 根據列的index獲得連絡人的ID號String contactId = cursor.getString(idColumn);// 根據列的index獲得連絡人姓名String disPlayName = cursor.getString(displayNameColumn);Toast.makeText(ContentProviderActivity.this,"連絡人姓名:" + disPlayName, Toast.LENGTH_LONG).show();// 查看該連絡人有多少個電話號碼。如果沒有這傳回值為0int phoneCount = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));if (phoneCount > 0) {// 獲得連絡人的電話號碼列表Cursor phonesCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID+ " = " + contactId, null,null);if (phonesCursor.moveToFirst()) {do {// 遍曆所有的電話號碼String phoneNumber = phonesCursor.getString(phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));Toast.makeText(ContentProviderActivity.this,"連絡人電話:" + phoneNumber,Toast.LENGTH_LONG).show();} while (phonesCursor.moveToNext());}}} while (cursor.moveToNext());}}};button.setOnClickListener(onClickListener);}}
別忘了在AndroidManifest.xml加上下面的許可權聲明
<uses-permission android:name="android.permission.READ_CONTACTS"/>