原文地址:http://justsee.iteye.com/blog/936612
當應用繼承ContentProvider類,并重寫該類用于提供數據和存儲數據的方法,就可以向其他應用共享其數據。雖然使用其他方法也可以對外共享數據,但數據訪問方式會因數據存儲的方式而不同,如:采用文件方式對外共享數據,需要進行文件操作讀寫數據;采用sharedpreferences共享數據,需要使用sharedpreferences API讀寫數據。而使用ContentProvider共享數據的好處是統一了數據訪問方式。
當應用需要通過ContentProvider對外共享數據時,第一步需要繼承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進行配置,為了能讓其他應用找到該ContentProvider , ContentProvider 采用了authorities(主機名/域名)對它進行唯一標識,你可以把 ContentProvider看作是一個網站(想想,網站也是提供數據者),authorities 就是他的域名:
<manifest .... >
?? ?<application android:icon="@drawable/icon" android:label="@string/app_name">
?? ? ? ?<provider android:name=".PersonContentProvider" android:authorities="com.jbridge.provider.personprovider"/>
?? ?</application>
</manifest>
注意:一旦應用繼承了ContentProvider類,后面我們就會把這個應用稱為ContentProvider(內容提供者)。
Uri介紹
Uri代表了要操作的數據,Uri主要包含了兩部分信息:1》需要操作的ContentProvider ,2》對ContentProvider中的什么數據進行操作,一個Uri由以下幾部分組成:
?ContentProvider(內容提供者)的scheme已經由Android所規定, scheme為:content:// 主機名(或叫Authority)用于唯一標識這個ContentProvider,外部調用者可以根據這個標識來找到它。 路徑(path)可以用來表示我們要操作的數據,路徑的構建應根據業務而定,如下: 要操作person表中id為10的記錄,可以構建這樣的路徑:/person/10 要操作person表中id為10的記錄的name字段, person/10/name 要操作person表中的所有記錄,可以構建這樣的路徑:/person 要操作xxx表中的記錄,可以構建這樣的路徑:/xxx 當然要操作的數據不一定來自數據庫,也可以是文件等他存儲方式,如下: 要操作xml文件中person節點下的name節點,可以構建這樣的路徑:/person/name 如果要把一個字符串轉換成Uri,可以使用Uri類中的parse()方法,如下: Uri uri = Uri.parse("content://com.jbridge.provider.personprovider/person")
UriMatcher類使用介紹 因為Uri代表了要操作的數據,所以我們很經常需要解析Uri,并從Uri中獲取數據。Android系統提供了兩個用于操作Uri的工具類,分別為UriMatcher 和ContentUris 。掌握它們的使用,會便于我們的開發工作。 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進行匹配,如果匹配就返回匹配碼,匹配碼是調用addURI()方法傳入的第三個參數,假設匹配content://com.jbridge.provider.personprovider/person路徑,返回的匹配碼為1
ContentUris類使用介紹 ContentUris類用于獲取Uri路徑后面的ID部分,它有兩個比較實用的方法: 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);//獲取的結果為:10
使用ContentProvider共享數據 ContentProvider類主要方法的作用: public boolean onCreate() 該方法在ContentProvider創建后就會被調用, Android在系統啟動時就會創建ContentProvider 。 public Uri insert(Uri uri, ContentValues values) 該方法用于供外部應用往ContentProvider添加數據。 public int delete(Uri uri, String selection, String[] selectionArgs) 該方法用于供外部應用從ContentProvider刪除數據。 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 該方法用于供外部應用更新ContentProvider中的數據。 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 該方法用于供外部應用從ContentProvider中獲取數據。 public String getType(Uri uri) 該方法用于返回當前Url所代表數據的MIME類型。如果操作的數據屬于集合類型,那么MIME類型字符串應該以vnd.android.cursor.dir/開頭,例如:要得到所有person記錄的Uri為content://com.jbridge.provider.personprovider/person,那么返回的MIME類型字符串應該為:“vnd.android.cursor.dir/person”。如果要操作的數據屬于單一數據,那么MIME類型字符串應該以vnd.android.cursor.item/開頭,例如:得到id為10的person記錄,Uri為content://com.jbridge.provider.personprovider/person/10,那么返回的MIME類型字符串應該為:“vnd.android.cursor.item/person”。
使用ContentResolver操作ContentProvider中的數據 當外部應用需要對ContentProvider中的數據進行添加、刪除、修改和查詢操作時,可以使用ContentResolver 類來完成,要獲取ContentResolver 對象,可以使用Activity提供的getContentResolver()方法。 ContentResolver 類提供了與ContentProvider類相同簽名的四個方法: public Uri insert(Uri uri, ContentValues values) 該方法用于往ContentProvider添加數據。 public int delete(Uri uri, String selection, String[] selectionArgs) 該方法用于從ContentProvider刪除數據。 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 該方法用于更新ContentProvider中的數據。 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 該方法用于從ContentProvider中獲取數據。
這些方法的第一個參數為Uri,代表要操作的是哪個ContentProvider和對其中的什么數據進行操作,假設給定的是: Uri.parse(“content://com.jbridge.provider.personprovider/person/10”),那么將會對主機名為cn.itcast.provider.personprovider的ContentProvider進行操作,操作的數據為person表中id為10的記錄。
使用ContentResolver操作ContentProvider中的數據 使用ContentResolver對ContentProvider中的數據進行添加、刪除、修改和查詢操作: 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示例程序
?我們為《Android之SQlite存儲》示例程序添加一個ContentProvider,供其他應用來訪問我們的數據。
?
?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參數為空,這樣就會修改表的所有數據了??????????????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://?//數據集的MIME類型字符串則應該以vnd.android.cursor.dir/開頭??????????????return?"vnd.android.cursor.dir/personprovider.person";??????????case?PERSON://單一數據的MIME類型字符串應該以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實際上就是主鍵值,主鍵為text則為行號??????????????return?ContentUris.withAppendedId(uri,?id);??????????case?PERSON://?com.jbridge.provider.personprovider/person/10??????????????id?=?db.insert("person",?"name",?values);//?返回值是記錄的行號,主鍵為int實際上就是主鍵值,主鍵為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參數為空,這樣就會修改表的所有數據了??????????????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??????//返回值為影響的記錄數??????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參數為空,這樣就會修改表的所有數據了??????????????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:?內容使用者
???????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??//向數據庫插入數據?????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??????//向數據庫修改數據?????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????????//向數據庫刪除數據?????????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??????//向數據庫查詢數據?????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???????//向電話本取得數據?????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"/>?? ?
- contentProviderUser.rar?(40.8 KB)
- 下載次數: 158
與50位技術專家面對面20年技術見證,附贈技術全景圖
總結
以上是生活随笔為你收集整理的Android 内容提供者(Content provider)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。