I have sorted and listed my phone contacts in to an arraylist but ,i got many duplicates of same contact names in the list .How this happens? how to avoid this?
This is what i have tried,
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null,
"(" + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + ") ASC");
while (cursor.moveToNext()) {
try {
name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
phonenumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contact_names_list.add(name);
phone_num_list.add(phonenumber);
} catch (Exception e) {
e.printStackTrace();
}
can anyone help??
No one here seems to answer your question.
The reason you're seeing duplicate contacts is that you're querying for phones not contacts.
In Android there are 3 main tables:
Contacts table - has one item per contact
RawContacts table - has one item per-contact per-account (such as Google, Outlook, Whatsapp, etc.) - multiple RawContacts are linked to a single Contact
Data table - has one item per detail (name, email, phone, address, etc.) - each data item is linked to a single RawContact, and multiple Data rows are linked to each RawContact.
You're querying on CommonDataKinds.Phone.CONTENT_URI which is a part of the Data table, so if a contact has more then one phone, and/or it has the same phone from multiple sources (e.g. Google and Whatsapp) you'll get the same phone with the same CONTACT_ID more then once.
The solution would be, to use a HashMap (rather then a HashSet), where the key is CONTACT_ID, so you can display multiple phones per contact:
String[] projection = new String[] { CommonDataKinds.Phone.CONTACT_ID, CommonDataKinds.Phone.DISPLAY_NAME, CommonDataKinds.Phone.NUMBER };
Cursor cursor = getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI, projection, null, null, null);
HashMap<Long, Contact> contacts = new HashMap<>();
while (cursor.moveToNext()) {
long id = cursor.getLong(0);
String name = cursor.getString(1);
String phone = cursor.getString(2);
Contact c = contacts.get(id);
if (c == null) {
// newly found contact, add to Map
c = new Contact();
c.name = name;
contacts.put(id, c);
}
// add phone to contact class
c.phones.add(phone);
}
cursor.close();
// simple class to store multiple phones per contact
private class Contact {
public String name;
// use can use a HashSet here to avoid duplicate phones per contact
public List<String> phones = new ArrayList<>();
}
If you want to sort your HashMap by name:
List<Contact> values = new ArrayList<>(contacts.values());
Collections.sort(values, new Comparator<Contact> {
public int compare(Contact a, Contact b) {
return a.name.compareTo(b.name);
}
});
// iterate the sorted list, per contact:
for (Contact contact : values) {
Log.i(TAG, "contact " + contact.name + ": ");
// iterate the list of phones within each contact:
for (String phone : contact.phones) {
Log.i(TAG, "\t phone: " + phone);
}
}
You can try with HashSet.
public class HashSet extends AbstractSet implements Set,
Cloneable, Serializable
Duplicate values are not allowed.
Code Structure
HashSet<String> hashSET = new HashSet<String>();
hashSET.add("AA");
hashSET.add("BB");
hashSET.add("CC");
hashSET.add("AA"); // Adding duplicate elements
Then
Iterator<String> j = hashSET.iterator();
while (j.hasNext())
System.out.println(j.next()); // Will print "AA" once.
}
Now SORT your Hashset Values using TreeSet.
TreeSet implements the SortedSet interface so duplicate values are not
allowed.
TreeSet<String> _treeSET= new TreeSet<String>(hashSET);
May be in your contacts having multiple groups, and that group will be a WhatsApp,Google etc..Go to your contacts and search that contact having whatsApp account. will showing double entry with different Group
you should use or change your ContactsBean , in your Bean use HashSet
Note: HashSet can avoid duplicate entry more
HashSet contains unique elements only,it can avoid same key element form HashSet
Example bean
public class ContactBean {
private HashSet<String> number = new HashSet<String>();
public void setNumber(String number) {
if (number == null)
return;
this.number.add(number.trim());
}
public HashSet<String> getNumber() {
return this.number;
}
}
Simple Example
//Creating HashSet and adding elements
HashSet<String> hashSet=new HashSet<String>();
hashSet.add("Dhruv");
hashSet.add("Akash");
hashSet.add("Dhruv"); //Avoiding this entry
hashSet.add("Nirmal");
//Traversing elements
Iterator<String> itr = hashSet.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
You can use HashSet for avoid duplication:-
HashSet<String> hset =
new HashSet<String>();
you can add like ArrayList in HashSet:-
hset.add(your_string);
OR
Convert your ArrayList to HashSet :-
Set<String> set = new HashSet<String>(your_arraylist_object);
HashSet avoid Duplicate Entry :)
I don't know why are you getting duplicate items from contacts, maybe phone contacts already have duplicate values.You can check that in Contacts app.
You should always use set data structure wherever you want to avoid duplicate items. You can find the better explanation and example here.
I think your duplication is because of Whatsapp contact interfering with contact . so you can use something like this
String lastPhoneName = "";
String lastPhoneNumber = "";
//IN YOUR CONTACT FETCHING WHILE LOOP , INSIDE TRY
String contactName = c.getString(c
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phNumber = c
.getString(c
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if (!contactName.equalsIgnoreCase(lastPhoneName) && !phNumber.equalsIgnoreCase(lastPhoneNumber)) {
lastPhoneName = contactName;
lastPhoneNumber = phNumber;
ContactModel model = new ContactModel();
model.setContact_id(contactid);
model.setContact_name(contactName.replaceAll("\\s+", ""));
model.setContact_number(phNumber.replaceAll("\\D+", ""));
list_contact_model.add(model);
}
this will check that previous number is same as old one than skip it . I hope You get your answer
HashSet add items in key/value pair and also remove duplicate entry from item set.
List<String> phone_num_list= new ArrayList<>();
// add elements to phone_num_list, including duplicates
Set<String> hs = new HashSet<>();
hs.addAll(phone_num_list);
phone_num_list.clear();
phone_num_list.addAll(hs);
Happy coding!!
I want to insert a new phone number with new contact id in the my SQLite. I need to know the maximum contact id in my contact, to ignore the saving same contact id. Is it possible to know the maximum contact id in Android? Thank you
From Contacts Table , you can get the last Contact Id by querying like shown below
final String sortOrder = ContactsContract.Contacts._ID+" DESC LIMIT 1";
Cursor lcursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,new String[] {ContactsContract.Contacts._ID,ContactsContract.Contacts.DISPLAY_NAME},null,null,sortOrder);
if (lcursor != null && lcursor.moveToFirst()) {
long id = lcursor.getLong(lcursor.getColumnIndex(ContactsContract.Contacts._ID));
String displayName = lcursor.getString(lcursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
Cursor will return only one entry and that entry will be the last contact_id in the contact's table
Note: This should not be done on Main thread, as it may take too much time if device Contact is more 1000+ contacts, so always be carefull of Querying the DataBase having large entries
Enjoy coding ! :)
I'm trying to get "notes" from a single contact. It added fine but retrieving it has been a problem.
String selection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" like'%" + sender +"%'";
String[] projection = new String[] { ContactsContract.CommonDataKinds.Note.NOTE};
Cursor c2 = getContentResolver().query(ContactsContract.Data.CONTENT_URI, projection, selection, null, null);
if (c2.moveToFirst()) {
notes = c2.getString(0);
}
It works fine with other values like name or phone number but can't seem to get notes to retrieve correctly. It retrieves a random value like email instead.
I believe that your problem is that not all rows in the table represent contact types that have notes. You have to request the proper MIME Type.
ContactsContract.CommonDataKinds.Note is an alias for the 'data1' column that is present on all rows, so when you get a row of a different MIME Type, it represents different data.
How to get contacts in Android should give you an idea of how to do this.
Is there an accepted/received way of checking to see if a person (phone number) is in the Contact List?
I'm hoping there's something I can call like this:
bool bInContactList = InContactList("1415922353");
It is not as simple as you want but you can query a Contacts content provider for the contact associated with a phone number:
Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor c = getContentResolver().query(lookupUri, new String[] {PhoneLookup._ID}, null, null, null);
if (c.getCount() > 0) {
// there is some contact
} else {
// there is no contacts with phoneNumber
}
The application needs android.permission.READ_CONTACTS permission to access contacts data.
You can check Android Developer site for further references about content providers and android.providers package documentation for the list of available standard providers in Android.
I am afraid you did not provide enough information about the language you are talking about. If you use Java -for example- you have a contains method (common to all collections) so, if you want to know if a certain String is contained in a collection you could do it by invoking this method:
boolean found = someCollection.conmtains("1415922353");
I'm trying to get a random contact from a phone's contact list, but without noticeably slowing down the phone. That means that I can't just grab all the contacts and stick them into an array and pick a random one from that array. I'd like to be able to get a random contact without having to get all of the contacts first.
Is this possible, and if so, how would I go about doing it?
Updated to use non-deprecated code. Query based on this answer: How to read contacts on Android 2.0
Cursor managedCursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
Then it's just a matter of getting the size of the Cursor:
int size = managedCursor.getCount();
get a random one, read it and check if it has phone numbers. If not, choose another one:
boolean found = false;
Random rnd = new Random();
while(!found) {
int index = rnd.nextInt(size);
managedCursor.moveToPosition(index);
String name = managedCursor.getString(people.getColumnIndex(PhoneLookup.DISPLAY_NAME));
found = Boolean.parseBoolean(managedCursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if (found) {
Cursor phones = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, null, null);
while (phones.moveToNext()) {
String phoneNumber = phones.getString(phones.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.d("Phone found:", phoneNumber);
}
phones.close();
}
}
I don't see how you could pick a random one otherwise. And this should not slow the phone down unless it's a really large contacts list.
Now it checks for the presence of phone numbers and reads all of them if found. If not, it chooses another entry.