內(nèi)容提供者 參考:
Android四大組件之內(nèi)容提供者--ContentProvider - java小兵 - CSDN博客 http://blog.csdn.net/wodewutai17quiet/article/details/46670597
Android四大組件之內(nèi)容提供者--ContentProvider ?
B程序通過內(nèi)容提供者來訪問聯(lián)系人程序的數(shù)據(jù)。
?
1,什么是ContentProvider ?
? ? ? ? ContentProvider將應(yīng)用中的數(shù)據(jù)對(duì)其它應(yīng)用進(jìn)行共享, 提供增刪改查的方法 ?
? ? ? ? ContentProvider統(tǒng)一了數(shù)據(jù)的訪問方式,不必針對(duì)不同數(shù)據(jù)類型采取不同的訪問策略 ?
? ? ? ? ContentProvider將數(shù)據(jù)封裝,只暴露出我們希望提供給其它程序的數(shù)據(jù) ?
? ? ? ? ContentProvider中可以注冊(cè)觀察者, 監(jiān)聽數(shù)據(jù)的變化 ??
2,怎么創(chuàng)建 ?
? ? ? ? 2.1定義類繼承ContentProvider, 實(shí)現(xiàn)抽象方法,抽象方法中對(duì)數(shù)據(jù)庫操作的增刪改查都有。 ?
? ? ? ? 2.2在清單文件中注冊(cè):在清單文件的<application>節(jié)點(diǎn)下進(jìn)行配置<provider>標(biāo)簽,標(biāo)簽中需要指定name和authorities屬性 ?
? ? ? ? ? ? name:完整的類名。 可以省略包名(manifest節(jié)點(diǎn)的package值),注意:省略后的類名是以"."開頭的。 ?
? ? ? ? ? ? authorities:主機(jī) ,是訪問Provider時(shí)的路徑,要唯一 ?
?
B程序需要通過com.baidu這個(gè)url來實(shí)現(xiàn)訪問修改讀取聯(lián)系人程序。
完整類名就是繼承ContentProvider類的那個(gè)類的完整類名。
這樣配置也是告訴計(jì)算機(jī),我這個(gè)類是內(nèi)容提供者,后面要被別人訪問,并且可以通過com.baidu這個(gè)主機(jī)訪問我。
我們?cè)贐程序中通過內(nèi)容解析者和主機(jī)名訪問聯(lián)系人程序。
?
3,在手機(jī)上注冊(cè) 將應(yīng)用安裝到手機(jī)上即可, 不用運(yùn)行程序 4,其它應(yīng)用怎么訪問 外部應(yīng)用使用ContentResolver 類對(duì)ContentProvider中的數(shù)據(jù)進(jìn)行訪問(CRUD操作) 獲取解析器ContentResolver ContentResolver resolver = Context.getContentResolver(); 通過resolver.insert(), delete(), update(), query()方法訪問Uri關(guān)聯(lián)的ContentProvider
?
?
5,Uri的處理 URI代表要操作的數(shù)據(jù),由scheme、authorites、path三部分組成 eg: content://com.jxn.provider/person scheme | authorites | path 1,schema:表明要訪問ContentProvider。固定為:"content://" 2,Authority(主機(jī)名或授權(quán)): 定義了是哪個(gè)ContentProvider提供這些數(shù)據(jù)。 3,path:路徑,可根據(jù)業(yè)務(wù)邏輯自定義 。eg: person、person/insert、person/insert/10等等 4,ID:通常定義URI時(shí)使用"#"號(hào)占位符代替, 使用時(shí)替換成對(duì)應(yīng)的數(shù)字 "content://com.jxn.provider/person/#" #表示數(shù)據(jù)id(#代表任意數(shù)字) "content://com.jxn.provider/person/*" *來匹配任意文本 Android系統(tǒng)提供了兩個(gè)用于操作Uri的工具類:UriMatcher 和 ContentUris 1,UriMatcher類用于匹配Uri ,用法如下: 第一步:把你需要匹配的Uri路徑全部給注冊(cè)上,如下: //常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼 UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); //如果match()方法匹配content://com.jxn.provider.personprovider/person路徑,返回匹配碼為1 matcher.addURI("com.jxn.provider.personprovider", "person", 1);//添加需要匹配uri,如果匹配就會(huì)返回匹配碼 //如果match()方法匹配content://com.jxn.provider.personprovider/person/230路徑,返回匹配碼為2 matcher.addURI("com.jxn.provider.personprovider", "person/#", 2);//#號(hào)為通配符 第二步:使用matcher.match(uri)方法對(duì)輸入的Uri進(jìn)行匹配,如果匹配成功就返回匹配碼 switch (matcher.match(Uri.parse("content://com.jxn.provider.personprovider/person/10"))) { case 1 // 相應(yīng)的業(yè)務(wù)操作 break; case 2 // 相應(yīng)的業(yè)務(wù)操作 break; default: // 相應(yīng)的業(yè)務(wù)操作 break; } 2,ContentUris類用于為路徑加上ID和獲取路徑的ID 給Uri加上id: ContentUris.withAppendedId(uri, id) 獲取id: ContentUris.parseId(uri)
?
?
6,監(jiān)聽內(nèi)容提供者數(shù)據(jù)變化?
?????
??????? 1,如果ContentProvider的訪問者需要知道ContentProvider中的數(shù)據(jù)發(fā)生了變化,可以在ContentProvider 發(fā)生數(shù)據(jù)變化時(shí)調(diào)用getContentResolver().notifyChange(uri, null)來通知注冊(cè)在此URI上的訪問者,例如:?
??????????? public class PersonContentProvider extends ContentProvider {?
??????????????? public Uri insert(Uri uri, ContentValues values) {?
??????????????????? db.insert("person", "personid", values);?
??????????????????? // 注:如果沒有調(diào)用notifyChange()方法,即使其它應(yīng)用注冊(cè)了ContentObserver,也不會(huì)知道ContentProvider中的數(shù)據(jù)的變化?
??????????????????? getContext().getContentResolver().notifyChange(uri, null);?
??????????????? }?
??????????? }?
?????????????
??????? 2,如果ContentProvider的訪問者需要得到數(shù)據(jù)變化通知,必須使用ContentObserver對(duì)數(shù)據(jù)(用uri描述)進(jìn)行監(jiān)聽,當(dāng)監(jiān)聽到數(shù)據(jù)變化通知時(shí),系統(tǒng)就會(huì)調(diào)用ContentObserver的onChange()方法:?
??????????? getContentResolver().registerContentObserver(Uri.parse("content://com.jxn.providers.personprovider/person"),true, new PersonObserver(new Handler()));?
??????????? public class PersonObserver extends ContentObserver{?
??????????????? public PersonObserver(Handler handler) {?
??????????????????? super(handler);?
??????????????? }?
??????????????? public void onChange(boolean selfChange) {?
??????????????????? //此處可以進(jìn)行相應(yīng)的業(yè)務(wù)處理?
??????????????? }?
??????????? }??
?
7,補(bǔ)充?
??????? getType()方法:主要用于匹配數(shù)據(jù)類型,返回當(dāng)前Uri所代表數(shù)據(jù)的MIME類型。?
??????????? 如果返回?cái)?shù)據(jù)是單條數(shù)據(jù):vnd.android.cursor.item??
??????????? 如果返回?cái)?shù)據(jù)是多條數(shù)據(jù):vnd.android.cursor.dir??
?
?
案例:B應(yīng)用通過A應(yīng)用提供的ContentProvider訪問A應(yīng)用中的數(shù)據(jù)?? ?? ????//?提供ContentProvider的A應(yīng)用中定義的SQLiteProvider?? ????public?class?SQLiteProvider?extends?ContentProvider?{?? ?? ????????//?Uri匹配器,?用來匹配傳入的Uri?? ????????private?static?final?UriMatcher?matcher?=?new?UriMatcher(UriMatcher.NO_MATCH);?? ?????????? ????????private?static?final?int?PERSON?=?1;?? ?????????? ????????//?DBOpenHelper?extends?SQLiteOpenHelper?? ????????private?DBOpenHelper?helper;?? ?? ????????static?{?? ????????????//?設(shè)置一個(gè)Uri,?如果匹配到person,?返回1?? ????????????matcher.addURI("com.jxn.sqlite.provider",?"person",?PERSON);?? ????????}?? ?????????? ?? ????????//?其它應(yīng)用第一次訪問時(shí)(此時(shí)會(huì)創(chuàng)建ContentProvider)執(zhí)行?? ????????//?第一次啟動(dòng)時(shí)執(zhí)行,?然后會(huì)長(zhǎng)期駐留在后臺(tái),?除非被殺死,?否則不會(huì)再執(zhí)行?? ????????@Override?? ????????public?boolean?onCreate()?{?? ????????????helper?=?new?DBOpenHelper(getContext());?? ????????????return?true;?? ????????}?? ?? ????????//?外部應(yīng)用使用此方法查詢數(shù)據(jù)?? ????????@Override?? ????????public?Cursor?query(Uri?uri,?String[]?projection,?String?selection,?String[]?selectionArgs,?String?sortOrder)?{?? ????????????SQLiteDatabase?db?=?helper.getReadableDatabase();?? ?????????????? ????????????//?用匹配器匹配傳入的uri?? ????????????switch?(matcher.match(uri))?{?? ????????????????case?PERSON:?? ????????????????????return?db.query("person",?projection,?selection,?selectionArgs,?null,?null,?sortOrder);?????//?執(zhí)行查詢?? ????????????????default:?? ????????????????????throw?new?RuntimeException("Uri不能識(shí)別:?"?+?uri);?? ????????????}?? ????????}?? ?? ????????//?外部應(yīng)用使用此方法添加數(shù)據(jù)?? ????????@Override?? ????????public?Uri?insert(Uri?uri,?ContentValues?values)?{?? ????????????SQLiteDatabase?db?=?helper.getWritableDatabase();?? ????????????switch?(matcher.match(uri))?{?? ????????????????case?PERSON:?? ????????????????????long?id?=?db.insert("person",?"id",?values);????//?插入記錄,?得到id?? ????????????????????return?ContentUris.withAppendedId(uri,?id);?????//?把id跟在uri后面返回?? ????????????????default:?? ????????????????????throw?new?RuntimeException("Uri不能識(shí)別:?"?+?uri);?? ????????????}?? ????????}?? ?? ????????@Override?? ????????public?int?delete(Uri?uri,?String?selection,?String[]?selectionArgs)?{?? ????????????SQLiteDatabase?db?=?helper.getWritableDatabase();?? ????????????switch?(matcher.match(uri))?{?? ????????????????case?PERSON:?? ????????????????????return?db.delete("person",?selection,?selectionArgs);?? ????????????????default:?? ????????????????????throw?new?RuntimeException("Uri不能識(shí)別:?"?+?uri);?? ????????????}?? ????????}?? ?? ????????@Override?? ????????public?int?update(Uri?uri,?ContentValues?values,?String?selection,?String[]?selectionArgs)?{?? ????????????SQLiteDatabase?db?=?helper.getWritableDatabase();?? ????????????switch?(matcher.match(uri))?{?? ????????????????case?PERSON:?? ????????????????????return?db.update("person",?values,?selection,?selectionArgs);?? ????????????????default:?? ????????????????????throw?new?RuntimeException("Uri不能識(shí)別:?"?+?uri);?? ????????????}?? ????????}?? ?? ????????@Override?? ????????public?String?getType(Uri?uri)?{?? ????????????switch?(matcher.match(uri))?{?? ????????????????case?PERSON:?? ????????????????????return?"vnd.android.cursor.dir/person";?????//?mimetype?? ????????????????default:?? ????????????????????throw?new?RuntimeException("Uri不能識(shí)別:?"?+?uri);?? ????????????}?? ????????}?? ????}?? ?? ?? ????//?B應(yīng)用中要訪問A應(yīng)用的數(shù)據(jù)的測(cè)試類?? ????public?class?ProviderTest?extends?AndroidTestCase?{?? ?????????? ????????public?void?test()?{?? ?????????? ????????????//?獲取解析器對(duì)象?? ????????????ContentResolver?resolver?=?getContext().getContentResolver();?? ?????????????? ????????????//?訪問內(nèi)容提供者?? ????????????Uri?uri?=?Uri.parse("content://com.jxn.sqlite.provider");?? ????????????ContentValues?values?=?new?ContentValues();?? ?? ????????}?? ?????????? ????????public?void?testQuery()?{?? ?????????? ????????????//?獲取解析器對(duì)象?? ????????????ContentResolver?resolver?=?getContext().getContentResolver();?? ????????????Uri?uri?=?Uri.parse("content://com.jxn.sqlite.provider/person");?? ?????????????? ????????????//?訪問內(nèi)容提供者?? ????????????Cursor?c?=?resolver.query(uri,?new?String[]{?"id",?"name",?"balance"?},?"balance>?",?new?String[]{?"9000"?},?"balance?DESC");?? ????????????while?(c.moveToNext())?{?? ????????????????Person?p?=?new?Person(c.getInt(0),?c.getString(1),?c.getInt(2));?? ????????????????System.out.println(p);?? ????????????}?? ????????}?? ?????????? ????????public?void?testInsert()?{?? ????????????ContentResolver?resolver?=?getContext().getContentResolver();?? ????????????Uri?uri?=?Uri.parse("content://com.jxn.sqlite.provider/person");?? ?????????????? ????????????ContentValues?values?=?new?ContentValues();?? ????????????values.put("name",?"provider");?? ????????????values.put("balance",?12345);?? ?????????????? ????????????//?插入數(shù)據(jù),?并且得到這條數(shù)據(jù)的uri?? ????????????uri?=?resolver.insert(uri,?values);?? ?????????????? ????????????System.out.println(uri);?? ????????}?? ?????????? ????????public?void?testUpdate()?{?? ????????????ContentResolver?resolver?=?getContext().getContentResolver();?? ????????????Uri?uri?=?Uri.parse("content://com.jxn.sqlite.provider/person");?? ?????????????? ????????????ContentValues?values?=?new?ContentValues();?? ????????????values.put("name",?"update");?? ????????????values.put("balance",?54321);?? ????????????int?count?=?resolver.update(uri,?values,?null,?null);?? ????????????System.out.println(count);?? ????????}?? ?????????? ????????public?void?testDelete()?{?? ????????????ContentResolver?resolver?=?getContext().getContentResolver();?? ????????????Uri?uri?=?Uri.parse("content://com.jxn.sqlite.provider/person");?? ?????????????? ????????????int?count?=?resolver.delete(uri,?null,?null);?? ????????????System.out.println(count);?? ????????}?? ?????????? ????????public?void?testGetType()?{?? ????????????ContentResolver?resolver?=?getContext().getContentResolver();?? ????????????//?獲取uri的類型?? ????????????String?type?=?resolver.getType(Uri.parse("content://com.jxn.sqlite.provider/person"));?? ????????????System.out.println(type);?? ????????}?? ????} ?
轉(zhuǎn)載于:https://www.cnblogs.com/Renyi-Fan/p/7471659.html
超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生
總結(jié)
以上是生活随笔 為你收集整理的内容提供者 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。