Reputation: 1961
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
Upvotes: 1
Views: 1496
Reputation: 1
Here is quick solution i came up with
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
null,
null,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC ");
contactArray = new ArrayList<>();
String tempId = "";
if(cursor != null && cursor.getCount() > 0){
while(cursor.moveToNext())
{
String contact_id = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
if(!tempId.equals(contact_id)){
String contact_name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String contact_number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String result = contact_id+"\n"+contact_name+"\n"+contact_number;
contactArray.add(result);
}
tempId = contact_id;
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, contactArray);
listView.setAdapter(adapter);
cursor.close();
Upvotes: 0
Reputation: 28179
You're getting duplicate contacts because you're actually reading RawContacts
, not contacts. Multiple RawContact
s 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:
Contacts
- each entry represents one contact, and groups together one or more RawContacts
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 entriesData
- 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 + ")");
}
Upvotes: 1