簡介
ContentProvider是一組讓你跟其他應用程式存取的資料庫
對於剛接觸的Android開發者來說
它會是一個比較難以上手的區域
Android提供一套通用的介面讓每個應用程式可以進行CRUD(新增、讀取、更新、刪除)的操作
ContentProvider用於管理音訊、影片、圖片、個人聯絡資訊等資料
ContentProvider處理流程
如果你要操作一個ContentProvider
可以透過繼承ContentProvider類別
就會看到以下的範例出現幾個方法必須實作
public class ContentProviderDemo extends ContentProvider{
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
但是一般正常的作法是不會自己去實作的
ContentResovler類別是實作ContentProvider的子類別
通常會透過ContentResovler類別去操作已經實作CURD
一般你要操作它會使用它的四種方法query、insert、delete和update
final Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
final Uri insert(Uri url, ContentValues values)
final int delete(Uri url, String where, String[] selectionArgs)
final int update(Uri uri, ContentValues values, String where, String[] selectionArgs)
更多詳細方法可以參考
https://developer.android.com/reference/android/content/ContentResolver.html
存取ContentProvider記得要加入權限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
6.0以後的手機還要多加入RuntimePermission
private static final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
if (grantResults.length <= 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
finish();
}
return;
}
}
}
我們以第一個query方法來進行說明
可以看到第一個傳入的參數是Uri
Android提供了一套查詢ContentProvider的Uri
https://developer.android.com/reference/android/provider/package-summary.html
query() 引數 | SELECT 關鍵字/參數 | 備註 |
Uri | FROM table_name | Uri 會對應至供應程式中名為的「table_name」表格。 |
projection | col,col,col,… | projection 代表需針對每個擷取的資料列 納入的一系列資料欄。 |
selection | WHERE col = value | selection 會指定資料列選取條件。 |
selectionArgs | (沒有任何相對應的關鍵字/參數。選取引數會取代選取子句中的 ? 預留位置。) | |
sortOrder | ORDER BY col,col,… | sortOrder 會指定資料列在傳回的 Cursor 中的顯示順序。 |
查詢資料
透過ContentResolver來進行查詢手機內相簿的資料夾名稱
private void queryImageBucketNameData(){
try {
final String[] columns = {MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
final String orderBy = MediaStore.Images.Media.DATE_ADDED;
Cursor imagecursor = getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
null, null, orderBy + " DESC");
if (imagecursor != null && imagecursor.getCount() > 0) {
while (imagecursor.moveToNext()) {
int bucketColumn = imagecursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
String bucket = imagecursor.getString(bucketColumn);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
插入資料
將想要插入的資訊放入至ContentValues物件內就可以進行插入
Uri mNewUri;
ContentValues mNewValues = new ContentValues();
mNewValues.put(UserDictionary.Words.APP_ID, "example.user");
mNewValues.put(UserDictionary.Words.LOCALE, "en_US");
mNewValues.put(UserDictionary.Words.WORD, "insert");
mNewValues.put(UserDictionary.Words.FREQUENCY, "100");
mNewUri = getContentResolver().insert(
UserDictionary.Word.CONTENT_URI,
mNewValues
);
更新資料
如要更新資料列,請使用內含經過更新的值 (與您在插入資料時所使用的值相同) 以及選取條件 (與您在建立查詢時所使用的選取條件相同) 的 ContentValues 物件。 您所使用的用戶端方法為 ContentResolver.update()。您只需針對要更新的資料欄,將相關值加到 ContentValues 物件即可。 如果您想清除資料欄的內容,請將值設定為 null。
ContentValues mUpdateValues = new ContentValues();
String mSelectionClause = UserDictionary.Words.LOCALE + "LIKE ?";
String[] mSelectionArgs = {"en_%"};
int mRowsUpdated = 0;
mUpdateValues.putNull(UserDictionary.Words.LOCALE);
mRowsUpdated = getContentResolver().update(
UserDictionary.Words.CONTENT_URI,
mUpdateValues
mSelectionClause
mSelectionArgs
);
刪除資料
刪除資料列的方法與擷取資料列資料類似:
您必須為想刪除的資料列指定選取條件,
用戶端方法最後會傳回已刪除的資料列數量。
以下程式碼片段可刪除應用程式 ID 為「user」的資料列。
此外,這個方法還會傳回已刪除的資料列數量。
String mSelectionClause = UserDictionary.Words.APP_ID + " LIKE ?";
String[] mSelectionArgs = {"user"};
int mRowsDeleted = 0;
mRowsDeleted = getContentResolver().delete(
UserDictionary.Words.CONTENT_URI,
mSelectionClause
mSelectionArgs
);
這樣就是一個簡單的ContentProvider操作了
更多詳細資訊可以參考官網
https://developer.android.com/guide/topics/providers/content-provider-basics.html?hl=zh-tw#SimpleQuery