考慮到這一點,MediaStore 內容提供器,這個用來分發映像,音頻和視頻資料的主內容提供器,利用了一個特殊的約定:用來擷取關於這個位元據的元資訊的query()或managedQuery()方法使用的URI,同樣可以被openInputStream()方法用來資料本身。類似的,用來把元資訊放進一個MediaStore記錄裡的insert()方法使用的URI,同樣可以被openOutputStream()方法用來在那裡存放位元據。下面的代碼片斷說明了這個約定:
java代碼:
- import android.provider.MediaStore.Images.Media;
- import android.content.ContentValues;
- import java.io.OutputStream;
- // Save the name and description of an image in a ContentValues map.
- ContentValues values = new ContentValues(3);
- values.put(Media.DISPLAY_NAME, "road_trip_1");
- values.put(Media.DESCRIPTION, "Day 1, trip to Los Angeles");
- values.put(Media.MIME_TYPE, "image/jpeg");
- // Add a new record without the bitmap, but with the values just set.
- // insert() returns the URI of the new record.
- Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
- // Now get a handle to the file for that record, and save the data into it.
- // Here, sourceBitmap is a Bitmap object representing the file to save to the database.
- try {
- OutputStream outStream = getContentResolver().openOutputStream(uri);
- sourceBitmap.compress(Bitmap.CompressFormat.JPEG, 50, outStream);
- outStream.close();
- } catch (Exception e) {
- Log.e(TAG, "exception while writing image", e);
- }
複製代碼
批次更新記錄Batch updating records
要批次更新一組記錄(例如,把所有欄位中的"NY"改為"New York"),可以傳以需要改變的列和值參數來調用ContentResolver.update()方法。
刪除一個記錄Deleting a record
要刪除單個記錄,可以傳以一個特定行的URI參數來調用ContentResolver.delete()方法。
要刪除多行記錄,可以傳以需要被刪除的記錄類型的URI參數來調用ContentResolver.delete()方法(例如,android.provider.Contacts.People.CONTENT_URI)以及一個SQL WHERE 語句來定義哪些行要被刪除。
建立一個內容提供器Creating a Content Provider
要建立一個內容提供器,你必須:
建立一個儲存資料的系統。大多數內容提供器使用Android的檔案儲存方法或SQLite資料庫來存放它們的資料,但是你可以用任何你想要的方式來存放資料。Android提供SQLiteOpenHelper類來協助你建立一個資料庫以及SQLiteDatabase類來管理它。
擴充ContentProvider類來提供資料提供者。
在清單manifest檔案中為你的應用程式聲明這個內容提供器(AndroidManifest.xml)。
擴充ContentProvider類Extending the ContentProvider class
你可以定義一個ContentProvider子類來暴露你的資料給其它使用符合ContentResolver和遊標Cursor對象約定的應用程式。理論上,這意味需要實現6個ContentProvider類的抽象方法:
query()
insert()
update()
delete()
getType()
onCreate()
query()方法必須返回一個遊標Cursor對象可以用來遍曆請求資料,遊標本身是一個介面,但Android提供了一些現成的Cursor對象給你使用。例如,SQLiteCursor可以用來遍曆SQLite資料庫。你可以通過調用任意的SQLiteDatabase類的query()方法得到它。還有一些其它的遊標實現-比如MatrixCursor-用來訪問沒有存放在資料庫中的資料。
因為這些內容提供器的方法可以從不同的進程和線程的各個ContentResolver對象中調用,所以它們必須以安全執行緒的方式來實現。
周到起見,當資料被修改時,你可能還需要調用ContentResolver.notifyChange()方法來通知偵聽者。
除了定義子類以外,你應該還需要採取其它一些步驟來簡化用戶端的工作和讓這個類更容易被訪問:
定義一個public static final Uri 命名為CONTENT_URI。這是你的內容提供器處理的整個content: URI的字串。你必須為它定義一個唯一的字串。最佳方案是使用這個內容提供器的全稱(fully qualified)類名(小寫)。因此,例如,一個TransportationProvider類可以定義如下:
java代碼:
- public static final Uri CONTENT_URI = Uri.parse("content://com.example.codelab.transporationprovider");
複製代碼