Android Contacts源码解析24 ContactsPRovider模块1ContactsProvider简介2数据库创建3主要数据库的表结构相互关系1data表2raw_contacts表3contacts表4mimetypes5其他表
第一篇:Android Contacts源码解析1
数据操作层。 ContactsProvider类的结构: 
ContactsProvider中数据操作基类是AbstractContactsProvider.java,它继承ContentProvider组件类并实现了SQLiteTransactionListener。 可以发现,该类是抽象基类,在里面实现了ContentProvider类的insert、delete和update三个抽象方法,在这三个方法中在其中使用了事务对数据库进行操作,方法为insertInTransaction,updateInTransaction和deleteInTransaction。该类在对数据库进行事务操作的同时,对子类开放了onBegin、onRollback,onCommit事务回调方法,子类可以根据自己的业务特点进行扩展。
以Insert为例,基本时序图为: 
数据库的一些概念性知识:
数据库索引: 对数据库表中一个或多个列的值进行排序的结构。排序之后进行搜索会更加有效率,也就是说,索引有助于更快地获取信息。
数据库视图: 将数据库的多个表的多个列组合为一张虚拟的表,称之为视图,方便查询,同时也掩饰了底层数据库的复杂性,把数据库设计的复杂性与用户屏蔽分开。
数据库触发: 触发器是一种特殊类型的存储过程,它在指定的表中的数据发生变化时自动生效。唤醒调用触发器以响应 INSERT、UPDATE 或 DELETE 语句。 常见的触发器有两种:before和after,决定触发的时机。
数据库的创建主要通过ContactsDatabaseHelper和LegacyApiSupport来进行创建。 ContactsDatabaseHelper类是单例类,继承了SQLiteOpenHelper,所以同一时刻不同的ContentProvider只能得到一个数据库引用。
当用户调用ContactsDatabaseHelper的OnCreate之后,先完成自己模块内定义的操作,然后执行LegacyApiSupport中的crateDatabase()。


联系人的数据库文件的位置: /data/data/com.android.providers.contacts/databases.contacts2.db
数据库中主要的几张表之间的关系: 
MimeTypeID和RawContactID,从而将data表和raw_contacts表、mimetypes联系起来。Data表储存所有与RawContract相关具体的信息。表的每一条记录对应一个特定信息,如:名字、电话,email地址, 头像和组信息等。每一记录通过一个mimetype_id字段来表明该行所记录的数据类型。例如,如果row的数据类型是Phone.CONTENT_ITEM_TYPE,那么第一个字段应该保存电话号码,如果数据类型为Email.CONTENT_ITEM_TYPE,那么这一记录的字段应该保存邮件地址。联系人的所有信息保存在列data1至data15中,各列中保存的内容根据MimeTypeID的不同而不同。如保存号码(MimeTypeID=5)的那行数据中,data1列保存号码,data2列保存号码类型(手机号码/家庭号码/工作号码等)。Data表的字段主要有:
| 列 | 说明 |
|---|---|
| mimetype_id | 表示该行存储的信息的类型,外键 |
| raw_contact_id | 表示该行所属的RawContact,外键 |
| is_primary | 多个data数据组成一个raw contact,该字段表示此data是否是其所属的raw contact的主data,即其display name会作为raw contact的display name |
| is_super_primary | 该data是否是其所属的contact的主data,如果is_super_primary为1则is_primary一定为1 |
| data1~data15 | 15个数据字段,对于不同类型的信息,表示不同的含义,ContactsContract.CommomDataKinds类中定义了与常用的数据类型相对应的一些类,这些类中分别定义了相应数据类型中这些字段表示的含义。一般data1表是主信息(如电话,Email地址等),data2表示副信息,data15表示Blob数据。 |
| data_sync1~data_sync4 | sync_adapter要用的字段(sync_adapter用于数据的同步,比如你手机中的Gmail帐户与Google服务器的同步)。 |
| data_version | 数据的版本,用于数据的同步。 |
Data表的索引Index有: _id data表的Id列 Mimetype_id 存储的信息的类型 raw_contact_id 所属的raw_contact的id
Data表的触发Trigger有: [data_updated] 数据更新时触发RawContacts表更新数据update {@link RawContacts#VERSION} [data_deleted] 数据被删除时触发RawContacts表更新数据update {@link RawContacts#VERSION}
raw contact表描述了联系人每个账户下的数据,根据账户名和账户类型字段进行区分。即同一个联系人可能在raw contact表中有多个记录,每个记录分属于不同的账户。表中的每一行表示一个联系人某一特定帐户的信息,存储Data表中一些数据行的集合及一些其他的信息。
当插入一个raw contact或当一个raw contact所属的一个data改变时,系统会检查这个raw contact跟其他的raw contact是否可以匹配(比如如果两个raw contact的data包含相同的电话号码或名字),如果匹配他们就会被综合到一起,也就是说他们会属于同一个contact,表现为在RawContact表中他们引用的cantact_id是一样的。联系人姓名、组织、电话号码、Email或昵称的改变会引发raw contact的重新聚合。
raw contact的主要字段有:
| 列 | 说明 |
|---|---|
| account_id | 本行数据关联的联系人账户 |
| contact_id | 本行数据关联的Contact表数据 |
| raw_contact_is_read_only | 是否只读 |
| version | 版本 |
| deleted | 是否已被删除 |
| last_time_contacted | 上次联系时间 |
| Times contact | 联系次数 |
| starred | 收藏? |
| indicate_phone_or_sim_contact | Sim卡/手机联系人 |
raw contact的索引有:
[] PRIMARY [_id] AUTOINCREMENT [raw_contact_sort_key1_index] [sort_key] [raw_contact_sort_key2_index] [sort_key_alt] [raw_contacts_contact_id_index] [contact_id] [raw_contacts_source_id_account_id_index] [sourceid] [account_id]raw contact的触发有:
[raw_contacts_deleted] 当一个Raw_contacts被删除的时候,自动删除Data表中相关的Data。(即Raw_contacts的id为删除的那个id)
[raw_contacts_marked_deleted] Triggers that update {@link RawContacts#VERSION} when the contact is marked for deletion。
每个联系人占一行,该表保存了联系人的ContactID、联系次数、最后一次联系的时间、是否含有号码、是否被添加到收藏夹等信息。 Contact表不能被主动创建,Contact表中的一行表示一个联系人,它是RawContact表中的一行或多行的数据的组合。这些RawContact表中的每一行,表示同一个人的不同的帐户信息。Contact中的数据由系统组合RawContact表中的数据自动生成,不可以直接向这个表中插入数据,当一个raw contact被插入的时候,系统会首先查找Contact表看是否有记录跟插入的raw contact表示同一个人,如果找到了,则把找到的这个contact的_ID插入raw contact记录的CONTACT_ID字段,如果没有找到,则系统自动插入一个Contact记录并把它的_ID插入新插入的raw contact的CONTACT_ID列。
Contacts表是对raw contact表按照account type和account name进行的聚合。 Contacts表的聚合逻辑在ContactAggregator.java文件中,该类中定义了一个成员方法.
Contacts表的主要字段:
| 列 | 说明 |
|---|---|
| name_raw_contact_id | 本行数据关联的联系人账户,外键 |
| last_time_contacted | 上次联系的时间 |
| raw_contact_is_read_only | 是否只读 |
| lookup | 查找字符串 |
| indicate_phone_or_sim_contact | Sim卡/手机联系人 |
| photo_id | 照片Id,外键 |
| starred | 收藏 |
Contacts表建立的索引:
[contact_last_updated_timestamp] 联系人上次更新时间[has_phone_number] 联系人是否有电话号码[name_raw_contact_id] raw contact ID该表定义了所有的MimeTypeID,即联系人的各个字段的唯一标志。 主要类型如下:
| 列 | 说明 |
|---|---|
| vnd.android.cursor.item/phone_v2 | 电话 |
| vnd.android.cursor.item/name | 姓名 |
| vnd.android.cursor.item/email_v2 | 邮件 |
| vnd.android.cursor.item/postal-address_v2 | 通信地址 |
| vnd.android.cursor.item/organization | 组织 |
| vnd.android.cursor.item/photo | 照片 |
calls表 最的通话记录 android.provider.CallLog.Calls
| 列 | 说明 |
|---|---|
| _id | 行id |
| number | 通话电话号码 |
| data | 拨打该电话号码的开始时间(以1970-01-01 00:00:00)计算到当前的时间差以毫秒为单位 |
| duration | 打电话持续时间,以秒为单位 |
| type | 呼叫类型(“1”来电,“2”外拨,“3”未接) |
| new | 呼叫已被确认与否。“1”代表来电,外拨,“0”代表未接 |
| name | 如果联系人存在,与电话号码相关联的联系人的名字 |
| numbertype | 如果联系人存在,与电话号码相关联的电话类型 |
| numberlabel | 如果联系人存在,自定义数字类型相关联的电话号码数字标签(例如VOICE)(numbertype 为1-7时numberlabel为null;为0时显示自定义标签) |
| typedial | 拨打电话的类型(语言电话、视频电话) |
phone_lookup表
| 列 | 说明 |
|---|---|
| data_id | 通过data_id可以找到 data表中相对的数据。 |
| raw_contact_id | 通过raw_contact_id 可以找到 raw_contact_表中相对的数据 |
| normalized_number | 原始电话号码 |
| min_match | 将每个电话号码逆序排列 |
groups表 ContactsContract.Groups
| 列 | 说明 |
|---|---|
| _id | 行id |
| package_id | |
| account_name | 账户名字 |
| account_type | 帐户的类型 |
| sourceid | |
| version 版本; | 当列或相关数据修改时,将会自动修改 |
| dirty | 版本发生改变的标记 |
| title | 这组显示的标题 |
| title_res | |
| notes | 这组的注释 |
| system_id | 如果它是一个系统组,这个组的ID,即对同步适配器具有特殊意义的一组,否则返回null。 |
| deleted | 删除标记;0 or 1;1 表示标记为被删除。 |
| group_visible | 群组是否在UI中 是否可见;是(1),否(0) |
| should_sync | 这组是否应该同步,是(1),否(0) |
| sync1到sync4 |
accounts表 android.accounts.Account
| 列 | 说明 |
|---|---|
| account_name | 账户名字 |
| account_type | 账户类型 |
settings表 android.provider.ContactsContract.Settings
| 列 | 说明 |
|---|---|
| account_name | 账户名字 |
| account_type | 账户类型 |
| ungrouped_versible | 标志该组是否在UI中可见;“1”可见,“0”不可见 |
| should_sync | 根据同步适配器定义的模式,这个标志控制此数据源的顶级的同步行为。 |
agg_exceptions表 ContactsContract.AggregationExceptions _id type 异常的类型:TYPE_KEEP_TOGETHER(1),TYPE_KEEP_SEPARATE(2)或TYPE_AUTOMATIC(3)。 raw_contact_id1 A reference to the _ID of the raw contact that the rule applies to. raw_contact_id1 A reference to the other _ID of the raw contact that the rule applies to. raw_contact_id1和raw_contact_id2之间通过规则(type)引用
sqlite_sequence表 SQLite中的自动编号列 name 自动编号字段所在的表 seq 当前用到的序号
新闻热点
疑难解答