Android應用程序可使用文件或SqlLite數據庫來存儲數據。Content Provider提供了一種在多個應用程序之間數據共享的方式(跨進程共享數據)。java
雖然Content Provider也能夠在同一個應用程序中被訪問,但這麼作並無什麼意義。Content Provider存在的目的向其餘應用程序共享數據和容許其餘應用程序對數據進行增、刪、改、查操做。android
Android系統自己提供了不少Content Provider,例如,音頻、視頻、聯繫人信息等等。咱們能夠經過這些Content Provider得到相關信息的列表。這些列表數據將以Cursor對象返回。所以,從Content Provider返回的數據是二維表的形式。數據庫
對於訪問Content Provider的程序,須要使用ContentResolver對象。ide
ContentResolver cr = getContentResolver();
與Activity同樣,Content Provider也須要與一個URI對應。每個Content Provider能夠控制多個數據集,在這種狀況下,每個數據集會對應一個單獨的URI。全部的URI必須以「content://」開頭。 爲了程序更容易維護,也爲了簡化程序代碼,通常將URI定義成一個常量。例如,下面的常量表示系統的聯繫人電話號碼。ui
android.provider.Contacts.Phones.CONTENT_URI
下面來看一下Content Provider的具體步驟:this
下面對圖5所示的URI的4個部分作一下解釋。code
A:Content Provider URI的固定前綴,也就是說,全部的URI必須以content://開頭。視頻
B:URI中最重要的部分。該部分是Content Provider的惟一標識。對於第三方應用程序來講,該部分最後使用完整的類名(包名+類名),以確保URI的惟一性。該部分須要在 AndroidManifest.xml文件中<provider>標籤中定義,代碼以下:xml
<provider name=".TransportationProvider" authorities="com.example.transportationprovider" . . . >
C:這部分是URI的路徑(path)。表示URI中各類被請求的數據。這部分是可選的, 若是Content Provider僅僅提供一種請求的數據,那麼這部分能夠省略。若是Content Provider要提供多種請求數據。就須要添加多個路徑,甚至是子路徑。例如,「land/bus」、「land/train」、「sea/ship」 就指定了3種可能提供的數據。對象
D:這部分也是可選的。若是要傳遞一個值給Content Provider,能夠經過這部分傳遞。固然,若是不須要傳值,這部分也能夠省略,省略後的URI以下所示:
content://com.example.transportationprovider/trains
本例利用了《基於 android SDK1.5的英文電子詞典的實現》一文中實現的電子詞典程序。經過ContentProvider,將電子詞典的查詞功能共享成Cursor對象。這樣 其餘的應用程序就能夠經過ContentProvider來查詞英文單詞了。
... ... public class DictionaryContentProvider extends ContentProvider { private static UriMatcher uriMatcher; private static final String AUTHORITY = "net.blogjava.mobile.dictionarycontentprovider"; private static final int SINGLE_WORD = 1; private static final int PREFIX_WORDS = 2; public static final String DATABASE_PATH = android.os.Environment .getExternalStorageDirectory().getAbsolutePath() + "/dictionary"; public static final String DATABASE_FILENAME = "dictionary.db"; private SQLiteDatabase database; static { // 添加訪問ContentProvider的Uri uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, "single", SINGLE_WORD); uriMatcher.addURI(AUTHORITY, "prefix/*", PREFIX_WORDS); } // 該方法在Activity的onCreate方法以前調用 @Override public boolean onCreate() { database = openDatabase(); return true; } // 在本例中只實現了query方法,其餘的方法(insert、update和delete)與query方法的實現 // 相似 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = null; switch (uriMatcher.match(uri)) { case SINGLE_WORD: // 查找指定的單詞 cursor = database.query("t_words", projection, selection, selectionArgs, null, null, sortOrder); break; case PREFIX_WORDS: String word = uri.getPathSegments().get(1); // 查找以指定字符串開頭的單詞集合 cursor = database .rawQuery( "select english as _id, chinese from t_words where english like ?", new String[] { word + "%" }); break; default: throw new IllegalArgumentException("<" + uri + ">格式不正確."); } return cursor; } ... ... }
關於DictionaryContentProvider類的代碼須要作以下的解釋。
content://net.blogjava.mobile.dictionarycontentprovider/single content://net.blogjava.mobile.dictionarycontentprovider/prefix/wo
要注意的是,訪問ContentProvider的URI必須以「content://」開頭。
下面在AndroidManifest.xml文件中配置DictionaryContentProvider類。
<provider android:name="DictionaryContentProvider" android:authorities="net.blogjava.mobile.dictionarycontentprovider" />
如今來看看應用程序如何調用ContentProvider。
調用ContentProvider的關鍵是使用 getContentResolver方法來得到一個ContentResolver對象,並經過ContentResolver對象的query方法來 訪問ContentProvider。
首先來定義兩個訪問ContentProvider的常量。
public final String DICTIONARY_SINGLE_WORD_URI = "content://net.blogjava.mobile.dictionarycontentprovider/single"; public final String DICTIONARY_PREFIX_WORD_URI = "content://net.blogjava.mobile.dictionarycontentprovider/prefix";
而後在查詢按鈕的單擊事件中編寫以下的代碼來查詢單詞。
public void onClick(View view) { Uri uri = Uri.parse(DICTIONARY_SINGLE_WORD_URI); // 經過ContentProvider查詢單詞,並返回Cursor對象,而後的操做就和直接從數據中得到 // Cursor對象後的操做是同樣的了 Cursor cursor = getContentResolver().query(uri, null, "english=?", new String[]{ actvWord.getText().toString() }, null); String result = "未找到該單詞."; if (cursor.getCount() > 0) { cursor.moveToFirst(); result = cursor.getString(cursor.getColumnIndex("chinese")); } new AlertDialog.Builder(this).setTitle("查詢結果").setMessage(result) .setPositiveButton("關閉", null).show(); }
下面是顯示單詞列表的代碼。
public void afterTextChanged(Editable s) { if ("".equals(s.toString())) return; Uri uri = Uri.parse(DICTIONARY_PREFIX_WORD_URI + "/" + s.toString()); // 從ContentProvider中得到以某個字符串開頭的全部單詞的Cursor對象 Cursor cursor = getContentResolver().query(uri, null, null, null, null); DictionaryAdapter dictionaryAdapter = new DictionaryAdapter(this, cursor, true); actvWord.setAdapter(dictionaryAdapter); }