Search code examples
androidandroid-contactsandroid-contentresolver

How can i get account type using ContentResolver?


How to retrieve account type (whatsapp,viber,etc..) using ContentResolver?
This is my code

ContentResolver cr = getContentResolver();
    Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null,null, null);

    if (cur.getCount() > 0) {
        while (cur.moveToNext()) {
            String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
            String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                Log.d("log : ","name : " + name + ", ID : " + id);

                // get the phone number
                Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
                        new String[]{id}, null);
                while (pCur.moveToNext()) {
                    String phone = pCur.getString(
                            pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    String phone1 = pCur.getString(
                            pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
                    Log.d("log : ","phone" + phone + " type : "+phone1);
                }
                pCur.close();

Solution

  • The data in Android's Contacts is split into 3 main tables:

    1. Contacts - each entry represents one contact, and groups together one or more RawContacts
    2. RawContacts - each entry represents data about a contact that was synced in by some SyncAdapter (e.g. Whatsapp, Google, Facebook, Viber), this groups multiple Data entries
    3. Data - The actual data about a contact, emails, phones, etc. each line is a single piece of data that belongs to a single RawContact

    The problem with your code is that you go over all Contacts, and then query for phones per contact. You're not querying the RawContact table which contains the ACCOUNT_NAME and ACCOUNT_TYPE you want. Plus, it's very inefficient to make hundreds of queries just to get all the phones on the device, you can do that with a single query instead.

    // First create a mapping from RAW_CONTACT_ID to ACCOUNT_TYPE (e.g. Whatsapp)
    
    Map<Long, String> rawContacts = new HashMap<Long, String>();
    String[] projection1 = {RawContacts._ID, RawContacts.ACCOUNT_TYPE};
    Cursor cur1 = cr.query(RawContacts.CONTENT_URI, projection1, null, null, null);
    while (cur1 != null && cur1.moveToNext()) {
        Long id = cur1.getLong(0);
        String account = cur1.getString(1);
        rawContacts.put(id, account);
    }
    
    // Now query for all the PHONES on the device (no need to query the Contacts table at all)
    
    String[] projection2 = { Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER, Phone.TYPE, Phone.RAW_CONTACT_ID };
    Cursor cur2 = cr.query(Phone.CONTENT_URI, projection2, null, null, null);
    
    while (cur2 != null && cur2.moveToNext()) {
        long id = cur2.getLong(0);
        String name = cur2.getString(1);
        String number = cur2.getString(2); // the actual info, e.g. +1-212-555-1234
        int type = cur2.getInt(3); // a numeric value representing type: e.g. home / office / personal
        long raw = cur2.getLong(4);
    
        Log.d(TAG, "contact: " + id + ", name: " + name + ", number: " + number + ", type: " + type + ", raw-id: " + raw + ", account-type: " + rawContacts.get(raw));
    }
    

    P.S. you can create a second HashMap with CONTACT_ID as key to group all the info about a single contact per contact.