Android內容提供者

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實現了在第三方應用中對我們應用的數據庫進行增刪改查等操作

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容