1.什么是ContentProvider
首先,ContentProvider(內容提供者)是android中的四大組件之一,但是在一般的開發中,可能使用的比較少。 ContentProvider為不同的軟件之間數據共享,提供統一的接口。也就是說,如果我們想讓其他的應用使用我們自己程序內的數據,就可以使用ContentProvider定義一個對外開放的接口,從而使得其他的應用可以使用咱們應用的文件、數據庫內存儲的信息。當然,自己開發的應用需要給其他應用共享信息的需求可能比較少見,但是在Android系統中,很多系統自帶應用,比如聯系人信息,圖片庫,音頻庫等應用,為了對其他應用暴露數據,所以就使用了ContentProvider機制。所以,我們還是要學習ContentProvider的基本使用,在遇到獲取聯系人信息,圖片庫,音頻庫等需求的時候,才能更好的實現功能
2.如何定義一個ContentProvider
Android系統為了讓我們更好的對外暴露數據,提供了統一的接口,所以定義了抽象類ContentProvider,因此,如果我們想對外提供數據,我們需要繼承ContentProvider,并且實現下面的這幾個方法:
onCreate() 當我們的provider初始化時被調用,我們應該在這個方法里面完成部分初始化操作 query() 查詢方法,用于給調用者返回數據 insert() 插入操作,用于讓外部應用插入數據到內容提供者中 update() 更新操作,用于更新內容提供者的數據 delete() 用于刪除數據 getType 返回內容提供者的MIME Type
上面這些方法,當我們繼承自ContentProvider的時候,eclipse會自動的給我們添加,但是這并不代表我們每個方法都需要自定義實現。如果我們只希望給其他應用提供數據,而不允許其他應用修改我們的數據,那么我們只需要實現onCreate(),getType()和query()這三個方法就可以了,其他的三個方法我們可以根據業務需求,實現或者是不實現。
因為一般使用ContentProvider向外部暴露數據庫的信息,因此,本篇將以使用ContentProvider向其他應用暴露數據庫信息為例,講解ContentProvider的基本使用。
Android中SQLite數據庫的創建和使用,本篇不再介紹,不清楚的請看這篇文章 SQLite數據庫的簡單實用
假設讀者已經學會了SQLite數據庫的使用,并且已經建立好了數據庫,下面我們開始寫我們的ContentProvider。 因為注釋解析的比較詳細,所以就不過多解釋了
/**
* Copyright? :版權所有2016
* Author? ? :壞叔叔
* Date? ? ? : 2016/8/21 16:51
*/
public classStudentProviderextendsContentProvider {
//數據庫操作類,用于獲取SQLiteDatabase
privateMyDbOpenHelperdbHelper;
private static final intSTUDENT=1;
private static final intSTUDENTS=2;
// UriMatcher類是一個很重要的類,因為我們需要根據傳入的uri,來判斷執行相對應的操作
private static finalUriMatcherMATCHER=newUriMatcher(UriMatcher.NO_MATCH);
//靜態代碼塊用于初始化MATCHER需要匹配的uri
static{
// MATCHER.addURI(主機名(用于唯一標示一個ContentProvider,這個需要和清單文件中的authorities屬性相同),路徑(可以用來表示我們要操作的數據,路徑的構建應根據業務而定),返回值(用于匹配uri的時候,作為匹配的返回值));
MATCHER.addURI("com.example.mydbdemo.StudentProvider","student",STUDENTS);
MATCHER.addURI("com.example.mydbdemo.StudentProvider","student/#",STUDENT);
}
@Override
public booleanonCreate() {
dbHelper=newMyDbOpenHelper(getContext());
return false;
}
//查詢
//如果uri為content://com.example.mydbdemo.StudentProvider/student
//則代表查詢所有的student表內的數據
//如果uri為content://com.example.mydbdemo.StudentProvider/student/6
//則代表查詢student表內id=6的數據
@Override
publicCursorquery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase db =dbHelper.getReadableDatabase();
//判斷傳入的uri到底匹配哪一個,從而實現不同的業務需求
switch(MATCHER.match(uri)) {
//查詢全部的學生信息
caseSTUDENTS:
//db.query(表明,要查詢的列(是一個String數組), where條件, where條件中的參數, groupBy, having, sortOrder);
returndb.query("student", projection, selection, selectionArgs,null,null, sortOrder);
//查詢某一個id對應的學生的信息
caseSTUDENT:
//取出我們要查詢的數據的id
longid = ContentUris.parseId(uri);
String where ="id="+ id;
//將selection查詢信息拼接到我們的where條件中
if(selection !=null&& !"".equals(selection)) {
where = selection +" and "+ where;
}
returndb.query("student", projection, where, selectionArgs,null,null, sortOrder);
//如uri不匹配,拋出不合法參數的異常
default:
throw newIllegalArgumentException("Unkwon Uri:"+ uri.toString());
}
}
//獲取MIME TYPE
@Override
publicStringgetType(Uri uri) {
switch(MATCHER.match(uri)) {
caseSTUDENT:
return"vnd.android.cursor.item/student";
caseSTUDENTS:
return"vnd.android.cursor.dir/student";
default:
throw newIllegalArgumentException("Unkwon Uri:"+ uri.toString());
}
}
//插入數據
@Override
publicUriinsert(Uri uri, ContentValues values) {
SQLiteDatabase db =dbHelper.getWritableDatabase();
switch(MATCHER.match(uri)) {
caseSTUDENTS:
longid = db.insert("student","name", values);
returnContentUris.withAppendedId(uri, id);
default:
throw newIllegalArgumentException("Uri不匹配");
}
}
//刪除數據
@Override
public intdelete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db =dbHelper.getWritableDatabase();
intcount =0;
switch(MATCHER.match(uri)) {
caseSTUDENTS:
count = db.delete("student", selection, selectionArgs);
returncount;
caseSTUDENT:
longid = ContentUris.parseId(uri);
String where ="id="+ id;
if(selection !=null&& !"".equals(selection)) {
where = selection +" and "+ where;
}
count = db.delete("student", where, selectionArgs);
returncount;
default:
throw newIllegalArgumentException("Unkwon Uri:"+ uri.toString());
}
}
//更新數據
@Override
public intupdate(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db =dbHelper.getWritableDatabase();
intcount =0;
switch(MATCHER.match(uri)) {
caseSTUDENTS:
count = db.update("student", values, selection, selectionArgs);
returncount;
caseSTUDENT:
longid = ContentUris.parseId(uri);
String where ="id="+ id;
if(selection !=null&& !"".equals(selection)) {
where = selection +" and "+ where;
}
count = db.update("student", values, where, selectionArgs);
returncount;
default:
throw newIllegalArgumentException("Unkwon Uri:"+ uri.toString());
}
}
}
我們在定義好我們的ContentProvider之后,因為ContentProvider數據四大組件之一,因此我們還需要在AndroidManifest清單文件中進行注冊才能使用,下面是注冊信息
android:name="com.example.mydbdemo.StudentProvider"
android:exported="true"
android:authorities="com.example.mydbdemo.StudentProvider" >
注意,provider的聲明和activity一樣,都是在application節點進行聲明的。
至此,我們就完成了我們自己的ContentProvider的生命,其他的應用現在就可以使用我們往外部暴露的數據信息了。
3.外部應用如何使用我們的ContentProvider
我們已經定義好了我們自己的ContentProvider,那么外部應用如何調用呢? 下面,我將新建一個測試單元工程,完成對ContentProvider的各個方法的測試
添加方法測試
//使用ContentProvider添加數據的測試
public void testadd() throws Throwable {
//獲取ContentResolver對象,完成對ContentProvider的調用
ContentResolver contentResolver = this.getContext().getContentResolver();
//構建我們的uir,這個uri
Uri insertUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student");
ContentValues values = new ContentValues();
values.put("name", "zhaokaikai");
values.put("age", 91);
values.put("school", "bbbb");
//返回值為我們剛插入進入的數據的uri地址
Uri uri = contentResolver.insert(insertUri, values);
Log.i(TAG, uri.toString());
}
刪除測試方法
//使用ContentProvider刪除數據的測試
public void testDelete() throws Throwable {
ContentResolver contentResolver = this.getContext().getContentResolver();
//刪除id為6的學生信息
Uri deleteUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/6");
contentResolver.delete(deleteUri, null, null);
}
修改測試方法
//使用ContentProvider更新數據的測試
public void testUpdate() throws Throwable {
ContentResolver contentResolver = this.getContext().getContentResolver();
//更新id = 6 的學生信息
Uri updateUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/6");
ContentValues values = new ContentValues();
values.put("name", "testUp");
values.put("age", "101");
values.put("school", "ccccc");
contentResolver.update(updateUri, values, null, null);
}
查詢數據測試
//使用ContentProvider查詢數據的測試
public void testFind() throws Throwable {
ContentResolver contentResolver = this.getContext().getContentResolver();
//這個uri用于查詢所有的數據,若查詢某個id的數據,則構建下面的uri
//Uri selectUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/要查詢的id");
Uri selectUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student");
Cursor cursor = contentResolver.query(selectUri, null, null, null, "id desc");
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
String school = cursor.getString(cursor.getColumnIndex("school"));
Log.i(TAG, "id=" + id + ",name=" + name + ",age=" + age +",school="+school);
}
}
上面的方法都經過了單元測試。
好了,至此,我們就使用ContentProvider實現了在第三方應用中對我們應用的數據庫進行增刪改查等操作