原文地址:http://justsee.iteye.com/blog/936612
當(dāng)應(yīng)用繼承ContentProvider類,并重寫該類用于提供數(shù)據(jù)和存儲數(shù)據(jù)的方法,就可以向其他應(yīng)用共享其數(shù)據(jù)。雖然使用其他方法也可以對外共享數(shù)據(jù),但數(shù)據(jù)訪問方式會因數(shù)據(jù)存儲的方式而不同,如:采用文件方式對外共享數(shù)據(jù),需要進(jìn)行文件操作讀寫數(shù)據(jù);采用sharedpreferences共享數(shù)據(jù),需要使用sharedpreferences API讀寫數(shù)據(jù)。而使用ContentProvider共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)訪問方式。
當(dāng)應(yīng)用需要通過ContentProvider對外共享數(shù)據(jù)時,第一步需要繼承ContentProvider并重寫下面方法:
public class PersonContentProvider extends ContentProvider{
?? public boolean onCreate()
?? public Uri insert(Uri uri, ContentValues values)
?? public int delete(Uri uri, String selection, String[] selectionArgs)
?? public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
?? public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
?? public String getType(Uri uri)}
第二步需要在AndroidManifest.xml使用<provider>對該ContentProvider進(jìn)行配置,為了能讓其他應(yīng)用找到該ContentProvider , ContentProvider 采用了authorities(主機(jī)名/域名)對它進(jìn)行唯一標(biāo)識,你可以把 ContentProvider看作是一個網(wǎng)站(想想,網(wǎng)站也是提供數(shù)據(jù)者),authorities 就是他的域名:
<manifest .... >
?? ?<application android:icon="@drawable/icon" android:label="@string/app_name">
?? ? ? ?<provider android:name=".PersonContentProvider" android:authorities="com.jbridge.provider.personprovider"/>
?? ?</application>
</manifest>
注意:一旦應(yīng)用繼承了ContentProvider類,后面我們就會把這個應(yīng)用稱為ContentProvider(內(nèi)容提供者)。
Uri介紹
Uri代表了要操作的數(shù)據(jù),Uri主要包含了兩部分信息:1》需要操作的ContentProvider ,2》對ContentProvider中的什么數(shù)據(jù)進(jìn)行操作,一個Uri由以下幾部分組成:
?ContentProvider(內(nèi)容提供者)的scheme已經(jīng)由Android所規(guī)定, scheme為:content:// 主機(jī)名(或叫Authority)用于唯一標(biāo)識這個ContentProvider,外部調(diào)用者可以根據(jù)這個標(biāo)識來找到它。 路徑(path)可以用來表示我們要操作的數(shù)據(jù),路徑的構(gòu)建應(yīng)根據(jù)業(yè)務(wù)而定,如下: 要操作person表中id為10的記錄,可以構(gòu)建這樣的路徑:/person/10 要操作person表中id為10的記錄的name字段, person/10/name 要操作person表中的所有記錄,可以構(gòu)建這樣的路徑:/person 要操作xxx表中的記錄,可以構(gòu)建這樣的路徑:/xxx 當(dāng)然要操作的數(shù)據(jù)不一定來自數(shù)據(jù)庫,也可以是文件等他存儲方式,如下: 要操作xml文件中person節(jié)點(diǎn)下的name節(jié)點(diǎn),可以構(gòu)建這樣的路徑:/person/name 如果要把一個字符串轉(zhuǎn)換成Uri,可以使用Uri類中的parse()方法,如下: Uri uri = Uri.parse("content://com.jbridge.provider.personprovider/person")
UriMatcher類使用介紹 因?yàn)閁ri代表了要操作的數(shù)據(jù),所以我們很經(jīng)常需要解析Uri,并從Uri中獲取數(shù)據(jù)。Android系統(tǒng)提供了兩個用于操作Uri的工具類,分別為UriMatcher 和ContentUris 。掌握它們的使用,會便于我們的開發(fā)工作。 UriMatcher類用于匹配Uri,它的用法如下: 首先第一步把你需要匹配Uri路徑全部給注冊上,如下: //常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼(UriMatcher.NO_MATCH的值為-1) UriMatcher ?sMatcher = new UriMatcher(UriMatcher.NO_MATCH); //如果match()方法匹配content://com.jbridge.provider.personprovider/person路徑,返回匹配碼為1 sMatcher.addURI(“com.jbridge.provider.personprovider”, “person”, 1);//添加需要匹配uri,如果匹配就會返回匹配碼 //如果match()方法匹配content://com.jbridge.provider.personprovider/person/230路徑,返回匹配碼為2 sMatcher.addURI(“com.jbridge.provider.personprovider”, “person/#”, 2);//#號為通配符 switch (sMatcher.match(Uri.parse("content://com.jbridge.provider.personprovider/person/10"))) {? case 1 break; case 2 break; default://不匹配 break; } 注冊完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法對輸入的Uri進(jìn)行匹配,如果匹配就返回匹配碼,匹配碼是調(diào)用addURI()方法傳入的第三個參數(shù),假設(shè)匹配content://com.jbridge.provider.personprovider/person路徑,返回的匹配碼為1
ContentUris類使用介紹 ContentUris類用于獲取Uri路徑后面的ID部分,它有兩個比較實(shí)用的方法: withAppendedId(uri, id)用于為路徑加上ID部分: Uri uri = Uri.parse("content://com.jbridge.provider.personprovider/person") Uri resultUri = ContentUris.withAppendedId(uri, 10);? //生成后的Uri為:content://com.jbridge.provider.personprovider/person/10
parseId(uri)方法用于從路徑中獲取ID部分: Uri uri = Uri.parse("content://com.jbridge.provider.personprovider/person/10") long personid = ContentUris.parseId(uri);//獲取的結(jié)果為:10
使用ContentProvider共享數(shù)據(jù) ContentProvider類主要方法的作用: public boolean onCreate() 該方法在ContentProvider創(chuàng)建后就會被調(diào)用, Android在系統(tǒng)啟動時就會創(chuàng)建ContentProvider 。 public Uri insert(Uri uri, ContentValues values) 該方法用于供外部應(yīng)用往ContentProvider添加數(shù)據(jù)。 public int delete(Uri uri, String selection, String[] selectionArgs) 該方法用于供外部應(yīng)用從ContentProvider刪除數(shù)據(jù)。 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 該方法用于供外部應(yīng)用更新ContentProvider中的數(shù)據(jù)。 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 該方法用于供外部應(yīng)用從ContentProvider中獲取數(shù)據(jù)。 public String getType(Uri uri) 該方法用于返回當(dāng)前Url所代表數(shù)據(jù)的MIME類型。如果操作的數(shù)據(jù)屬于集合類型,那么MIME類型字符串應(yīng)該以vnd.android.cursor.dir/開頭,例如:要得到所有person記錄的Uri為content://com.jbridge.provider.personprovider/person,那么返回的MIME類型字符串應(yīng)該為:“vnd.android.cursor.dir/person”。如果要操作的數(shù)據(jù)屬于單一數(shù)據(jù),那么MIME類型字符串應(yīng)該以vnd.android.cursor.item/開頭,例如:得到id為10的person記錄,Uri為content://com.jbridge.provider.personprovider/person/10,那么返回的MIME類型字符串應(yīng)該為:“vnd.android.cursor.item/person”。
使用ContentResolver操作ContentProvider中的數(shù)據(jù) 當(dāng)外部應(yīng)用需要對ContentProvider中的數(shù)據(jù)進(jìn)行添加、刪除、修改和查詢操作時,可以使用ContentResolver 類來完成,要獲取ContentResolver 對象,可以使用Activity提供的getContentResolver()方法。 ContentResolver 類提供了與ContentProvider類相同簽名的四個方法: public Uri insert(Uri uri, ContentValues values) 該方法用于往ContentProvider添加數(shù)據(jù)。 public int delete(Uri uri, String selection, String[] selectionArgs) 該方法用于從ContentProvider刪除數(shù)據(jù)。 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 該方法用于更新ContentProvider中的數(shù)據(jù)。 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 該方法用于從ContentProvider中獲取數(shù)據(jù)。
這些方法的第一個參數(shù)為Uri,代表要操作的是哪個ContentProvider和對其中的什么數(shù)據(jù)進(jìn)行操作,假設(shè)給定的是: Uri.parse(“content://com.jbridge.provider.personprovider/person/10”),那么將會對主機(jī)名為cn.itcast.provider.personprovider的ContentProvider進(jìn)行操作,操作的數(shù)據(jù)為person表中id為10的記錄。
使用ContentResolver操作ContentProvider中的數(shù)據(jù) 使用ContentResolver對ContentProvider中的數(shù)據(jù)進(jìn)行添加、刪除、修改和查詢操作: ContentResolver resolver = ?getContentResolver(); Uri uri = Uri.parse("content://com.jbridge.provider.personprovider/person"); //添加一條記錄 ContentValues values = new ContentValues(); values.put("name", "itcast"); values.put("age", 25); resolver.insert(uri, values); //獲取person表中所有記錄 Cursor cursor = resolver.query(uri, null, null, null, "personid desc"); while(cursor.moveToNext()){ Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1)); } //把id為1的記錄的name字段值更改新為liming ContentValues updateValues = new ContentValues(); updateValues.put("name", "liming"); Uri updateIdUri = ContentUris.withAppendedId(uri, 2); resolver.update(updateIdUri, updateValues, null, null); //刪除id為2的記錄 Uri deleteIdUri = ContentUris.withAppendedId(uri, 2); resolver.delete(deleteIdUri, null, null);
ContentProvider示例程序
?我們?yōu)椤禔ndroid之SQlite存儲》示例程序添加一個ContentProvider,供其他應(yīng)用來訪問我們的數(shù)據(jù)。
?
?1.為SQLite示例程序添加ContentProvider類
Java代碼??
package?com.jbridge.db;????import?com.jbridge.service.DataBaseOpenHelper;????import?android.content.ContentProvider;??import?android.content.ContentUris;??import?android.content.ContentValues;??import?android.content.UriMatcher;??import?android.database.Cursor;??import?android.database.sqlite.SQLiteDatabase;??import?android.net.Uri;??import?android.text.TextUtils;????public?class?PersonContentProvider?extends?ContentProvider?{??????private?DataBaseOpenHelper?dbOpenHelper;??????private?static?final?int?ALLPERSON?=?1;??????private?static?final?int?PERSON?=?2;??????private?static?final?UriMatcher?sMatcher?=?new?UriMatcher(??????????????UriMatcher.NO_MATCH);??????static?{??????????sMatcher.addURI("com.jbridge.provider.personprovider",?"person",??????????????????ALLPERSON);??????????sMatcher.addURI("com.jbridge.provider.personprovider",?"person/#",??????????????????PERSON);??????}????????@Override??????public?int?delete(Uri?uri,?String?selection,?String[]?selectionArgs)?{??????????SQLiteDatabase?db?=?dbOpenHelper.getWritableDatabase();??????????int?count?=?0;??????????switch?(sMatcher.match(uri))?{??????????case?ALLPERSON://?com.jbridge.provider.personprovider/person??????????????count=db.delete("person",?selection,selectionArgs);??????????????break;??????????case?PERSON://?com.jbridge.provider.personprovider/person/10??????????????long?personid=ContentUris.parseId(uri);??????????????//防止他輸入時String?selection,?String[]?selectionArgs參數(shù)為空,這樣就會修改表的所有數(shù)據(jù)了??????????????String?where=TextUtils.isEmpty(selection)?"personid=?":selection+"?and?personid=?";??????????????String[]?params=new?String[]{String.valueOf(personid)};???????????????if?(!TextUtils.isEmpty(selection)&&selectionArgs!=null)?{??????????????????params=new?String[selectionArgs.length+1];??????????????????for?(int?i=0;i<selectionArgs.length;i++)?{??????????????????????params[i]=selectionArgs[i];??????????????????}??????????????????params[selectionArgs.length]=String.valueOf(personid);??????????????}??????????????count?=?db.delete("person",?where,params);??????????????break;??????????default:??????????????throw?new?IllegalArgumentException("Unknow?Uri:"?+?uri);????????????}????????????????????return?count;??????}????????@Override??????public?String?getType(Uri?uri)?{??????????switch?(sMatcher.match(uri))?{??????????case?ALLPERSON://?//數(shù)據(jù)集的MIME類型字符串則應(yīng)該以vnd.android.cursor.dir/開頭??????????????return?"vnd.android.cursor.dir/personprovider.person";??????????case?PERSON://單一數(shù)據(jù)的MIME類型字符串應(yīng)該以vnd.android.cursor.item/開頭??????????????return?"vnd.android.cursor.item/personprovider.person";??????????default:??????????????throw?new?IllegalArgumentException("Unknow?Uri:"?+?uri);??????????}??????}????????@Override??????public?Uri?insert(Uri?uri,?ContentValues?values)?{??????????SQLiteDatabase?db?=?dbOpenHelper.getWritableDatabase();??????????long?id?=?0;??????????switch?(sMatcher.match(uri))?{??????????case?ALLPERSON://?com.jbridge.provider.personprovider/person??????????????id?=?db.insert("person",?"name",?values);//?返回值是記錄的行號,主鍵為int實(shí)際上就是主鍵值,主鍵為text則為行號??????????????return?ContentUris.withAppendedId(uri,?id);??????????case?PERSON://?com.jbridge.provider.personprovider/person/10??????????????id?=?db.insert("person",?"name",?values);//?返回值是記錄的行號,主鍵為int實(shí)際上就是主鍵值,主鍵為text則為行號??????????????String?path?=?uri.toString();??????????????return?Uri.parse(path.substring(0,?path.lastIndexOf("/"))?+?id);??????????default:??????????????throw?new?IllegalArgumentException("Unknow?Uri:"?+?uri);??????????}??????}????????@Override??????public?boolean?onCreate()?{??????????dbOpenHelper=new?DataBaseOpenHelper(this.getContext());??????????return?false;??????}????????@Override??????public?Cursor?query(Uri?uri,?String[]?projection,?String?selection,?String[]?selectionArgs,??????????????String?sortOrder)?{??????????SQLiteDatabase?db?=?dbOpenHelper.getWritableDatabase();??????????switch?(sMatcher.match(uri))?{??????????case?ALLPERSON://?com.jbridge.provider.personprovider/person??????????????return?db.query("person",projection,?selection,?selectionArgs,null,?null,?sortOrder);??????????case?PERSON://?com.jbridge.provider.personprovider/person/10??????????????long?personid=ContentUris.parseId(uri);??????????????//防止他輸入時String?selection,?String[]?selectionArgs參數(shù)為空,這樣就會修改表的所有數(shù)據(jù)了??????????????String?where=TextUtils.isEmpty(selection)?"personid=?":selection+"?and?personid=?";??????????????String[]?params=new?String[]{String.valueOf(personid)};???????????????if?(!TextUtils.isEmpty(selection)&&selectionArgs!=null)?{??????????????????params=new?String[selectionArgs.length+1];??????????????????for?(int?i=0;i<selectionArgs.length;i++)?{??????????????????????params[i]=selectionArgs[i];??????????????????}??????????????????params[selectionArgs.length]=String.valueOf(personid);??????????????}??????????????return?db.query("person",projection,?where,?params,null,?null,?sortOrder);????????????default:??????????????throw?new?IllegalArgumentException("Unknow?Uri:"?+?uri);????????????}??????????????????????????}????????@Override??????//返回值為影響的記錄數(shù)??????public?int?update(Uri?uri,?ContentValues?values,?String?selection,?String[]?selectionArgs)?{??????????SQLiteDatabase?db?=?dbOpenHelper.getWritableDatabase();??????????int?count?=?0;??????????switch?(sMatcher.match(uri))?{??????????case?ALLPERSON://?com.jbridge.provider.personprovider/person??????????????count?=?db.update("person",?values,?selection,selectionArgs);??????????????break;??????????case?PERSON://?com.jbridge.provider.personprovider/person/10??????????????long?personid=ContentUris.parseId(uri);??????????????//防止他輸入時String?selection,?String[]?selectionArgs參數(shù)為空,這樣就會修改表的所有數(shù)據(jù)了??????????????String?where=TextUtils.isEmpty(selection)?"personid=?":selection+"?and?personid=?";??????????????String[]?params=new?String[]{String.valueOf(personid)};???????????????if?(!TextUtils.isEmpty(selection)&&selectionArgs!=null)?{??????????????????params=new?String[selectionArgs.length+1];??????????????????for?(int?i=0;i<selectionArgs.length;i++)?{??????????????????????params[i]=selectionArgs[i];??????????????????}??????????????????params[selectionArgs.length]=String.valueOf(personid);??????????????}??????????????count?=?db.update("person",?values,?where,params);??????????????break;??????????default:??????????????throw?new?IllegalArgumentException("Unknow?Uri:"?+?uri);????????????}????????????????????return?count;??????}????}?? ?
???????2.添加ContentProvider配置
| ?<provider android:name=".PersonContentProvider" android:authorities="com.jbridge.provider.personprovider" ?android:permission="android.permission.READ_PERSON_DB"/> ?? |
???????3.測試SQLite示例程序的ContentProvider,建立項目contentProviderUser
?
?? ? ??Project name:?contentProviderUser
???????BuildTarget:Android2.2
???????Application name:?內(nèi)容使用者
???????Package name:?com.jbridge.user
???????Create Activity:?ContentProviderUserActivity
???????Min SDK Version:8
?
?? ??
Java代碼??
package?com.jbridge.user;????import?android.R.string;??import?android.app.Activity;??import?android.content.ContentResolver;??import?android.content.ContentValues;??import?android.database.Cursor;??import?android.net.Uri;??import?android.os.Bundle;??import?android.provider.ContactsContract;??import?android.util.Log;????public?class?ContentProviderUserActivity?extends?Activity?{??????private?static?final??String?TAG="ContentProviderUserActivity";??/*????@Override??//向數(shù)據(jù)庫插入數(shù)據(jù)?????public?void?onCreate(Bundle?savedInstanceState)?{?????????super.onCreate(savedInstanceState);?????????setContentView(R.layout.main);?????????ContentResolver?contentResolver=this.getContentResolver();?????????Uri?uri=Uri.parse("content://com.jbridge.provider.personprovider/person");?????????ContentValues?values=new?ContentValues();?????????values.put("name",?"劉德華");?????????values.put("age",(short)55);?????????contentResolver.insert(uri,?values);?????}*/???????????/*?@Override??????//向數(shù)據(jù)庫修改數(shù)據(jù)?????public?void?onCreate(Bundle?savedInstanceState)?{?????????super.onCreate(savedInstanceState);?????????setContentView(R.layout.main);?????????ContentResolver?contentResolver=this.getContentResolver();?????????Uri?uri=Uri.parse("content://com.jbridge.provider.personprovider/person/4");?????????ContentValues?values=new?ContentValues();?????????values.put("name",?"haha");?????????values.put("age",(short)55);?????????contentResolver.update(uri,?values,?null,?null);?????}*/?????????????/*@Override????????//向數(shù)據(jù)庫刪除數(shù)據(jù)?????????public?void?onCreate(Bundle?savedInstanceState)?{?????????????super.onCreate(savedInstanceState);?????????????setContentView(R.layout.main);?????????????ContentResolver?contentResolver=this.getContentResolver();?????????????Uri?uri=Uri.parse("content://com.jbridge.provider.personprovider/person");?????????????contentResolver.delete(uri,?"personid>?",new?String[]{String.valueOf(18)}?);?//??????????contentResolver.delete(uri,null,null?);?????????}*/????????????/*@Override??????//向數(shù)據(jù)庫查詢數(shù)據(jù)?????public?void?onCreate(Bundle?savedInstanceState)?{?????????super.onCreate(savedInstanceState);?????????setContentView(R.layout.main);?????????ContentResolver?contentResolver=this.getContentResolver();?????????Uri?uri=Uri.parse("content://com.jbridge.provider.personprovider/person");??????Cursor?cursor=contentResolver.query(uri,?new?String[]{"personid","name","age"},?null,?null,?"personid?desc");?????while?(cursor.moveToNext())?{?????????Log.i(TAG,?"personid??"+cursor.getInt(0));?????}?????cursor.close();?????}*/??????????????????@Override???????//向電話本取得數(shù)據(jù)?????public?void?onCreate(Bundle?savedInstanceState)?{?????????super.onCreate(savedInstanceState);?????????setContentView(R.layout.main);?????????ContentResolver?contentResolver=this.getContentResolver();??????????????Cursor?cursor=contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null,?null,?null,?null);?????while?(cursor.moveToNext())?{??????int?contactID=cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));??????String?name=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));??????Log.i(TAG,?"contactid="+contactID+",name="+name);??????Cursor?phones=contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,?null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+contactID,null,?null);??????StringBuilder?sb=new?StringBuilder();??????while?(phones.moveToNext())?{??????????String?phoneNumber=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));??????????sb.append(phoneNumber).append(",");??????}??????sb.deleteCharAt(sb.lastIndexOf(","));??????phones.close();??????Log.i(TAG,?sb.toString());?????????????Cursor?emails?=?getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,???????????????null,???????????????ContactsContract.CommonDataKinds.Email.CONTACT_ID?+?"?=?"?+?contactID,???????????????null,?null);???????????????while?(emails.moveToNext())?{????????????????//?This?would?allow?you?get?several?email?addresses????????????????String?emailAddress?=?emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));??????????????Log.i(TAG,?"emailAddress="+?emailAddress);?????????????}???????????????emails.close();????????????cursor.close();??????}????????????}????????}?? ? 在AndroidManifest.xml中添加 Xml代碼??
<uses-permission?android:name="android.permission.READ_CONTACTS"/>?????<uses-permission?android:name="android.permission.READ_PERSON_DB"/>?? ?
- db.rar?(71 KB)
- 下載次數(shù): 147
- contentProviderUser.rar?(40.8 KB)
- 下載次數(shù): 158
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的Android 内容提供者(Content provider)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。