How to get non duplicated phone numbers from andro

2019-07-24 01:32发布

问题:

I am trying to get all contacts which have mobile numbers. I am able to fetch the contacts.But the problem is it gives me duplicate contacts.same phone number comes two times.

I used the following code to get contacts.

public static List<RawContact>  getAllContacts(Context context,Account account){
        Log.d(TAG, "*** Looking for local contacts with mobile number!!");
        String phoneNumber = null;
        String email = null;
        int numberOfContacts = 0;
        List<RawContact> newContacts = new ArrayList<RawContact>();
        Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
        String _ID = ContactsContract.Contacts._ID;
        String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
        String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;

        Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
        String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;

        List<RawContact> localNewContacts = new ArrayList<RawContact>();
        final ContentResolver contentResolver = context.getContentResolver();
        final Cursor cursor = contentResolver.query(CONTENT_URI,
                null,
                null,
                null,
                null);

        if(cursor.getCount()>0){
            numberOfContacts = 0;
            Log.d(TAG, "*** Looking for local contacts "+cursor.getCount());
            while(cursor.moveToNext()){
                String contact_id = cursor.getString(cursor.getColumnIndex(_ID));
                String name = cursor.getString(cursor.getColumnIndex(DISPLAY_NAME));
                int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(HAS_PHONE_NUMBER)));
                final long rawContactId = cursor.getLong(DirtyQuery.COLUMN_RAW_CONTACT_ID);
                if (hasPhoneNumber > 0) {
                    //This is to read multiple phone numbers associated with the same contact
                    Cursor phoneCursor = contentResolver.query(PhoneCONTENT_URI, null, ContactsContract.RawContacts.ACCOUNT_TYPE + " <> 'google' "+" AND "+ Phone_CONTACT_ID + " = ?", new String[]{contact_id}, null);
                    while (phoneCursor.moveToNext()) {
                        phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER));
                        Log.d(TAG,"Phone number is: "+phoneNumber);
                        RawContact rawContact = getRawContact(context, rawContactId);
                        Log.d(TAG, "Contact Name: " + rawContact.getBestName());
                        localNewContacts.add(rawContact);
                    }phoneCursor.close();
            }
            numberOfContacts++;
            Log.d(TAG, "numberOfContacts updated: "+numberOfContacts);
        }

    }
        return localNewContacts;
    }

How to solve this issue

回答1:

You're getting duplicate contacts because you're actually reading RawContacts, not contacts. Multiple RawContacts can and will contain info about a single person represented by a single Contact.

You need a single query over the Phones table, and organize the data using a HashMap from CONTACT_ID to Contact info, so you won't get duplicates.

The Contacts DB is organized in three 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

You're trying to make a query on the Contacts table, with projection of fields from the Data table, you can't do that.

You can use something like the following code, just convert the HashMap to work with your ContactModel object:

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

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

while (cur != null && cur.moveToNext()) {
    long id = cur.getLong(0);
    String name = cur.getString(1);
    String mime = cur.getString(2); // type of data (e.g. "phone")
    String data = cur.getString(3); // the actual info, e.g. +1-212-555-1234
    int type = cur.getInt(4); // a numeric value representing type: e.g. home / office / personal
    String label = cur.getString(5); // a custom label in case type is "TYPE_CUSTOM"

    String labelStr = Phone.getTypeLabel(getResources(), type, label);
    Log.d(TAG, "got " + id + ", " + name + ", " + kind + " - " + data + " (" + labelStr + ")");

    // add info to existing list if this contact-id was already found, or create a new list in case it's new
    List<String> infos;
    if (contacts.containsKey(id)) {
        infos = contacts.get(id);
    } else {
        infos = new ArrayList<String>();
        infos.add("name = " + name);
        contacts.put(id, infos);
    }
    infos.add(kind + " = " + data + " (" + labelStr + ")");
}