Android ContentProvider学习

来源:互联网 发布:汤灿到底怎么了知乎 编辑:程序博客网 时间:2024/06/08 17:42

Android中,我们的应用有的时候需要对外提供数据接口,可以有如下几种方法:1AIDL 2Broadcast 3ContentProvider
   
 使用AIDL需要我们编写AIDL接口以及实现,而且对方也要有相应的接口描述,有点麻烦;

使用Broadcast,我们不需要任何接口描述,只要协议文档就可以了,但是这种方式不直接而且是异步的;

使用ContentProvider我们不需要接口描述,只需要知道协议,同时这种方式是同步的,使用方便。下面是ContentProvider简单介绍:

Android中的Contentprovider机制可支持在多个应用中存储和读取数据。这也是跨应用共享数据的唯一方式。在android系统中,没有一个公共的内存区域,供多个应用共享存储数据。

ContentProvider介绍:

Android有一个独特之处就是,数据库只能被它的创建者所使用,其他的应用是不能访问的,所以如果想实现不同应用之间的数据共享,就不得不用content provider了。

 Android ContentProvider数据对外的接口,只需通过使用ContentProvider访问数据而不需要关心数据具体的存储及访问过程,这样既提高了数据的访问效率,同时也保护了数据。Activity类中有一个继承自ContentWappergetContentResolver()无参数方法,该方法返回一个ContentResolver对象,通过调用其queryinsertupdatedelete方法访问数据。这几个方法的第一个参数均为URI,用来标识资源。

通常,一个应用程序可以创建自己的数据,这个数据对该应用程序来说是私有的,外界根本看不到,也不知道数据是如何存储的,是使用数据库还是使用文件,或是通过网上获得,这些一切都不重要,重要的是外界可以通过ContentProvider这一套标准及统一的接口和这个程序里的数据打交道,例 如:添加(insert)、删除(delete)、查询(query)、修改(update)
    Android
为我们提供了ContentProvider来实现数据的共享,一个程序如果想让别的程序可以操作自己的数据,就定义自己的 ContentProvider,然后在AndroidManifest.xml中注册,其他application可以通过获取ContentResolver通过Uri来操作上一程序的数据。

android自身也提供了几个现成的content providerContacts Browser,CallLog,Settings,MediaStore可在android.provider包下面找到一些android提供的Contentprovider。可以查询它们包含的数据,当然前提是已获得适当的读取权限。

 

总的来说:
1
ContentProvider为存储和读取数据提供了统一的接口
2
、使用ContentProvider,应用程序可以实现数据共享
3
android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)

Uri介绍:

1、每一个ContentProvider都拥有一个公共的Uri,这个Uri用于表示这个ContentProvider提供的数据
    2
Android所提供的ContentProvider都存放在andriod.provider这个包里面

AndroidContentProvider URI有固定的形式:content://contract/people

 

标准前缀固定为content : //

URI标识它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在元素的authorities属性中说明:一般是定义该ContentProvider的包.类的名称(主机名/Authority

路径people 具体的资源类型

路径的构建应根据业务而定,如下:
要操作person表中id10的记录,可以构建这样的路径:/person/10
要操作person表中id10的记录的name字段, person/10/name
要操作person表中的所有记录,可以构建这样的路径:/person
要操作xxx表中的记录,可以构建这样的路径:/xxx

当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")

 

Android中广泛应用URI,而不是URLURL标识资源的物理位置,相当于文件的路径;而URI则是标识资源的逻辑位置,并不提供资源的具体位置。比如说电话薄中的数据,如果用URL来标识的话,可能会是一个很复杂的文件结构,而且一旦文件的存储路径改变,URL也必须得改动。但是若是URI,则可以用诸如content://contract/people这样容易记录的逻辑地址来标识,而且并不需要关心文件的具体位置,即使文件位置改动也不需要做变化,当然这都是对于用户来说,后台程序中URI到具体位置的映射还是需要程序员来改动的。

UriMatcher类使用介绍

因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcherContentUris 。掌握它们的使用,会便于我们的开发工作。
    UriMatcher
类用于匹配Uri,它的用法如下:
   
 首先第一步把你需要匹配Uri路径全部给注册上,如下:

//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.ljq.provider.personprovider/person路径,返回匹配码为1
sMatcher.addURI("com.ljq.provider.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码
//
如果match()方法匹配content://com.ljq.provider.personprovider/person/230路径,返回匹配码为2
sMatcher.addURI("com.ljq.provider.personprovider", "person/#", 2);//#号为通配符
switch (sMatcher.match(Uri.parse("content://com.ljq.provider.personprovider/person/10"))) {
  
 case 1
    
 break;
  
 case 2
    
 break;
  
 default://不匹配
     break;
}

注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.ljq.provider.personprovider/person路径,返回的匹配码为

              

ContentUris类使用介绍

ContentUris类用于操作Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)
用于为路径加上ID部分:

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

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

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

 

创建ContentProvider共享应用程序中的数据

实现ContentProvider的过程:(创建)

1、定义一个COTENT_URI常量
2
、定义一个类,继承ContentProvider
3
、实现query(),delete(),update(),insert(),onCreate(),getType()方法

public class PersonContentProvider extends ContentProvider{
  
 public boolean onCreate() //ContentProvider创建后就会被调用
  
 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)// 用于供外部应用更新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记录的Uricontent://com.ljq.provider.personprovider/person,那么返回的MIME类型字符串应该为:"vnd.android.cursor.dir/person"

如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,

例如:得到id10person记录,Uricontent://com.ljq.provider.personprovider/person/10,那么返回的MIME类型字符串为:"vnd.android.cursor.item/person"

 

 

4、在AndroidMainfest.xml中申明,ContentProvider采用了authorities(主机名/域名)对它进行唯一标识,你可以把ContentProvider看作是一个网站

<</SPAN>manifest.... >
  
 <</SPAN>application android:icon="@drawable/icon" android:label="@string/app_name">
     
 <</SPAN>provider android:name=".PersonContentProvider" 
           android:authorities
="com.ljq.providers.personprovider"/>
  
 </</SPAN>application>
</</SPAN>manifest>

 

   如果想创建自己的contentprovider,最好把自定义的URI设置为类的常量,这样简化别人的调用,并且以后如果更新URI也很容易。

 

使用已经提供ContentProvider的应用程序中的数据:

应用可以通过一个唯一的ContentResolver interface使用具体的某个content provider   

ContentResolver cr getContentResolver();  

然后就可以用ContentResolver提供的方法来使用需要的content provider了。其中contentResolver提供的方法包括query(),insert(),update()等。ContentResolver实例带的方法可实现找到指定的Contentprovider并获取到Contentprovider的数据。   

contentprovider的用户都不可能直接访问到contentprovider实例,只能通过ContentResolver在中间代理。Contentprovider返回的数据结构,是类似JDBCResultSet,在android中,Cursor对象

 

ContentProvider负责

组织应用程序的数据;

向其他应用程序提供数据;

ContentResolver则负责

获取ContentProvider提供的数据;

修改/添加/删除更新数据等;

一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据完全暴露出去,而且ContentProviders是以类似数据库中表的方式将数据暴露

ContentProvider应该是Android在系统启动时就创建了,否则就谈不上数据共享了。 这就要求在AndroidManifest.XML中使用元素明确定义。

0 0
原创粉丝点击