Android Contacts数据库分析

数据库分析

概述:

mimetype表

该表中的数据主要用作标记,标记data表中的每一条数据是何种数据类型。

此表中的记录内容相对稳定,内容如下:

1. vnd.android.cursor.item/email_v2--邮件

  1. vnd.android.cursor.item/im--帐号

  2. vnd.android.cursor.item/postal-address_v2--邮政地址

  3. vnd.android.cursor.item/photo--图片

  4. vnd.android.cursor.item/phone_v2--电话

  5. vnd.android.cursor.item/name--姓名

  6. vnd.android.cursor.item/organization--公司

  7. vnd.android.cursor.item/nickname--昵称

  8. vnd.android.cursor.item/group_membership-组别


Contacts表

实际上Contact表不保存联系人的具体数据,具体数据是保存于data表,一个用于保存主数据,一个用于保存子数据(详细数据)。

总结

data、raw_contacts、contacts三个表代表了联系人数据的三种层次。


data里面的一行记录可存储一个联系人信息,如电话号码和email地址。存储于此表的数据类型的集合是开放的,应用程序可以增加自己的数据类型。


raw_contacts的记录表示一个联系人信息,并且可以和一个帐号(account)进行关联(例如,一个gmail帐号)。raw_contacts和打他是一对多的关系。


contacts的记录表示一个或者多个raw_contacts的记录的联合,用于表示用一个联系人的不同联系信息。contacts和raw_contact也是一对多关系。


具体的关系描述从ContactsContract(frameworks/base/core/java/android/provider)中可以看到。


联系人总体代码结构中的如下部分都是与数据库相关的,其中ContactsProvider2是联系人数据提供者,ContactsDatabaseHelper是数据库创建和版本管理的帮助类。

位于frameworks目录下的ContactsContract是联系人数据的描述类,它是联系人数据提供者和应用程序之间的一种约定。它包含了可支持URI和字段信息。


/packages/providers/ContactsProvider/src/com/android/providers/contacts

ContactsDatabaseHelper.java

ContactsProvider2.java


数据相关类—ContactsContract

理解ContactsContract这个类对理解整个联系人数据库至关重要。它不但是对数据库几个表和字段的说明,而且是Contacts provider和应用程序之间的一种约定,它提供了对Contacts provider所支持的URI和各字段的描述。此类可以看作对Contacts2.db这个数据库进行描述的类。

此类的结构非常庞大,整体结构:ContactsContract里面各个内部类分别对应一个数据库表结构,如:Contacts、Data、RawContacts、Group等,而ContactsContract里面同时存在许多接口(Interface),接口之间还有集成关系,用于表示各个字段的定义和组合关系。


数据相关类—ContactsContract$Data

Data作为一个 ContactsContract的一个静态类,继承了DataColumnsWithJoins接口,而DataColumnsWithJoins又继承了DataColumns,DataColumnsWithJoins组合里data表查询时所有可能返回的字段,然后内部类Email实现此字段。Data类图示意图如下:

ContactsContract$CommonDataKinds$Email

data表字段信息位于DataColumns接口定义中,如data1字段对应的DATA1属性,而Email的public static final String ADDRESS=DATA1;是将接口DataColumns中的DATA1属性进行了重新命名而已,对应的表字段还是data1,只不过对于Email而言,data1代表了Email地址。而对于其他类,data1可能表达其他意义,如phone的NUMBER属性也是对应字段data1.这样,在程序中就可以使用Phone.NUMBER这种可读性强的代码。


其他和Email类似的定义有:

Nickname、Organization、Phone、StructuredName、StructuredPostal。这些类都对应data表的某些字段的集合,各自组成了联系人的某类信息。


ContactsProvider2

此类是联系人的数据提供者和操作者,是数据库和应用程序之间的桥梁。

它的代码结构也比较庞大,但从本质上说,它的主要内容就是查询、添加、删除、修改。

1.查询

public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder)

2.增加

public Uri insert(Uri uri,ContentValues values)

如果是批处理的话(运行在事务中),它在基类SQLiteContentProvider的insert会调用自身的protected Uri insertInTransaction(Uri uri,ContentValues values)\

3.删除

public int delete(Uri uri,String selection,String[] selectionArgs)

如果是批处理的话,它会调用

protected int deleteInTransaction(Uri uri,String selection,String[] selectionArgs)

4.更新

public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs)

如果是批处理的话,它会调用

protected int updateInTransaction(Uri uri,ContentValues values,String selection,String[] selectionArgs)

还有一些其他重要函数,不一一列举。


ContactsProvider2与Uri

前面介绍的ContactsProvider2的主要方法里面的地一个参数就是Uri,它通过Uri判断究竟是对哪种类型的数据进行处理,是contacts、raw_contacts还是data,是处理单个记录还是多个记录。它借助UriMatcher这个类对Uri分类进行处理。在类的static静态初始化代码快里面,有如下代码:


static {


// Contacts URI matching table


final UriMatcher matcher = sUriMatcher;


matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions",


AGGREGATION_SUGGESTIONS);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*",


AGGREGATION_SUGGESTIONS);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/display_photo",


CONTACTS_ID_DISPLAY_PHOTO);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items",


CONTACTS_ID_STREAM_ITEMS);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/photo",


CONTACTS_LOOKUP_PHOTO);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data",


CONTACTS_LOOKUP_ID_DATA);


matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/photo",


CONTACTS_LOOKUP_ID_PHOTO);

…………


其中CONTACTS、CONTACTS_ID都是实现定义好的常数,用于表示匹配Uri后的标识符。

以uri实际传的值为content://com.android.contacts/contacts/7为例,它被标识为 CONTACTS_ID标识符。

在query、insert(insertInTransaction)、update(updateInTransaction)、delete(deleteInTransaction)里面。有如下语句:

final int match = sUriMatcher.match(uri);


switch (match) {


……

case CONTACTS: {


// TODO


return 0;


}




case CONTACTS_ID: {


……

}

case CONTACTS_ID之后是具体的处理代码

如果是查询,则删除的是_id为7的联系人信息

如果是删除,则删除_id为7的联系人信息

如果是更新,则更新_id为7的联系人数据

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值