How to fetch all contacts from local phonebook and google contacts together?

亡梦爱人 提交于 2019-12-11 19:45:57

问题


I am trying to fetch contacts from the phonebook in my Android application. But it fetches the contacts that are present only in the local phone storage. I need to fetch all the contacts including the ones synced to the device using various accounts like Google. That is currently not happening. I am using a RecyclerView to display the contacts fetched.

I have tried using https://github.com/mirrajabi/rx-contacts2 library for fetching asynchronously. But that doesn't include Google contacts as well. Then I tried using Android's built-in CotentResolver

Contact contact;

        ContentResolver contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
        if (cursor != null) {
            if (cursor.getCount() > 0) {
                while (cursor.moveToNext()) {

                    int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
                    if (hasPhoneNumber > 0) {
                        String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
                        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

                        contact = new Contact(Long.parseLong(id));
                        contact.setDisplayName(name);

                        Cursor phoneCursor = contentResolver.query(
                                ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                                null,
                                ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                                new String[]{id},
                                null);
                        if (phoneCursor != null) {
                            if (phoneCursor.moveToNext()) {
                                String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                                Set<String> phoneNumbers = new HashSet<>();
                                phoneNumbers.add(phoneNumber);
                                contact.setPhoneNumbers(phoneNumbers);
                            }
                            phoneCursor.close();
                        }


                        Cursor emailCursor = contentResolver.query(
                                ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                                null,
                                ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
                                new String[]{id}, null);
                        if (emailCursor != null) {
                            while (emailCursor.moveToNext()) {
                                String emailId = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                            }
                            emailCursor.close();
                        }
                        listContacts.add(contact);
                    }
                }
            }
        cursor.close();
}

Currently, I am trying to fetch the contacts synchronously and it hangs up the main thread. It would be really helpful if you could suggest some ways to do that asynchronously. When doing so I also require a trigger to know when the task is completed.


回答1:


Your code should work on all contacts synced to the device, including Google contacts (assuming the Google account is installed, and the contacts sync is enabled).

However, your code has some bugs, and can be greatly improved, currently for a device with 500 contacts, you are doing ~1000 queries. All the data you need is on a single table called Data so you can get everything in a single quick query, see here:

Map<Long, Contact> contacts = new HashMap<>();

String[] projection = {Data.CONTACT_ID, Data.DISPLAY_NAME, Data.MIMETYPE, Data.DATA1};
String selection = Data.MIMETYPE + " IN ('" + Phone.CONTENT_ITEM_TYPE + "', '" + Email.CONTENT_ITEM_TYPE + "')";
Cursor cur = cr.query(Data.CONTENT_URI, projection, selection, null, null);

while (cur.moveToNext()) {
    long id = cur.getLong(0);
    String name = cur.getString(1);
    String mime = cur.getString(2); // email / phone
    String data = cur.getString(3); // the actual info, e.g. +1-212-555-1234

    // get the Contact class from the HashMap, or create a new one and add it to the Hash
    Contact contact;
    if (contacts.containsKey(id)) {
        contact = contacts.get(id);
    } else {
        contact = new Contact(id);
        contact.setDisplayName(name);
        // start with empty Sets for phones and emails
        contact.setPhoneNumbers(new HashSet<>());
        contact.setEmails(new HashSet<>());
        contacts.put(id, contact);
    } 

    switch (mime) {
        case Phone.CONTENT_ITEM_TYPE: 
            contact.getPhoneNumbers().add(data);
            break;
        case Email.CONTENT_ITEM_TYPE: 
            contact.getEmails().add(data);
            break;
    }
}
cur.close();

Notes:

  1. I've changed your listContacts to a HashMap called contacts so we can quickly find an existing contact
  2. I've added setEmails, getPhoneNumbers and getEmails to your Contact class


来源:https://stackoverflow.com/questions/57107930/how-to-fetch-all-contacts-from-local-phonebook-and-google-contacts-together

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!