Android Contacts : The Tough Part
Kirtan Thakkar
Life is all about learningIf you have ever been trying to retrieve a list of contacts with the phone numbers and emails in your application, you might have struggled initially. The same happened with me. But, when I decided to dive deeper, it was easy to understand (actually!). We will go through the basic structure to understand how they are stored (so that we can query correctly) and code snippet to quickly retrieve the list of contacts.
Let's quickly understand first how all the queries are working internally to fetch the data we want.
The basic structure of the contacts stored on your device is like this:
Let's understand what each of them is storing.
- Contact
- ContactsContract.Contacts table
- Rows represnts different people aggregated based on the raw contacts.
- Raw Contact
- ContactsContract.RawContacts table
- It contains the data of a user for a specific account type. Say there are 2 different account for your number on your device, one for google account and other for whatsapp. These both are 2 different raw contacts which will be aggregated in the Contact table. You might have seen a special row for the whatsapp number when you see the contact details in your phone's contacts application. So, that's the 2 different raw contacts aggregated based on the data in each of them to represent the single contact.
- Data
- ContactsContract.Data table
- It stores the data of a raw contact like email addresses and phone numbers in each rows. Say one record for your phone number and another for your email address.
So, you now understood what tables will get you what types of data. Now, let's see what are some common fields which can help us with the data we want.
Each table's _ID
column is the primary key of the table. So, ContactsContract.Contacts table's _ID
will give you unique id of a single contact. But you may not use _ID
of ContactsContract.RawContacts to get the data of the same person from the ContactsContract.Contacts table. It might be different.
Below points will clear how they all are connected:
- ContactsContract.Data table has a
RAW_CONTACT_ID
column which says that this data record is of which Raw Contact. - ContactsContract.Data table and ContactsContract.RawContacts table has a
CONTACT_ID
column which is the_ID
of the ContactsContract.Contacts table.
Refer to the below image. It will help you understand this visually.
Now, let's understand how the data is stored in the ContactsContract.Data table, because that is the place where we need to query for the actual data.
ContactsContract.Data table has the MIMETYPE
column which defines which type of data is stored in that record, for example phone number or email address. DATA1
column contains the actual data based on the mime type defined. So, for example it will contain an actual phone number of the person if mime type is phone.
I found the below image on the stackoverflow post which helped me a lot to understand. Here is the image:
This will make many of the things pretty clear. So, now lets code it to access the list of contacts really fast.
Please refer to the below function which will retrieve the list of contacts in the Friend
bean/model class.
This function provides a list of contacts which contains an email address or a phone number. And the data we are getting is Name, Email and Photo uri of the contact.
So, we are querying everything from the ContactsContract.Data table and then merging the data based on the CONTACT_ID
of the record.
This will give us the results pretty fast rather than querying by phone no and querying again for email address of that person. We get all the records in the single query instead of the nested queries which you may have found on some other stackoverflow questions or other sites. Because of this, performance is very good. You can now use the RecyclerView to display your records.
So, that's it. Hope you have now understood how things works. Let me know in the comments if you have any doubts.