android ContentProvider

来源:互联网 发布:淘宝购物车放多久 编辑:程序博客网 时间:2024/05/20 17:20

ContentProvider简介:

ContentProvider(数据提供者)是在应用程序间共享数据的一种接口机制

ContentProvider提供了更为高级的数据共享方法,应用程序可以指定需要共享的数据,而其他应用程序则可以在不知数据来源、路径的情况下,对共享数据进行查询、添加、删除和更新等操作

许多Android系统的内置数据也通过ContentProvider提供给用户使用,例如通讯录、音视频文件和图像文件等
在创建ContentProvider时,需要首先使用数据库、文件系统或网络实现底层存储功能,然后在继承ContentProvider的类中实现基本数据操作的接口函数,包括添加、删除、查找和更新等功能

调用者不能够直接调用ContentProvider的接口函数,而需要使用ContentResolver对象,通过URI间接调用ContentProvider。

使用ContentProvider可以在不同的应用程序之间共享数据。 它为存储和获取数据提供了统一的接口。

ContentProvide对数据进行封装,不用关心数据存储的细节。 



Android系统提供了大量的ContentProvider,允许开发者来操作这些contentprovider所暴露的接口。

系统包:http://developer.android.com/intl/zh-cn/reference/android/provider/package-summary.html

联系人管理的Uri:

ContactsContract.Contacts.CONTENT_URI:管理联系人
ContactsContract.CommonDataKinds.Phone.CONTENT_URI:管理联系人的电话
ContactsContract.CommonDataKinds.Email.CONTENT_URI:管理联系人的E-mail.

多媒体内容管理的Uri:

MediaStore.Audio.Media.EXTERNAL_CONTENT_URI:外部存储器上的音频文件
MediaStore.Audio.Media.INTERNAL_CONTENT_URI:内部存储器上的音频文件
MediaStore.Images.Media.EXTERNAL_CONTENT_URI:外部存储器上的图片文件
MediaStore.Images.Media.INTERNAL_CONTENT_URI:内部存储器上的图片文件
MediaStore.Video.Media.EXTERNAL_CONTENT_URI:外部存储器上的视频文件
MediaStore.Video.Media.INTERNAL_CONTENT_URI:内部存储器上的视频文件


URI的简介:

Uri代表了要操作的数据,它为系统的每一个资源给其一个名字,比方说通话记录。每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。


URI的格式 :


A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"

B:URI 的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称; "content://hx.android.text.myprovider",这个部分就是ContentProvider的authority.

C:路径,通俗的讲就是你要操作的数据库中表的名字;"content://hx.android.text.myprovider/tablename"

D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://hx.android.text.myprovider/tablename/#" #表示数据id,动态改变

注意:

路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下: • 要操作contact表中id为10的记录,可以构建这样的路径:/contact/10 • 要操作contact表中id为10的记录的name字段, contact/10/name • 要操作contact表中的所有记录,可以构建这样的路径:/contact

要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下: 要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name

如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下: Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")


工具类:UriMatcher :

为了确定该ContentProvider实际能处理的Uri,以及确定每个方法中Uri参数所操作的数据,Android提供了UriMacher工具类,用法如下:   

1.首先把你需要匹配Uri路径全部给注册上(便于ContentProvider判断具体的操作,一般是确定对单个记录操作还是多个记录操作),如:

uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);

void addUri(String authority,String path,int code):该方法用于向UriMacher对象注册Uri.其中authority和path组合成一个Uri,而code则代表对应的标识码。标识码匹配Uri的类型,需要注册多少个Uri则根据业务需要。

2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码.

//如果match()匹配路径,返回匹配码为1
content://com.changcheng.sqlite.provider.contactprovider/contact
//如果match()匹配路径,返回匹配码为2
content://com.changcheng.sqlite.provider.contactprovider/contact/23

int match(Uri uri):根据前面注册的Uri来判断指定Uri对应的标识码。如果找不到匹配的标识码,该方法将会返回-1。

用来解析来自ContentResolver传递过来的Uri则能知道这个Uri具体操作的类型,由uriMatcher.addURI指定,则根据返回的标识码就知道了要操作的类型(一般是确定对单个记录操作还是多个记录操作)


工具类:ContentUris :

ContentUris类用于操作Uri字符串的工具类,它有两个比较实用的方法:

withAppendedId(uri, id)用于为路径加上ID部分:

Uri uri =Uri.parse("content://cn.itcast.provider.personprovider/person")
Uri resultUri = ContentUris.withAppendedId(uri, 10); 
//生成后的Uri为:content://cn.itcast.provider.personprovider/person/10

parseId(uri)方法用于从路径中获取ID部分:

Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person/10")
long personid = ContentUris.parseId(uri);//获取的结果为:10

ContentProvider的编程方法 :

程序开发人员通过继承ContentProvider类可以创建一个新的数据提供者,过程可以分为三步 :

继承ContentProvider,并重载六个函数

delete():删除数据集,返回被删除的记录条数
insert():添加数据集,返回新插入的记录的Uri
qurey():查询数据集,返回查询得到的Cursor
update():更新数据集,返回被更新的记录条数
onCreate():初始化底层数据集和建立数据连接等工作
getType():返回指定URI的MIME数据类型,
如果URI是单条数据,则返回的MIME数据类型应以vnd.android.cursor.item开头
如果URI是多条数据,则返回的MIME数据类型应以vnd.android.cursor.dir/开头

声明CONTENT_URI,实现UriMatcher

注册ContentProvider

<application android:icon="@drawable/icon" android:label="@string/app_name"><provider android:name = ".PeopleProvider"android:authorities = "edu.hrbeu.peopleprovider"/></application>

属性:

 name:ContentProvider的实现类的类名

    authorities:指定该ContentProvider对应的Uri(域名)

    android:exported:指定该ContentProvider是否允许其他应用调用



ContentResolver的编程方法:

使用ContentProvider是通过Android组件都具有的ContentResolver对象,通过URI进行数据操作

程序开发人员只需要知道URI和数据集的数据格式,则可以进行数据操作,解决不同应用程序之间的数据共享问题

每个Android组件都具有一个ContentResolver对象,获取ContentResolver对象的方法是调用getContentResolver()函数

ContentResolver resolver = getContentResolver();

调用ContentResolver的如下方法:

insert(Uri url,ContentValues values):

delete(Uri url,String where String[] selectionArgs):

update(Uri uri,ContentValues values,String where,String[] selectionArgs):

query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder):


实例代码如下:

ContentProviderDemo:

工具类:(用来暴露给使用者,用作说明文档)

package edu.hrbeu.ContentProviderDemo;import android.net.Uri;public class People{public static final String MIME_DIR_PREFIX = "vnd.android.cursor.dir";public static final String MIME_ITEM_PREFIX = "vnd.android.cursor.item";public static final String MINE_ITEM = "vnd.hrbeu.people";public static final String MINE_TYPE_SINGLE = MIME_ITEM_PREFIX + "/" + MINE_ITEM;public static final String MINE_TYPE_MULTIPLE = MIME_DIR_PREFIX + "/" + MINE_ITEM;public static final String AUTHORITY = "edu.hrbeu.peopleprovider";public static final String PATH_SINGLE = "people/#";public static final String PATH_MULTIPLE = "people";public static final String CONTENT_URI_STRING = "content://" + AUTHORITY + "/" + PATH_MULTIPLE;public static final Uri  CONTENT_URI = Uri.parse(CONTENT_URI_STRING); public static final String KEY_ID = "_id";public static final String KEY_NAME = "name";public static final String KEY_AGE = "age";public static final String KEY_HEIGHT = "height";}


ContentProvider:
package edu.hrbeu.ContentProviderDemo;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.content.Context;import android.content.UriMatcher;import android.database.Cursor;import android.database.SQLException;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import android.database.sqlite.SQLiteQueryBuilder;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.net.Uri;public class PeopleProvider extends ContentProvider{private static final String DB_NAME = "people.db";private static final String DB_TABLE = "peopleinfo";private static final int DB_VERSION = 1;private SQLiteDatabase db;private DBOpenHelper dbOpenHelper;private static final int MULTIPLE_PEOPLE = 1;private static final int SINGLE_PEOPLE = 2;private static final UriMatcher uriMatcher;static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(People.AUTHORITY, People.PATH_MULTIPLE, MULTIPLE_PEOPLE); uriMatcher.addURI(People.AUTHORITY, People.PATH_SINGLE, SINGLE_PEOPLE);}@Overridepublic String getType(Uri uri) {switch(uriMatcher.match(uri)){case MULTIPLE_PEOPLE:return People.MINE_TYPE_MULTIPLE;case SINGLE_PEOPLE:return People.MINE_TYPE_SINGLE;default:throw new IllegalArgumentException("Unkown uri:"+uri);}}@Overridepublic boolean onCreate() {Context context = getContext();dbOpenHelper = new DBOpenHelper(context, DB_NAME, null, DB_VERSION);db = dbOpenHelper.getWritableDatabase();if (db == null)return false;else return true;}@Overridepublic Uri insert(Uri uri, ContentValues values) {long id = db.insert(DB_TABLE, null, values);if ( id > 0 ){Uri newUri = ContentUris.withAppendedId(People.CONTENT_URI, id);getContext().getContentResolver().notifyChange(newUri, null);return newUri;}throw new SQLException("Failed to insert row into " + uri);}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {int count = 0;switch(uriMatcher.match(uri)){case MULTIPLE_PEOPLE:count = db.delete(DB_TABLE, selection, selectionArgs);break;case SINGLE_PEOPLE:String segment = uri.getPathSegments().get(1);count = db.delete(DB_TABLE, People.KEY_ID + "=" + segment, selectionArgs);break;default:throw new IllegalArgumentException("Unsupported URI:" + uri);}getContext().getContentResolver().notifyChange(uri, null);return count;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {SQLiteQueryBuilder qb = new SQLiteQueryBuilder();qb.setTables(DB_TABLE);switch(uriMatcher.match(uri)){case SINGLE_PEOPLE:qb.appendWhere(People.KEY_ID + "=" + uri.getPathSegments().get(1));break;default:break;}Cursor cursor = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);cursor.setNotificationUri(getContext().getContentResolver(), uri);return cursor;}@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {int count;switch(uriMatcher.match(uri)){case MULTIPLE_PEOPLE:count = db.update(DB_TABLE, values, selection, selectionArgs);break;case SINGLE_PEOPLE:String segment = uri.getPathSegments().get(1);count = db.update(DB_TABLE, values, People.KEY_ID+"="+segment, selectionArgs);break;default:throw new IllegalArgumentException("Unknow URI:" + uri);}getContext().getContentResolver().notifyChange(uri, null);return count;}  private static class DBOpenHelper extends SQLiteOpenHelper {  public DBOpenHelper(Context context, String name, CursorFactory factory, int version) {    super(context, name, factory, version);  }  private static final String DB_CREATE = "create table " +     DB_TABLE + " (" + People.KEY_ID + " integer primary key autoincrement, " +    People.KEY_NAME+ " text not null, " + People.KEY_AGE+ " integer," + People.KEY_HEIGHT + " float);";  @Override  public void onCreate(SQLiteDatabase _db) {    _db.execSQL(DB_CREATE);  }  @Override  public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) {        _db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);    onCreate(_db);  }}   }


AndroidManifest.xml:
 <application android:icon="@drawable/icon" android:label="@string/app_name">        <provider android:name = ".PeopleProvider"    android:authorities = "edu.hrbeu.peopleprovider"/>    </application>


ContentResolverDemo:

工具类:

package edu.hrbeu.ContentResolverDemo;import android.net.Uri;public class People{public static final String MIME_DIR_PREFIX = "vnd.android.cursor.dir";public static final String MIME_ITEM_PREFIX = "vnd.android.cursor.item";public static final String MINE_ITEM = "vnd.hrbeu.people";public static final String MINE_TYPE_SINGLE = MIME_ITEM_PREFIX + "/" + MINE_ITEM;public static final String MINE_TYPE_MULTIPLE = MIME_DIR_PREFIX + "/" + MINE_ITEM;public static final String AUTHORITY = "edu.hrbeu.peopleprovider";public static final String PATH_SINGLE = "people/#";public static final String PATH_MULTIPLE = "people";public static final String CONTENT_URI_STRING = "content://" + AUTHORITY + "/" + PATH_MULTIPLE;public static final Uri  CONTENT_URI = Uri.parse(CONTENT_URI_STRING); public static final String KEY_ID = "_id";public static final String KEY_NAME = "name";public static final String KEY_AGE = "age";public static final String KEY_HEIGHT = "height";}


ContentResolver:
package edu.hrbeu.ContentResolverDemo;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.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class ContentResolverDemo extends Activity {private EditText nameText;private EditText ageText;private EditText heightText;private EditText idEntry;private TextView labelView;private TextView displayView;private ContentResolver resolver;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);               nameText = (EditText)findViewById(R.id.name);        ageText = (EditText)findViewById(R.id.age);        heightText = (EditText)findViewById(R.id.height);        idEntry = (EditText)findViewById(R.id.id_entry);                labelView = (TextView)findViewById(R.id.label);        displayView = (TextView)findViewById(R.id.display);                                Button addButton = (Button)findViewById(R.id.add);        Button queryAllButton = (Button)findViewById(R.id.query_all);              Button clearButton = (Button)findViewById(R.id.clear);        Button deleteAllButton = (Button)findViewById(R.id.delete_all);                Button queryButton = (Button)findViewById(R.id.query);        Button deleteButton = (Button)findViewById(R.id.delete);        Button updateButton = (Button)findViewById(R.id.update);                        addButton.setOnClickListener(addButtonListener);         queryAllButton.setOnClickListener(queryAllButtonListener);             clearButton.setOnClickListener(clearButtonListener);        deleteAllButton.setOnClickListener(deleteAllButtonListener);                      queryButton.setOnClickListener(queryButtonListener);        deleteButton.setOnClickListener(deleteButtonListener);        updateButton.setOnClickListener(updateButtonListener);                resolver = this.getContentResolver();               }            OnClickListener addButtonListener = new OnClickListener() {@Overridepublic void onClick(View v) {ContentValues values = new ContentValues();  values.put(People.KEY_NAME, nameText.getText().toString());values.put(People.KEY_AGE, Integer.parseInt(ageText.getText().toString()));values.put(People.KEY_HEIGHT, Float.parseFloat(heightText.getText().toString()));    Uri newUri = resolver.insert(People.CONTENT_URI, values);labelView.setText("添加成功,URI:" + newUri);}    };        OnClickListener queryAllButtonListener = new OnClickListener() {@Overridepublic void onClick(View v) {Cursor cursor = resolver.query(People.CONTENT_URI,new String[] { People.KEY_ID, People.KEY_NAME, People.KEY_AGE, People.KEY_HEIGHT},null, null, null);if (cursor == null){labelView.setText("数据库中没有数据");return;}labelView.setText("数据库:" + String.valueOf(cursor.getCount()) + "条记录");String msg = "";if (cursor.moveToFirst()){do{msg += "ID:" + cursor.getInt(cursor.getColumnIndex(People.KEY_ID)) + ",";msg += "姓名:" + cursor.getString(cursor.getColumnIndex(People.KEY_NAME))+ ",";msg += "年龄:" + cursor.getInt(cursor.getColumnIndex(People.KEY_AGE)) + ", ";msg += "身高:" + cursor.getFloat(cursor.getColumnIndex(People.KEY_HEIGHT)) + "\n";}while(cursor.moveToNext());  }displayView.setText(msg);}    };                OnClickListener clearButtonListener = new OnClickListener() {@Overridepublic void onClick(View v) {displayView.setText("");}    };        OnClickListener deleteAllButtonListener = new OnClickListener() {@Overridepublic void onClick(View v) {resolver.delete(People.CONTENT_URI, null, null);String msg = "数据全部删除" ;labelView.setText(msg);}    };        OnClickListener queryButtonListener = new OnClickListener() {@Override public void onClick(View v) {Uri uri = Uri.parse(People.CONTENT_URI_STRING + "/" + idEntry.getText().toString());Cursor cursor = resolver.query(uri,new String[] { People.KEY_ID, People.KEY_NAME, People.KEY_AGE, People.KEY_HEIGHT},null, null, null);if (cursor == null){labelView.setText("数据库中没有数据");return;}String msg = "";if (cursor.moveToFirst()){msg += "ID:" + cursor.getInt(cursor.getColumnIndex(People.KEY_ID)) + ",";msg += "姓名:" + cursor.getString(cursor.getColumnIndex(People.KEY_NAME))+ ",";msg += "年龄:" + cursor.getInt(cursor.getColumnIndex(People.KEY_AGE)) + ", ";msg += "身高:" + cursor.getFloat(cursor.getColumnIndex(People.KEY_HEIGHT)) + "\n";  }labelView.setText("数据库:");displayView.setText(msg);}    };        OnClickListener deleteButtonListener = new OnClickListener() {@Overridepublic void onClick(View v) {Uri uri = Uri.parse(People.CONTENT_URI_STRING + "/" + idEntry.getText().toString());int result = resolver.delete(uri, null, null);String msg = "删除ID为"+idEntry.getText().toString()+"的数据" + (result>0?"成功":"失败");labelView.setText(msg);}    };        OnClickListener updateButtonListener = new OnClickListener() {@Overridepublic void onClick(View v) {ContentValues values = new ContentValues();  values.put(People.KEY_NAME, nameText.getText().toString());values.put(People.KEY_AGE, Integer.parseInt(ageText.getText().toString()));values.put(People.KEY_HEIGHT, Float.parseFloat(heightText.getText().toString()));    Uri uri = Uri.parse(People.CONTENT_URI_STRING + "/" + idEntry.getText().toString());int result = resolver.update(uri, values, null, null);String msg = "更新ID为"+idEntry.getText().toString()+"的数据" + (result>0?"成功":"失败");labelView.setText(msg);}    };}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 牙颈部楔状缺损怎么办 牙齿磨了很疼怎么办 小孩牙有窟窿疼怎么办 西瓜吃多了尿不停怎么办 吃了个西瓜不停拉肚子怎么办 例假完了又来了怎么办 肾上面有个肿瘤怎么办 膀胱壁毛糙增厚怎么办 痔疮手术后尿不出来怎么办 小牛肚一天不尿怎么办 小孩拉肚一直不好怎么办 尿涨但是尿很少怎么办 十四岁尿血医生说是肾炎怎么办 吃肉反胃想吐怎么办 母牛排尿带血尿发烧怎么办 4岁发烧40度怎么办 狗狗拉肚子咳漱哮喘怎么办 拉肚子拉脱水人无力怎么办 孕中期拉稀拉水怎么办 吃坏肚子拉稀水怎么办 手上起小疙瘩疼怎么办 手上长东西很痛怎么办 七八十斤猪拉稀怎么办 宝宝扁桃体化脓反复发烧怎么办 骑单车后膝盖痛怎么办 孩子一运动就喘怎么办 小孩晚上咳嗽很厉害怎么办 1岁宝宝夜里咳嗽怎么办 咳嗽咳的胸疼怎么办 儿童又咳又喘怎么办 咳嗽咳到胸口痛怎么办 咳嗽咳得肋骨疼怎么办 孕妇咳嗽咳得胸口疼怎么办 怀孕偏左侧宫腔怎么办 晨起活动后咳嗽怎么办 运动后乳房坠痛怎么办 嗓子痒咳嗽怎么办夜间最为难受 小孩鼻炎引起的咳嗽怎么办 跑完800米喉咙痒怎么办 过敏源总ige高怎么办 一岁宝宝咳嗽喘怎么办