Android学习19--使用ContentProvider实现数据共享

1、数据共享标准:ContentProvider简介

ContentProvider是不同应用程序之间进行数据交换的标准API,ContentProvider以某种Uri的形式对外提供数据,允许其他应用访问或修改数据:其它应用程序使用ContentResolver根据Uri去访问操作指定数据。

ContentProvider也是Android应用的四大组件之一,与Activity、Service、BroadcastReceiver相似,它们都需要在AndroidManifest.xml文件中进行配置。

(1)开发一个ContentProvider的步骤:

a、定义自己的ContentProvider类,该类需要继承Android提供的ContentProvider基类。

b、在AndroidManifest.xml文件中注册这个ContentProvider,就像注册Activity一样,注册ContentProvider时需要为它绑定一个域名。向Android系统中注册ContentProvider只要在元素下添加如下子元素:

//其中name属性指定ContentProvider类,authorities就相当于为该ContentProvider指定域名。

当我们想Android系统注册了ContentProvider之后,其它应用程序就可通过该Uri来访问DictProvider所暴露的数据了

那么DictProvider如何暴露它所提供的数据呢?其实很简单,应用程序对数据的操作无非就是CRUD操作,因此DictProvider除了需要继承ContentProvider之外,还需要提供如下几个方法:

a、public boolean onCreate():该方法在ContentProvider创建后会被调用,当其它应用程序第一次访问ContentProvider时,该ContentProvider会被创建出来,并立即回调该onCreate()方法。

b、public Uri  insert(Uri uri,ContentValues  values):根据Uri插入values对应的数据。

c、public int delete(Uri uri,String selection,String[ ]  selectionArgs):根据Uri删除select条件所匹配的全部记录。

d、public int  update(Uri uri,ContentValues  values,String selection,String[ ] selectionArgs):根据Uri修改select条件所匹配的全部记录。

e、public Cursor query(Uri uri,String[ ]  projection,String selection,String[ ] selectionArgs,String sortOrder):根据Uri查询出select条件所匹配的全部记录,其中projection就是一个列名列表,表明只选择出指定的数据列。

f、public  String getType(Uri uri):用于返回当前Uri所代表的数据的MIME类型。如果该Uri对应数据可能包含多条记录,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,如果该Uri对应的数据只包含一条记录,那么返回MIME类型字符串应该以vnd.android.cursor.item/开头。

(2)Uri简介

示例Uri:content://org.lxj.provider.dictprovider/words,它可以分为三部分:

content://:这个部分是Android所规定的,是固定的。

org.lxj.provider.dictprovider:这个部分就是ContentProvider的authorities。系统就是由这个部分来找到操作哪个ContentProvider。只要访问固定的ContentProvider,这个部分总是固定的。

words:资源部分(或者说数据部分),当访问者需要访问不同资源时,这个部分是动态改变的。

为了将一个字符串转换为Uri,Android提供的Uri工具提供了parse()静态方法,示例代码如下:

Uri uri=Uri.parse(”content://org.lxj.provider.dictprovider/words“)

(3)使用ContentResolver操作数据

Context提供如下方法来获取ContentResolver对象

getContentResolver(),一旦在程序中获得ContentResolver对象之后,接下来就可以调用ContentResolver的如下方法来操作数据:

insert(Uri uri,ContentValues  values):根据Uri插入values对应的数据。

delete(Uri uri,String selection,String[ ]  selectionArgs):根据Uri删除select条件所匹配的全部记录。

update(Uri uri,ContentValues  values,String selection,String[ ] selectionArgs):根据Uri修改select条件所匹配的全部记录。

query(Uri uri,String[ ]  projection,String selection,String[ ] selectionArgs,String sortOrder):根据Uri查询出select条件所匹配的全部记录,其中projection就是一个列名列表,表明只选择出指定的数据列。

2、使用ContentProvider管理联系人

Android系统提供了Contacts应用程序来管理联系人,而且Android系统还为联系人管理提供了ContentProvider,这就允许其它应用程序以ContentResolver来管理联系人数据。

Android系统对联系人管理Contentprovider的几个Uri如下:

ContactsContacts.Contacts.CONTENT_URI:管理联系人的Uri。

ContactsContacts.CommonDataKinds.Phone.CONTENT_URI:管理联系人的电话的Uri

ContactsContacts.CommonDataKinds.Email.CONTENT_URI:管理联系人的Email的Uri

知道联系人管理ContentProvider的Uri之后,接下来就可以在应用程序中通过ContentResolver去操作系统的联系人数据了

3、使用ContentProvider管理多媒体内容

Android为多媒体提供的ContentProvider的Uri如下:

MediaStore.Audio.Media.EXTERNAL_CONTENT_URI:存储在外部存储器(SD卡)上的音频文件内容的ContentProvider的Uri。

MediaStore.Audio.Media.INTERNAL_CONTENT_URI:存储在手机内部存储器上的音频文件内容的ContentProvider的Uri。

MediaStore.Images.Media.EXTERNAL_CONTENT_URI:存储在外部存储器(SD卡)上的图片文件内容的ContentProvider的Uri。

MediaStore.Images.Media.INTERNAL_CONTENT_URI:存储在手机内部存储器上的图片文件内容的ContentProvider的Uri。

MediaStore.Video.Media.EXTERNAL_CONTENT_URI:存储在外部存储器(SD卡)上的视频文件内容的ContentProvider的Uri。

MediaStore.Video.Media.INTERNAL_CONTENT_URI:存储在手机内部存储器上的视频文件内容的ContentProvider的Uri。

4、实现ContentProvider

上面介绍的是如何使用ContentResolver来操作系统ContentProvider提供的数据,下面将开始介绍如何开发自己的ContentProvider。

前面已经介绍了开发ContentProvider的两步:

a、定义自己的ContentProvider类,该类需要继承Android提供的ContentProvider基类,并实现增、删、改、查等方法。

b、在AndroidManifest.xml文件中注册这个ContentProvider

开发ContentProvider时所实现的增、删、改、查方法都需要一个Uri参数,该参数决定了对哪个Uri执行数据操作。

为了确定该ContentProvider实际能匹配的Uri,以及确定每个方法中Uri参数所操作的数据,Android提供了UriMatcher工具类。UriMatcher工具类主要提供了如下两个方法:

void addURI(String authority,String path,int code):向UriMatcher对象注册Uri,其中authority和path组合成一个Uri,而code则代表该Uri对应的标识码。

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

例如我们先通过如下代码创建UriMatcher对象:

UriMatcher matcher=new  UriMatcher(UriMatcher.NO_MATCH);

matcher.addURI(”org.lxj.provider.dictprovider“,”words“,1);

matcher.addURI(”org.lxj.provider.dictprovider“,”word/#“,2);

上面创建的UriMatcher对象注册了两个Uri,其中org.lxj.provider.dictprovider/words对应的标识码是1,org.lxj.provider.dictprovider/word/#对应的标识码是2,其中#为通配符

这就意味着如下匹配结果:

matcher.match(Uri.parse(”org.lxj.provider.dictprovider/words“));       返回标识码1

matcher.match(Uri.parse(”org.lxj.provider.dictprovider/word/2“));       返回标识码2

matcher.match(Uri.parse(”org.lxj.provider.dictprovider/word/10“));       返回标识码2

至于到底需要为UriMatcher对象注册多少个Uri,这取决于系统的业务需求。

除此之外,Android还提供了一个ContentUris工具类,这是一个操作Uri字符串的工具类,它提供了如下两个工具方法:

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

Uri uri=Uri.parse(“org.lxj.provider.dictprovider/word”);

Uri  resultUri=ContentUris.withAppendedId(uri,2);//生成后的Uri为:”org.lxj.provider.dictprovider/word/2“

parseId(uri):用于从指定Uri中解析出所包含的ID值,例如:

Uri uri=Uri.parse(“org.lxj.provider.dictprovider/word/2”);

long  wordId=ContentUris.parseId(uri);//获取的结果为2

5、监听ContentProvider的数据改变

为了在应用程序中监听ContentProvider数据的改变,需要利用Android提供ContentObserver基类。

监听ContentProvider数据改变的监听器需要继承ContentObserver类,并重写该基类所定义的onChange(boolean selfChange)方法--当它所监听的ContentProvider数据发生改变时,该onChange将会被触发。

为了监听指定ContentProvider的数据变化,需要通过ContentResolver向指定Uri注册ContentObserver监听器,ContentResolver提供如下方法来注册监听器:

registerContentObserver(Uri uri,boolean notifyForDescendents,ContentObserver  observer),其中的参数说明:

uri:该监听器所监听的ContentProvider的Uri。

notifyForDescendents:如果该参数设为true,假如注册监听的Uri为content://abc,那么Uri为content://abc/xyz,content://abc/xyz/foo的数据改变时也会触发该监听器。如果为false,监听器只响应content://abc的触 发。

observer:监听器实例



你可能感兴趣的:(android学习笔记)