在Android系统上,每一个应用程序都有一个独立的用户ID。为什么要给每一个应用程序分配一个独立的用户ID呢?这是为了保护各个应用程序的数据不被其它应用程序恶意破坏而设计的。例如,只有当一个用户对某个文件拥有读权限时,这个用户才可以调用read系统调用来读取这个文件的内容。Android系统继承了Linux系统管理文件的方法,为每一个应用程序分配一个独立的用户ID和用户组ID,而由这个应用程序创建出来的数据文件就赋予相应的用户以及用户组读写的权限,其余用户则无权对该文件进行读写。
Android系统中的Content Provider应用程序组件正是结合上面分析的这种文件权限机制来秉承这种有保护地开放自己的数据给其它应用程序使用的理念。
1.在需要时暴露的自身应用的数据供其他应用访问,则需继承contentprovider类并实现,以便其他应用可用;
2.在应用需要用其他应用的contentprovider数据时,需在androidmanifest.xml文件增加读写权限,如:
读写联系人数据,
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
与<application 标签是平行的;
16.1、Provider概述
Content Provider,内容供给源,简称供给源或Provier,Android四类组件之一,用来在不同的application之间共享数据,通常包含两个部分,用别人或被别人用,即调用别人application的Provider或为自己的application创建Provier给别人用。举例来说,系统自有电话薄application就对外提供了ContactsProvider,我们可以做个application通过ContactsProvider来得到系统电话簿的数据,如果自己的application需要向外共享数据时,需要建立自己的Provider,Provider可以理解为不同application之间的数据接口。
官网地址http://developer.android.com/guide/topics/providers/content-providers.html#basics
16.2、Provider Uri
我们知道一个database包含很多个table,每个table包含多个column,每个table有记录数据。一个provider类似一个database,或.net中的dataset,内部也包含一个或多个table,每个table包含一个或多个column。
为了方便操作provider,系统采用uri的方式来操作数据,格式为:
<Standard_Prefix>://<authority>/<data_path>/<id>
例content ://com.android.contacts/data/phones
content://com.android.contacts/contacts
系统自带联系人uri为“content://com.android.contacts/contacts”,Content表示该Uri对应一个Content Provider,而不是http或ip,“com.android.contacts”对应authority,contacts为表名。联系人的电话薄uri为content://com.android.contacts/data/phones,phones为表名。如果带id则表示操作该id对应的数据。
16.3、调用别人Provider
·
方法一:getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder)
方法二:Activity.managedQuery(uri, projection, selection, selectionArgs, sortOrder)
Uri:表名
projection:列名称集合
selection:对应sql语句中的where
selectionArgs: selection中占位符“?”对应变量的参数值
sortOrder:对应order by 语句
这两个方法返回的是Cursor游标,相当于数据库中的游标,Cursor提供了moveToFirst()、moveToLast()、moveToNext()、moveToPrevious() 、moveToPosition(position)等方法来控制游标的移动,同时提供了getString(columnIndex)、getInt(columnIndex)等方法来读取值。
·
单个添加:getContentResolver().insert(url, values)
Uri:表名
Values:键值对,key为列名,value为值
该方法返回一个带id的uri,代表刚添加的数据项的uri
批量添加:getContentResolver().applyBatch(authority, operations)
返回值为添加的个数
·
getContentResolver().update(uri, values, where, selectionArgs)
·
getContentResolver().delete(url, where, selectionArgs)
返回删除的个数
16.4、创建Provider被调用
可以从抽象类ContentProvider派生自己的类来实现自己的provider,在此过程中需要重载如下几个抽象方法:
·
·
·
·
·
·
注意建立完自己的provider后,不要忘记在AndroidManifest.xml文件中进行配置
16.5、Content Provider更新的通知机制
当多个应用或同一个应用的不同操作来使用同一个provider时,就需要一种及时的通知机制。如下图,当应用2修改了provider的数据时,要及时的通知应用1。
图16-1 更新通知机制
通过在应用1中建立Observer观察者对象来完成对Provider中特定URI(表)的监视,当Provider数据变化时,观察者会自动被通知,然后观察者再通知注册的Resolver,Resolver通过观察者的URI,知道provider中哪个表被修改。
在应用2中,通过
Cursor.setNotificationUri(cr, uri);
getContentResolver().notifyChange(uri, observer);
方法发出通知,从而通知应用1中的观察者。
应用1中注册观察者通过
getContentResolver().registerContentObserver(uri, notifyForDescendents, observer);
方法来实现,注销时用
getContentResolver().unregisterContentObserve
方法来实现。
更改在观察者的onChange()方法捕获。
注意:观察者可以观察到URI的变化,但是URI并没有作为参数传递给观察者,所以当观察者观察一个表时,仅可以观察到表的改变,但是具体是增删改查哪种操作,或者哪个记录被操作无法观察到。
示例:
l
l
Uri uri = ContactsContract.Contacts.CONTENT_URI;
observer = new ContactObserver(new Handler());
getContentResolver().registerContentObserver(uri, true, observer);
l
if(observer!=null) {