Data From Sync Adapters
用户直接输入联系人的数据到设备中,但是也可以通过sync adapters从服务器上获取联系人的数据。sync adapter 会自动同步设备和服务器上的数据。sync adapter运行在后台,由系统来控制。系统调用ContentResolver去管理数据。
在Android中,和sync adapter一起工作的服务器是由账户类型表示的。每个sync adapter和一种账户类型共同工作,但是它也可以同时支持多个不同的账户名。账户类型和账户名在Sources of raw contacts data有简要的描述。下面会有更详细的描述,还会描述账户名和账户类型与sync adapter和服务器的关系。
账户类型:
标识一个用户用来存储数据的服务器。通常情况下,用户需要取得该服务器的认证。例如,Google contacts是一个账户类型,它由google.com来标识,这个标识就是在 AccountManager中要使用到的账户类型。
账户名:
标识一个账户,或用来登入到某个类型。Google contacts的账户名和Google的账户名一样,使用邮件地址作为账户名。其他的服务器可能只使用字母或数字作为用户名。
账户类型不需要唯一的。用户可以配置多个Google contact的账户,并下载它们的数据到Contacts Provider。例如,用户有一个私人的账户名,用来存储私人的联系人数据;还有另一个工作的账户名,用来存储工作的联系人。账户名+账户类型一起标识一组特定的联系人数据,这组数据可以在contacts provider和服务器上同步。
如果你想要下载你自己服务器上的数据到contacts provider,你需要自己写一个sync adapter。在Contacts Provider Sync Adapters中有更多关于这方面的描述。
下图展示了Contacts Provider如何桥接联系人的数据。每个sync adapter都用它的账户类型来标记。
Required Permissions
如果想要访问Contacts Provider,需要以下权限:
读取一个或多个表:
READ_CONTACTS,在 AndroidManifest.xml文件中,使用<uses-permission>标签定义。例如:
<uses-permission android:name="android.permission.READ_CONTACTS">。
写入一个或多个表:
WRITE_CONTACTS,在
AndroidManifest.xml文件中,使用<uses-permission>标签定义。例如:<uses-permission android:name="android.permission.WRITE_CONTACTS">
这些权限并不对用户配置文件数据起作用。用户配置文件和其权限会来接下来的The User Profile章节中讨论。
记住,用户的联系人数据是私人的,并且是敏感的。用户会在意他们的隐私,他们不愿意让任意程序收集他们个人或联系人的信息。如果你没有明确告知用户,为何需要访问联系人的权限,他们可能会给你的应用低的评价或简单的拒绝安装。
The User Profile
在ContactsContract.Contacts表中,有一行保存用户的配置文件数据。这行数据用来描述用户的信息,而不是联系人的信息。这行用户配置文件为每个心痛关联一条raw contact的数据。每行raw contact可以拥有多条的data数据。在ContactsContract.Profile中定义了访问用户配置文件的相关常量。
访问用户配置文件数据需要特殊的权限。除了 READ_CONTACTS和
WRITE_CONTACTS用来读写联系人外,还需要android.Manifest.permission#READ_PROFILE和 android.Manifest.permission#WRITE_PROFILE权限。
你必须记住,用户的配置文件数据是敏感的。android.Manifest.permission#READ_PROFILE权限允许你访问私人数据。一定要在你的应用描述中告诉用户你为何需要访问用户的个人配置文件数据。
使用 ContentResolver.query()方法去查询包含用户配置文件数据的一行联系人数据。把CONTENT_URI设进去,并且不要任何过滤条件。你也可以用这个URI用为基准uri,来查询raw contact或data的数据。例如,下面的代码片段用来查询用户的配置文件数据:
// Sets the columns to retrieve for the user profile
mProjection = new String[]
{
Profile._ID,
Profile.DISPLAY_NAME_PRIMARY,
Profile.LOOKUP_KEY,
Profile.PHOTO_THUMBNAIL_URI
};
// Retrieves the profile from the Contacts Provider
mProfileCursor =
getContentResolver().query(
Profile.CONTENT_URI,
mProjection ,
null,
null,
null);
注意:如果你查询多行contact数据,你想要检测一下某行是否为用户配置文件数据,使用
IS_USER_PROFILE
列,这一列值为1的话,就是用户配置文件。
Contacts Provider Metadata
Contents Provider在数据库中存储跟踪联系人状态的数据。数据库中的元数据存储在很多个地方,包括raw contacts,data,contacts,ContactsContract.Settings和 ContactsContract.SyncState等表中。下面的表格展示了一些数据表的功能:
Table | Column | Values | Meaning |
---|---|---|---|
ContactsContract.RawContacts | DIRTY | "0" -从上次同步后,没有改变. | 标记raw contacts在设备上已经修改,需要同步到服务器。当应用程序更新一条raw contact数据的时候,Contacts Provider会自动修改这个值。 Sync adapters 修改raw contact 或者data表的时候,需要把CALLER_IS_SYNCADAPTER加入到他们使用的URI中。这样,provider才不会把这些修改编辑成dirty。否则,sync同步到本地数据,又会被回传到服务器,即使这个修改是由服务器发起的。 |
"1" - 在上次同步后,数据有改变。需要同步到服务器 | |||
ContactsContract.RawContacts | VERSION | 这一行的版本号 | 当这一行或其关联的数据发生改变时,Contacts Provider会自动增加这个值。 |
ContactsContract.Data | DATA_VERSION | 这一行的版本号 | 当这一行或其关联的数据发生改变时,Contacts Provider会自动增加这个值。 |
ContactsContract.RawContacts | SOURCE_ID | 指向创建这个raw contact的账户 | 当sync adapter创建一个raw contact的时候,这一列被设置成服务器可以唯一识别的ID。当Android的应用创建一个raw contact的时候,应用程序要把这一列放空。这样子告诉sync adapter需要在服务器上创建一个新的raw contact,并给它一个SOURCE_ID。 唯一性:一个账户的每一行数据都需要 拥有它自己的source ID,如果不强制这样做,在联系人的应用中就会引出问题。注意,相同账户类型的两个raw contact可能会有相同的source id。例如,
|
ContactsContract.Groups | GROUP_VISIBLE | "0" - 在Android的应用中,这一组中的联系人不可见。 | 为了兼容侮辱器,可以隐藏某些组的功能。 |
"1" -在Android的应用中,这一组中的联系人可见。 | |||
ContactsContract.Settings | UNGROUPED_VISIBLE | "0" - 在这个账户名和账户类型中,不属于任何组的联系人,在Android应用程序中,不可见。 | 默认情况下,如果contacts的所有raw contact数据都不属于任何一个组,则这条contact不可教案。raw contact的组用由一行或多行 ContactsContract.Data中的 |
"1" - 在这个账户名和账户类型中,不属于任何组的联系人,在Android应用程序中,可见。 | |||
ContactsContract.SyncState | (all) | 这个表用来存储sync adapter的元数据。 | 可以在设备中存储同步状态或其他同步相关的数据。 |