2

There is multiple examples of how we could retrieve contacts in android the most common type is using ContactsContract like this:

ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(ContactsContract.contacts.CONTENT_URI,null,null,null,null);

while(cursor.moveToNext){
//get contact details
.........

}

My Question:

If users can save their contacts in three places phone, SIM, google_account. Then how I am able to use a method that retrieves all numbers that a user have on the phone?

Also as the contact list in the phone duplicates contacts how can we avoid getting a contact twice or 4 times or 5 times?

What would be the method that one must use to cover all possible contacts once?

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
data
  • 739
  • 6
  • 17

1 Answers1

1

Users can actually save contacts in many places, not just 3, e.g. if a user installs the Yahoo app, they can start storing contacts on Yahoo as well, same goes for Outlook, etc.

The ContactsContract covers all these options, and provides a single API to query for all contacts stored on the device. The different storage types are distinguished by ACCOUNT_NAME and ACCOUNT_TYPE at the RawContact level.

a Contact result you get from your query, is actually an aggregation of multiple RawContacts coming from one or more origins or ACCOUNT_TYPEs, so duplicate RawContacts on your SIM and Phone should aggregate into a single Contact

Here's some code to explore your own contacts on your device (this is very slow code, there are ways to improve performance significantly):

String[] projection = new String[] { Contacts._ID, Contacts.DISPLAY_NAME};
Cursor contacts = resolver.query(ContactsContract.Contacts.CONTENT_URI, projection, null, null, null);

while (contacts.moveToNext()) {

    long contactId = contacts.getLong(0);
    String name = contacts.getString(1);

    Log.i("Contacts", "Contact " + contactId + " " + name + " - has the following raw-contacts:");

    String[] projection2 = new String[] { RawContacts._ID, RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_NAME };
    Cursor raws = resolver.query(RawContacts.CONTENT_URI, null, RawContacts.CONTACT_ID, null, null);

    while (raws.moveToNext()) {

        long rawId = raws.getLong(0);
        String accountType = raws.getString(1);
        String accountName = raws.getString(2);

        Log.i("Contacts", "\t RawContact " + rawId + " from " + accountType + " / " + accountName);
    }
    raws.close();
}
contacts.close();
marmor
  • 27,641
  • 11
  • 107
  • 150
  • Thanks for your answer, may I ask: 1) Does this mean that even if I have duplicate contacts in my phone book I will query 1 contact when reading using cursor. 2) Is the SIM card considered an account in other words does ContactContract return contacts in SIM in addition to phone, google, yahoo? – data Aug 21 '18 at 11:40
  • (1) that's the way it should work, Android tries to aggregate raw-contacts it considers are duplicates into a single contact, in reality this doesn't always work flawlessly. (2) yes, they would be returned with ACCOUNT_TYPE `vnd.sec.contact.sim` (might variate slightly for certain vendors) – marmor Aug 21 '18 at 11:50
  • So from the answer you provided all contacts on all accounts: google, sim, phone, yahoo, viber, whatsapp will be returned? – data Aug 21 '18 at 11:52
  • In your opinion if I have a contacts on a server and want to loop through my contacts using the method above to check which number is on the server.....does it mean I will loop through raw contacts as much as there exist to check with server (it will take time) ..... If I have user A with 4 accounts does it mean that if I want to check user A on the server I must loop through all accounts or there is a primary account? – data Aug 21 '18 at 12:05
  • you can and should skip some accounts like whatsapp, viber, etc. and focus on "real" contacts storages like Google, Exchange, Yahoo. you can iterate over the list of sync-adapters to get a list of suitable SyncAdapters, and then limit your query to only contacts with ACCOUNT_TYPE on that list. See: https://stackoverflow.com/a/47001090/819355 – marmor Aug 21 '18 at 12:22
  • I read the link but can't understand how that will help me exclude other accounts, I loop through contact ==> then loop through raw contacts ==>these raw contacts can be 3 or more ..... should I exclude them while querying? Or there exist a way to get the primary raw contact? – data Aug 21 '18 at 13:12
  • And I cant say query if not whatapp or query if not viber .... becuase I can never know how many accounts are linked to each contact? – data Aug 21 '18 at 13:13
  • Can you please help me in [this question](https://stackoverflow.com/questions/51954469/android-contactscontract-class-how-to-ignore-non-primary-account-types) – data Aug 21 '18 at 18:13