Android Content Provider

来源:互联网 发布:淘宝无线链接转化 编辑:程序博客网 时间:2024/06/04 00:59
Android Content Provider

在Android中,你通过Content Provider向其他Application提供数据。
Content Provider 对外提供数据的表现形式非常象操作数据库的接口。有类似的table, cursor, records, fields的概念。但是provider的内部实际的数据不一定要存在数据库中。
如果你要提供一个Content Provider。你要考虑哪些事情?

首先是你的数据是如何组织的。有几个表,有哪些fields,每个field存的都是什么类型的数据?除了这些,Android系统还需要你提供一些信息!这些信息包括
  • URI
  • MIME type
  • permission

URI
URI是你数据的address。所有要通讯的数据必须有个Address, 就像你电脑要上网就必须有个IP address一样。就是别人怎么找到你(的数据)。Android系统怎么找到你的数据,你provider的使用者(content resolver)怎么找到你的数据。就是拿这个你提供的URI作为Address来找到你的数据的。
URI 由 scheme, authority, path这几个部分组成。类似下面这样的形式
scheme://authority/path
对于content provider,scheme始终是content, authority是你向android系统注册的你自己提供的名字,代表了某个provider。path也是你自己提供的名字,代表了某个表,再下面一层可以是代表了某条记录。
所谓向Android系统注册你的provider的authority,就是通过AndroidManifest.xml文件中的provider结点的authorities属性。

MIME type
你要为每个表定义2个MIME type。因为每个表都有自己的URI,也就是说你要为这些你定义的URI定义2个MIME type。一个代表表中单条记录的MIME type,另一个代表表中多条记录的MIME type。
对于单条记录,MIME type应该是:
vnd.android.cursor.item/vnd.com.example.provider.table1
对于多条记录,MIME type应该是:
vnd.android.cursor.dir/vnd.com.example.provider.table1
MIME type中的sub type,应该是 vnd + 包名 + 表名
这个MIME type通过你的provider的getType()函数返回。它有啥作用?按我的理解,他的作用之一是用在 Intent Filter中的data属性中,指定data的type。因为Intent Filter是用来说明component的能力的。这里主要是Activity。也就是说,他可以让Activity在AndroidManifest.xml中向系统说明他可以处理你这个Provider的这个table的多条或单条数据。例如,在Android的sample里面的NotePade程序中各Activity的Intent Filter

permission
关于permission,你应该好好去看一看Implementing Content Provider Permissions这一段
你要决定你的数据受权限保护的粒度。是读写权限在一起,还是读权限,写权限分开。你甚至可以设定path-level的permission。
你通过AndroidMenifest.xml中的permission结点向Android系统注册新的permission的名字
然后在provider结点中通过android:permission, android:readPermission 和 android:writePermission属性,要求访问者必须申请了什么权限,才能访问你的provider。
访问者必须在他的AndroidManifest.xml中通过uses-permission结点来申请获得相应的权限。
另外还有临时权限。是通过provider结点的android:grantUriPermissions属性和<grant-uri-permission> 子结点来设置的。具体也去看文档啦。


关于Contract类
你应该把所有的常量都封装到一个final static的Contract类里面。比如field name, URI, MIME type等等。这样用起来也方便。而且一般你需要通过一个jar文件导出这个Contract给你的使用者。这样你的使用者用起来才方便嘛。


总结一下:
在AndroidManifest.xml文件中你要
同过 <permission> 结点,注册新的permission name
通过 <provider> 结点,注册你的provider。
在<provider> 结点中,
通过 authorities 属性,注册URI中的authority部分
通过 permisson 属性,或者 readPermission 和 writePermission属性,向Android系统说明,如果要访问你的provider,使用者需拿了什么权限(前面通过<permission>结点注册的)
通过 android:grantUriPermissions 属性,向系统说明,可以通过临时权限访问你的provider

在源代码里面,实现一个继承provider的子类。实现里面的onCreate(), query(), insert(), update(), delete() 等方法。还要实现getType()方法,返回指定URI的MIME type
就这么多吧。具体可以看例子了。

另外要注意的是。
onCreate()里面不能执行长时间的操作。不应该去执行创建database这样耗时的操作。防止阻塞主线程嘛。
其他的访问数据的函数,要注意实现成线程安全的。因为他们会在不同的线程中被同时调用啊!


访问content provider
你需要先在AndroidManifest.xml中申请相应的权限。如果你不知道具体是什么权限,去看provider提供的文档。或者看provider的源代码,或者打电话给provider的作者。XD
然后你通过Context.getContentResolver()得到ContentResolver, 然后通过ContentResolver访问content provider的数据。你调用的Content Resolver的函数里面都需要提供URI, Android系统会通过URI找到对应的provider,调用对应的函数,然后返回值。
projection就是字段列表。selection clause就是选择条件,满足条件的data才会返回。
query()返回的是cursor。如果返回的是null,则表示出错了。如果返回的cursor的cursor.getCount()是0,则表示一条符合条件的数据都没有。否则你只需便利cursor就可以了。
关于从cursor中取数据,你先调用cursor.getColumnIndex( FieldName ),获得你想要的field的在cursor中的index。然后
int index = cursor.getColumnIndex( FieldName );
while( cursor.moveToNext() ) {
    value = cursor.getXXX( index );
}

关于更多的详细的,你应该去看文档 Content Provider Basics

原创粉丝点击