关于 contact aggregation & lookup uri

来源:互联网 发布:电子商务网站源码下载 编辑:程序博客网 时间:2024/04/29 10:56

http://developer.android.com/resources/articles/contacts.html

Using the Contacts API

Starting from Android 2.0 (API Level 5), the Android platform provides animproved Contacts API for managing and integrating contacts from multipleaccounts and from other data sources. To handle overlapping data from multiplesources, the contacts content provider aggregates similar contacts and presentsthem to users as a single entity. This article describes how to use the new APIto manage contacts.

The new Contacts API is defined in the android.provider.ContactsContract and related classes. The older API is still supported, although deprecated. If you have an existing application that uses the older API, see Considerations for legacy apps, below, for ideas on how to support the Contacts API in your app.

If you'd like to look at an applied example of how to use the new Contacts API, including how to support both the new and older API in a single app,please see theBusiness Card sample application.

Data structure of Contacts

In the new Contacts API, data is laid out in three primary tables: contacts,raw contacts, anddata, a structure that is slightly different from that used in the older API. The new structure allows the system to more easily store and manage information for a specific contact from multiple contacts sources.

  • Data is a generic table that stores all of the data pointsassociated with a raw contact. Each row stores data of a specific kind —for example name, photo, email addresses, phone numbers, and group memberships.Each row is tagged with a MIME type to identify what type of data it cancontain, across the entire column. Columns are generic and the type of data theycontain is determined by the kind of data stored in each row. For example, if arow's data kind isPhone.CONTENT_ITEM_TYPE, then the first columnstores the phone number, but if the data kind isEmail.CONTENT_ITEM_TYPE, then the column stores the email address.

    The ContactsContract.CommonDataKinds class provides subclasses corresponding to common MIME types for contacts data. If needed, your application or other contacts sources can define additional MIME types for data rows. For more information about the Data table and examples of how to use it, seeandroid.provider.ContactsContract.Data.

  • A row in the RawContacts table represents the set ofData and other information describing a person and associated witha single contacts source. For example, a row might define the data associatedwith a person's Google or Exchange account or Facebook friend. For moreinformation, see ContactsContract.RawContacts.
  • A row in the Contacts table represents an aggregate of one ormoreRawContacts describing the same person (or entity).

    As mentioned above, the Contacts content provider automatically aggregatesRaw Contacts into a single Contact entry, where possible, since common datafields (such as name or email address) are likely to be stored in each rawcontact. Since the aggregation logic maintains the entries in the Contact rows,the entries can be read but should not be modified. See the sectionAggregation of contacts, below, for more details, including and information on how tocontrol aggregation.

When displaying contacts to users, applications should typically operate onthe Contacts level, since it provides a unified, aggregated view of contactsfrom various underlying sources.

Example: Inserting a Phone Number

To insert a phone number using the new APIs you'll need the ID of the RawContact to attach the phone number to, then you'll need to create a Datarow:

import android.provider.ContactsContract.CommonDataKinds.Phone;...ContentValues values = new ContentValues();values.put(Phone.RAW_CONTACT_ID, rawContactId);values.put(Phone.NUMBER, phoneNumber);values.put(Phone.TYPE, Phone.TYPE_MOBILE);Uri uri = getContentResolver().insert(Phone.CONTENT_URI, values);

Aggregation of contacts

When users sync contacts from multiple sources, several contacts might referto the same person or entity, but with slightly different (or overlapping) data. For example, "Bob Parr" might be a user's co-worker and also his personalfriend, so the user might have his contact information stored in both acorporate email account and a personal account. To provide a simplified view forthe user, the system locates such overlapping contacts and combines them into asingle, aggregate contact.

The system automatically aggregates contacts by default. However, if needed,your application can control how the system handles aggregation or it candisable aggregation altogether, as described in the sections below.

Automatic aggregation

When a raw contact is added or modified, the system looks for matching(overlapping) raw contacts with which to aggregate it. It may not find anymatching raw contacts, in which case it will create an aggregate contact thatcontains just the original raw contact. If it finds a single match, it creates anew contact that contains the two raw contacts. And it may even find multiplesimilar raw contacts, in which case it chooses the closest match.

Two raw contacts are considered to be a match if at least one of theseconditions is met:

  • They have matching names.
  • Their names consist of the same words but in different order (for example, "Bob Parr" and "Parr, Bob")
  • One of them has a common short name for the other (for example, "Bob Parr" and "Robert Parr")
  • One of them has just a first or last name and it matches the other raw contact. This rule is less reliable, so it only applies if the two raw contacts are also sharing some other data like a phone number, an email address or a nickname (for example, Helen ["elastigirl"] = Helen Parr ["elastigirl"])
  • At least one of the two raw contacts is missing the name altogether and they are sharing a phone number, an email address or a nickname (for example, Bob Parr [incredible@android.com] = incredible@android.com).

When comparing names, the system ignores upper/lower case differences (Bob=BOB=bob) and diacritical marks (Hélène=Helene). When comparing two phone numbers the system ignores special characters such as "*", "#", "(", ")", and whitespace. Also if the only difference between two numbers is that one has a country code and the other does not, then the system considers those to be a match (except for numbers in the Japan country code).

Automatic aggregation is not permanent; any change of a constituent raw contact may create a new aggregate or break up an existing one.

Explicit aggregation

In some cases, the system's automatic aggregation may not meet therequirements of your application or sync adapter. There are two sets of APIs youcan use to control aggregation explicitly:aggregation modes allow youto control automatic aggregation behaviors andaggregation exceptionsallow you to override automated aggregation entirely.

Aggregation modes

You can set an aggregation mode for each raw contact individually. To do so,add a mode constant as the value of theAGGREGATION_MODE column intheRawContact row. The mode constants available include:

  • AGGREGATION_MODE_DEFAULT — normal mode, automaticaggregation is allowed.
  • AGGREGATION_MODE_DISABLED — automatic aggregation is notallowed. The raw contact will not be aggregated.
  • AGGREGATION_MODE_SUSPENDED — automatic aggregation isdeactivated. If the raw contact is already a part of an aggregated contact whenaggregation mode changes to suspended, it will remain in the aggregate, even ifit changes in such a way that it no longer matches the other raw contacts in theaggregate.

Aggregation exceptions

To keep two raw contacts unconditionally together or unconditionally apart,you can add a row to theContactsContract.AggregationExceptions table. Exceptionsdefined in the table override all automatic aggregation rules.

Loookup URI

The new Contacts API introduces the notion of a lookup key for a contact. Ifyour application needs to maintain references to contacts, you should use lookupkeys instead of the traditional row ids. You can acquire a lookup key from thecontact itself, it is a column on the ContactsContract.Contacts table. Once you have a lookup key,you can construct a URI in this way:

Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey)

and use it like you would use a traditional content URI, for example:

Cursor c = getContentResolver().query(lookupUri, new String[]{Contacts.DISPLAY_NAME}, ...);try {    c.moveToFirst();    String displayName = c.getString(0);} finally {    c.close();}

The reason for this complication is that regular contact row IDs areinherently volatile. Let's say your app stored a long ID of a contact. Then theuser goes and manually joins the contact with some other contact. Now there is asingle contact where there used to be two, and the stored long contact ID pointsnowhere.

The lookup key helps resolve the contact in this case. The key is a stringthat concatenates the server-side identities of the raw contacts. Yourapplication can use that string to find a contact, regardless whether the rawcontact is aggregated with others or not.

If performance is a concern for your application, you might want to storeboth the lookup and the long ID of a contact and construct a lookup URI out ofboth IDs, as shown here:

Uri lookupUri = getLookupUri(contactId, lookupKey)

When both IDs are present in the URI, the system will try to use the long IDfirst. That is a very quick query. If the contact is not found, or if the onethat is found has the wrong lookup key, the content provider will parse thelookup key and track down the constituent raw contacts. If your appbulk-processes contacts, you should maintain both IDs. If your app works with asingle contact per user action, you probably don't need to bother with storingthe long ID.

Android itself uses lookup URIs whenever there is a need to reference a contact,such as with shortcuts or Quick Contact, and also during editing or even viewinga contact. The latter case is less obvious — why would a contact ID changewhile we are simply viewing the contact? It could change because there might bea sync going in the background, and the contact might get automaticallyaggregated with another while being viewed.

In summary: whenever you need to reference a contact, we recommend that youdo so by its lookup URI.



自己验证后的结果

每条raw_contact除了自己的id外,还有一个引用CONTACT_ID以表明其所属的contact,

每条contact会有一个NAME_RAW_CONTACT_ID来表示它用来命名的那条raw_contact的id,

即多条raw_contact和contact是一对多的关系,其中的CONTACT_ID字段表明所指向的contact id,

contact中的name_raw_contact_id只是表明用来命名的那条raw_contact的id,光用contact中的字段不能表明哪些raw_contact属于它,必须与raw_contact表联合起来根据contact id才能查到