22

I have a "dump" utility that I am using to study the ContactsContract since I don't quite get it in the documentation. When I dump the contacts it counts 263 records in the table, however, the contacts application on my device lists that I have 244 ("Displaying 244 contacts.")

Can someone explain the discrepancy?

My Sprint LG's Contacts App has display options for each of the accounts that I sync and I have gone in and checked all of them, so there shouldn't be any filtering.

The main URI that I am using in the utility is:

    Uri uriRawContacts = ContactsContract.RawContacts.CONTENT_URI;
    String[] projection = new String [] {
            ContactsContract.RawContactsEntity._ID,
            ContactsContract.RawContactsEntity.CONTACT_ID,
            ContactsContract.RawContactsEntity.DELETED,
            ContactsContract.RawContactsEntity.AGGREGATION_MODE,
    };
    Cursor cursorRaw = cr.query(uriRawContacts, projection, null, null, null);
    DumpCursor.dumpAnyCursor(getApplicationContext(), "RawContacts", cr, cursorRaw, ",");

Followed by (for each _ID in the above query):

                long rawContactId = Long.parseLong(anyCursor.getString(anyCursor.getColumnIndex(RawContacts.CONTACT_ID)));

                Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
                 Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);

                 Log.d(TAG, "rawContactUri: " + rawContactUri.toString());
                 Log.d(TAG, "entityUri: " + entityUri.toString());

                 Cursor c = cr.query(entityUri, new String[] { RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1 }, null, null, null);

I then loop through the first query, display all the columns in my projection, then, using the _ID field in the first query's loop, I issue the second query and dump all of its columns.

Bullets from the answer transposed here for convenience: Refer to the reference for more detailed explanation. More specifically, you are encouraged to read about the aggregation rules. Ref: Click here for the original cited text that follows

  • The Contacts database is divided into 3 tables contacts, raw contacts, and data.
  • Each table contains column (_ID) which is an auto incremented primary
    key.
  • The data table contains all the contact info like phone number, mail id,
    address etc.
  • The raw contacts points to the actual contact created. Hence we use the raw contacts while adding a contact.
  • The user cannot add any data in the contacts table. The data in this
    table is populated internally due to
    aggregation of contacts.

The reason your logic worked for some of the contacts is: _ID for contacts, raw contacts remains same until there is any contact aggregation taking place. Lets say you add two contacts with same name abc. Here the _ID for raw contacts increments twice while _ID for contacts increments only once as these two contacts gets merged due to the aggregation of contacts

Community
  • 1
  • 1
mobibob
  • 8,030
  • 17
  • 76
  • 126
  • The last approved Edit was incorrect. If you read the original, you will see the missing punctuation and the emphasis on the 3 tables. Then s/he makes a reference to that as "The data table, 'contacts' contains all the ..." You have modified the original author's correct statements. – mobibob Jun 22 '13 at 18:06

2 Answers2

24

This difference is due to RawContacts getting merged to Contacts due to the aggregation rule.

You add contact to RawContacts while the list displays Contacts. Hence the count difference.

Please find some description between Contacts, RawContacts and Data here. Even though the question is a different one you might be able to get the difference between Contacts and RawContacts.

CopsOnRoad
  • 109,635
  • 30
  • 367
  • 257
Manish Khot
  • 2,957
  • 1
  • 25
  • 37
  • 1
    Super answer and +1. I think the info is important enough that I am going to ref and transpose the six bullets from that answer into this Q&A. – mobibob Mar 11 '11 at 17:44
5

The three tables are commonly referred to by the names of their contract classes. The classes define constants for content URIs, column names, and column values used by the tables:

ContactsContract.Contacts table :- Rows representing different people, based on aggregations of raw contact rows.

ContactsContract.RawContacts table :- Rows containing a summary of a person's data, specific to a user account and type.

ContactsContract.Data table :- Rows containing the details for raw contact, such as email addresses or phone numbers.

for more info click

Mansukh Ahir
  • 3,546
  • 4
  • 36
  • 58
  • suppose I want to get the id that apps use to open chat intents, such as viber, how do I do that? For example, if Viber has a contact X, it has some ID for it Y, which is used to open an intent of chat with this contact , using: intent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://com.android.contacts/data/"+id)); intent.setPackage("com.viber.voip"); – android developer Mar 14 '16 at 11:53
  • I can't find the needed ID for this. Can you please help? I've made a post about it here: http://stackoverflow.com/q/35972329/878126 – android developer Mar 14 '16 at 13:50