Android联系人信息保存在3层数据模型中,并且使用3张表保存: contacts、raw contacts及data。下图是Android联系人3层结构图。
- Data是RawContact的数据属性,不同类型的数据保存为一行,例如姓名、照片、Email地址等。数据类型通过ContactsContract.Data.MINETYPE字段来区分,并且通过ContactsContract.Data.RAW_CONTACT_ID与RawContact关联。
- RawContact是一个联系人特定类型的账号,例如Google账号、新浪微博账号。RawContact使用accountName和accountType标识账号信息,其中accountName表示账号名称,例如SIM;accountType表示账号类型,例如com.anddroid.contacts.sim。
- Contact表示一个“物理的”联系人,他可以聚合多个RawContact。Android会根据RawContact的姓名、email等信息判断RawContacts是否对应于一个Contact,并提醒用户对他们进行关联。
简单而言,一个Contact表示一个联系人,RawContact表示该联系人在Android不同应用中的账号,如Google账号、新浪微博账号等。Data则是RawContact的属性,比如生日、纪念日、头像等。
上述相关信息均可通过联系人的ContentProvider查询出,例如查询下列字段:
private static String[] CONTACT_COLUMNS = { //联系人ID ContactsContract.Contacts.Data.RAW_CONTACT_ID, //联系人显示姓名 ContactsContract.Contacts.DISPLAY_NAME, //事件公历日期 ContactsContract.CommonDataKinds.Event.START_DATE, //事件名称 ContactsContract.CommonDataKinds.Event.LABEL, //事件类型 ContactsContract.CommonDataKinds.Event.TYPE, //帐户名称 ContactsContract.RawContacts.ACCOUNT_NAME, //账户类型 ContactsContract.RawContacts.ACCOUNT_TYPE }; //查询记录 Cursor cursor = context.getContentResolver().query( Data.CONTENT_URI, //查询联系人URI CONTACT_COLUMNS, //联系人字段 null, //查询条件 null, //查询条件对应的值 null); //排序规则
联系人账号的类型,即accountType,是系统级唯一的,因此Android软件开发商通常会以Java包命名的习惯定义accountType。例如com.google是Google账号、com.htc.friendstream.sinaweiboplugin表示新浪微博账号,而这如果在应用直接显示该值,对用户而言是非常不友好的。
Android SDK提供了account label来描述accountType,而且支持国际化。
Android SDK使用AuthenticatorDescription保存账号签发机构的描述信息,并将账号类型的描述资源保存在AuthenticatorDescription.labelId中,这样就能实现国际化描述。
//获取AccountManager AccountManager am = AccountManager.get(context); //获取系统所有AuthenticatorDescription AuthenticatorDescription[] descriptions = am.getAuthenticatorTypes(); //获取PackageManager PackageManager pm = context.getPackageManager(); //循环打印出AuthenticatorDescription的信息 for (AuthenticatorDescription ad : descriptions) { //获取账号类型的国际化描述 CharSequence label = pm.getText(ad.packageName, ad.labelId, null); Log.d("Account Type", "Account Type: " + ad.type + ", Account Label: " + label)); }