您的位置:首页 > 移动开发 > Android开发

Pro Android学习笔记(一六十):联系人API(3):联系人数据

2015-03-05 20:44 543 查看
文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei

联系人信息

查看reference中android.provider.ContactsContract.CommonDataKinds可以知道该版本的Android API联系人中带有哪些信息。在API level 19中,我们看到有以下的信息:



而各个信息,例如Email,又有着他的结构,我们可以继续查看ContactsContract.CommondataKinds.Email。



联系人数据库

一个账号account拥有其自己的联系人,这些联系人称为raw contacts,具有自己的数据信息,例如email,phone号码,地址等。Android在people应用中提供了raw contacts的整合,不同账号的raw contact进行整合,只在列表中出现一次。
联系人信息存放在/data/data/com.android.providers.contacts/databases中。



在profile.db中存放的是personal profile账号的下属联系人。我们将contacts2.db和profile.db导出来,通过SQLiteManager看看里面的内容,也可以用SDK中的platform-tools/sqlite3.exe命令,具体的参见Pro
Android学习笔记(五):了解Content Provider(上)。

sqlite> .schema raw_contacts;

sqlite> .tables

_sync_state phone_lookup view_data_usage_stat

_sync_state_metadata photo_files view_entities

accounts properties view_groups

agg_exceptions raw_contacts view_raw_contacts

android_metadata search_index view_raw_entities

calls search_index_content view_stream_items

contacts search_index_docsize view_v1_contact_methods

data search_index_segdir view_v1_extensions

data_usage_stat search_index_segments view_v1_group_membership

default_directory search_index_stat view_v1_groups

deleted_contacts settings view_v1_organizations

directories status_updates view_v1_people

groups stream_item_photos view_v1_phones

mimetypes stream_items view_v1_photos

name_lookup v1_settings visible_contacts

nickname_lookup view_contacts voicemail_status

packages view_data

raw contacts

每个账号下面有raw contacts表格,记录各自的raw contacts信息。通过图形工具,我们来查看raw_contacts的定义:



CREATE TABLE raw_contacts (

_id INTEGER PRIMARY KEY AUTOINCREMENT,

account_id INTEGER REFERENCES accounts(_id),表明raw contact属于哪个account,可以在accounts的表中,根据_id查到account_name和account_type。

sourceid TEXT, 表明这个raw contact在这个account中是唯一的,例如account为Google email账号,这里是用户的email ID。如何组织管理账号以及里面联系人和手机制造商有关,这里也可能weiNull。

raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0,

version INTEGER NOT NULL DEFAULT 1,

dirty INTEGER NOT NULL DEFAULT 0,

deleted INTEGER NOT NULL DEFAULT 0,

contact_id INTEGER REFERENCES contacts(_id),表格contacts中是整合的账号表,这里是对应整合表contacts中的_id。

aggregation_mode INTEGER NOT NULL DEFAULT 0,

aggregation_needed INTEGER NOT NULL DEFAULT 1,

custom_ringtone TEXT,

send_to_voicemail INTEGER NOT NULL DEFAULT 0,

times_contacted INTEGER NOT NULL DEFAULT 0,

last_time_contacted INTEGER,

starred INTEGER NOT NULL DEFAULT 0,

pinned INTEGER NOT NULL DEFAULT 2147483647,

display_name TEXT,这是只读,有表格data中的的data列触发生成。

display_name_alt TEXT,

display_name_source INTEGER NOT NULL DEFAULT 0,

phonetic_name TEXT,

phonetic_name_style TEXT,

sort_key TEXT COLLATE PHONEBOOK,

phonebook_label TEXT,

phonebook_bucket INTEGER,

sort_key_alt TEXT COLLATE PHONEBOOK,

phonebook_label_alt TEXT,

phonebook_bucket_alt INTEGER,

name_verified INTEGER NOT NULL DEFAULT 0,

sync1 TEXT, sync2 TEXT, sync3 TEXT, sync4 TEXT )sync用于设备上contact与服务器之间的同步。
我们也可以在android.providers.ContactsContact.RawContact中查看相关信息。
使用SDK的定义可以特别在不同SDK版本表格出现列的增删改情况,仍可以安全地使用。但是SDK中看起来很复杂和繁琐,不容易理清,所以我们直接看表格定义。自开放式,我们将使用SDK里面的定义。

data表

在raw_contacts表格并没有存放contact的所有信息,例如电话号码、邮件等,是存放在data表中。

CREATE TABLE data (

_id INTEGER PRIMARY KEY AUTOINCREMENT,

package_id INTEGER REFERENCES package(_id),

mimetype_id INTEGER REFERENCES mimetype(_id) NOT NULL,表明是哪个信息,例如名字、电话号码等等,mimetype也将决定信息存储data1~data15的含义 。

raw_contact_id INTEGER REFERENCES raw_contacts(_id) NOT NULL,data表和raw_contacts表之间相互索引。raw_contact_id是可以重复的,用于分别存放不同的信息。

is_read_only INTEGER NOT NULL DEFAULT 0,

is_primary INTEGER NOT NULL DEFAULT 0,

is_super_primary INTEGER NOT NULL DEFAULT 0,

data_version INTEGER NOT NULL DEFAULT 0,

data1 TEXT,data2 TEXT,data3 TEXT,data4 TEXT,data5 TEXT,data6 TEXT,data7 TEXT,data8 TEXT,data9 TEXT,data10 TEXT,data11 TEXT,data12 TEXT,data13 TEXT,data14 TEXT,data15 TEXT,

data_sync1 TEXT, data_sync2 TEXT, data_sync3 TEXT, data_sync4 TEXT )
我们看一个查询的结果:



下面是表mimetype的内容,通过data中的mime_type_id可以检索具体的类型。用表格来存储类型,而不是进行固化,这可以灵活地增加、删除和修改定义,是个好的设计。



data表的各列也可以查看ContactsContract.Data,具体的某个mimetype对应的data1~data15各标识什么,可以查阅ContactsContract.CommonDataKinds.*,例如ContactsContract.CommonDataKinds.Phone。

整合联系人:表contacts

在不同的账号下面可以会有相同的联系人,Android进行了整合,存放在可读表contacts中,raw_contacts和data表有trigger可以触发来填写或者修改contacts表的数据。

CREATE TABLE contacts (

_id INTEGER PRIMARY KEY AUTOINCREMENT,

name_raw_contact_id INTEGER REFERENCES raw_contacts(_id),

photo_id INTEGER REFERENCES data(_id),

photo_file_id INTEGER REFERENCES photo_files(_id),

custom_ringtone TEXT,

send_to_voicemail INTEGER NOT NULL DEFAULT 0,

times_contacted INTEGER NOT NULL DEFAULT 0,

last_time_contacted INTEGER,

starred INTEGER NOT NULL DEFAULT 0,

has_phone_number INTEGER NOT NULL DEFAULT 0,

has_valid_sip_account INTEGER NOT NULL DEFAULT 0,

lookup TEXT,
contacts表格数据是系统根据raw contacts的数据进行生成和修改,这个表的数据会根据raw contacts的变化而变化,采用 将_id代表某个联系人,并将之作为索引,在某些情况下并不合适,因此引入了lookup,lookup是进行过编码,含有account以及其下的raw_contact联系人ID,可将之作为生成LookUpURI进行查询,获取最新整合联合人的信息。我们在下一学习的小例子进行演示。

status_update_id INTEGER REFERENCES data(_id))
Andriod如何判断是否可以进行判断。如果两个raw_contacts名字相同,或者first name和last name的顺序不同,但内容一致,或者是缩写或昵称(例如Bob和Robert);如果name只有first name或者last name,将查找其他属性,例如电话号码、邮件,如果其他属性也匹配,可以进行整合;如果raw contact没有name,那么将查询其他属性。
基于这些判断进行整合是可能出现误判的。在raw_contacts中aggregation_mode列,有三个值:AGGEREGATION_MODE_DEFAULT,AGGERGATION_MODE_DISABLED(禁止整合,如果已经整合,将从整合中分离出来,为其分配一个新的contact ID),以及AGGEREGATION_MODE_SUSPENDED(当属性变化是,并不整合到整合联系人中)。

视图:view_contacts

API并不直接暴露contacts表,而是通过视图view_contacts读取。当通过URI:ContactsContract.Contacts.CONTENT_URI来查询时,实际查询的是view_contacts。

CREATE VIEW view_contacts AS

SELECT contacts._id AS _id,

contacts.custom_ringtone AS custom_ringtone,

name_raw_contact.display_name_source AS display_name_source,

name_raw_contact.display_name AS display_name,

name_raw_contact.display_name_alt AS display_name_alt,

name_raw_contact.phonetic_name AS phonetic_name,

name_raw_contact.phonetic_name_style AS phonetic_name_style,

name_raw_contact.sort_key AS sort_key,

name_raw_contact.sort_key_alt AS sort_key_alt,

has_phone_number,

has_valid_sip_account,

name_raw_contact_id,

lookup,

photo_id,

photo_file_id,

CAST(EXISTS (SELECT _id FROM visible_contacts WHERE contacts._id=visible_contacts._id) AS INTEGER) AS in_visible_group,

status_update_id,

contacts.last_time_contacted AS last_time_contacted,

contacts.send_to_voicemail AS send_to_voicemail,

contacts.starred AS starred,

contacts.times_contacted AS times_contacted,

(CASE WHEN photo_file_id IS NULL

THEN (

CASE WHEN photo_id IS NULL OR photo_id=0

THEN NULL

ELSE 'content://com.android.contacts/contacts/'||contacts._id|| '/photo' END)

ELSE 'content://com.android.contacts/display_photo/'||photo_file_id END) AS photo_uri,

(CASE WHEN photo_id IS NULL OR photo_id=0

THEN NULL

ELSE 'content://com.android.contacts/contacts/'||contacts._id|| '/photo' END) AS photo_thumb_uri,

0 AS is_user_profile,

name_raw_contact.view_mode AS view_mode,

name_raw_contact.sim_index AS sim_index

FROM contacts JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id)

视图:view_entities

合并raw_contacts和data,可以获得每个raw contacts的全部信息。

CREATE VIEW view_entities AS

SELECT raw_contacts.contact_id AS _id,

raw_contacts.contact_id AS contact_id,

raw_contacts.deleted AS deleted,

is_primary,

is_super_primary,

data_version,

data.package_id,

package AS res_package,

data.mimetype_id,

mimetype AS mimetype,

is_read_only,

data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, data13, data14, data15,

data_sync1, data_sync2, data_sync3, data_sync4,

raw_contacts.account_id,

accounts.account_name AS account_name,

accounts.account_type AS account_type,

accounts.data_set AS data_set,

(CASE WHEN accounts.data_set IS NULL

THEN accounts.account_type

ELSE accounts.account_type||'/'||accounts.data_set END) AS account_type_and_data_set,

raw_contacts.sourceid AS sourceid,

raw_contacts.name_verified AS name_verified,

raw_contacts.version AS version,

raw_contacts.dirty AS dirty,

raw_contacts.sync1 AS sync1,raw_contacts.sync2 AS sync2,raw_contacts.sync3 AS sync3,raw_contacts.sync4 AS sync4,

contacts.custom_ringtone AS custom_ringtone,

name_raw_contact.display_name_source AS display_name_source,

name_raw_contact.display_name AS display_name,

name_raw_contact.display_name_alt AS display_name_alt,

name_raw_contact.phonetic_name AS phonetic_name,

name_raw_contact.phonetic_name_style AS phonetic_name_style,

name_raw_contact.sort_key AS sort_key,

name_raw_contact.phonebook_label AS phonebook_label,

name_raw_contact.phonebook_bucket AS phonebook_bucket,

name_raw_contact.sort_key_alt AS sort_key_alt,

name_raw_contact.phonebook_label_alt AS phonebook_label_alt,

name_raw_contact.phonebook_bucket_alt AS phonebook_bucket_alt,

has_phone_number,

name_raw_contact_id,

lookup,

photo_id,

photo_file_id,

CAST(EXISTS (SELECT _id FROM visible_contacts WHERE contacts._id=visible_contacts._id) AS INTEGER) AS in_visible_group,

status_update_id,

contacts.contact_last_updated_timestamp,

contacts.last_time_contacted AS last_time_contacted,

contacts.send_to_voicemail AS send_to_voicemail,

contacts.starred AS starred,

contacts.pinned AS pinned,

contacts.times_contacted AS times_contacted,

(CASE WHEN photo_file_id IS NULL

THEN (CASE WHEN photo_id IS NULL OR photo_id=0

THEN NULL

ELSE 'content://com.android.contacts/contacts/'||raw_contacts.contact_id|| '/photo' END)

ELSE 'content://com.android.contacts/display_photo/'||photo_file_id END) AS photo_uri,

(CASE WHEN photo_id IS NULL OR photo_id=0

THEN NULL ELSE 'content://com.android.contacts/contacts/'||raw_contacts.contact_id|| '/photo' END)

AS photo_thumb_uri,

0 AS is_user_profile,

data_sync1, data_sync2, data_sync3, data_sync4,

raw_contacts._id AS raw_contact_id,

data._id AS data_id,

groups.sourceid AS group_sourceid FROM raw_contacts

JOIN accounts ON (raw_contacts.account_id=accounts._id)

JOIN contacts ON (raw_contacts.contact_id=contacts._id)

JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id)

LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id)

LEFT OUTER JOIN packages ON (data.package_id=packages._id)

LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id)

LEFT OUTER JOIN groups ON (mimetypes.mimetype='vnd.android.cursor.item/group_membership' AND groups._id=data.data1)
相关链接:我的Android开发相关文章
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐