Hi all I am trying to get contact information from the contact database using ContentResolver with these field want to get name, number, FORMATTED_ADDRESS, PHOTO
details for a contact in one single query.
So basically I need to make 3 queries per contact to obtain these
details.
What I want to know is that, is there a simpler and more efficient way
to achieve what this.
but using the below code i am getting exception.
java.lang.IllegalArgumentException: Invalid column data1
Can any body help me for finding the solution for the same.
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS,
ContactsContract.CommonDataKinds.Photo.PHOTO};
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '1'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor contacts = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
Maybe problem will be at selection. Replace yours method with mine.
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS,
ContactsContract.CommonDataKinds.Photo.PHOTO};
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?";
String[] selectionArgs = { String.valueOf(1) };
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor contacts = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
You should always use parametrized statements. Your approach is dangerous. And your URI was bad.
Here you go
Replace
ContactsContract.Contacts.CONTENT_URI;
with
ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
Related
I have a requirement when I need to get the Contact name of the selected numbers from the ANDROID_CONTACTS.
I can get the name of a particular number using ->
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor cursor = cr.query(uri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null);
if (cursor == null) {
return;
}
How can I pass a list of numbers and get their respective names?
Here's the naive approach:
String[] phones = new String[] { "(212) 555-1111", "(212) 555-2222", "(212) 555-3333"};
String selection = Phone.NUMBER + "IN (?,?,?)";
String[] selectionArgs = phones;
String[] projection = new String[] { Phone.NUMBER, Phone.CONTACT_ID, Phone.DISPLAY_NAME };
Cursor cur = getContentResolver().query(Phone.CONTENT_URI, projection, selection, selectionArgs, null);
DatabaseUtils.dumpCursor(cur); // dumps the cursor to logcat
However, this will only work if you enter the phone number in exactly the same format as it is stored in the ContactsContract DB under NUMBER.
The nice thing about the PhoneLookup.CONTENT_FILTER_URI API you've used is that the format of the number doesn't matter, it'll find it in the DB in any format you use.
To replicate something like that, you can try using another field called NORMALIZED_NUMBER which should always hold the number in a specific format called E164.
So you can run a query like this:
String[] e164_phones = new String[] { "+12125551111", "+12125552222", "+12125553333"};
String selection = Phone.NUMBER + "IN (?,?,?)";
String[] selectionArgs = e164_phones; // all phones here must be in e164 format
String[] projection = new String[] { Phone.NUMBER, Phone.CONTACT_ID, Phone.DISPLAY_NAME };
Cursor cur = getContentResolver().query(Phone.CONTENT_URI, projection, selection, selectionArgs, null);
You'll probably need a way to convert a phone number to E164 format for this code, check out this answer then.
I am implementing an AutocompleteView to search phone numbers. The code is working fine except in some conditions.
My Code :
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.TYPE};
String selection = ContactsContract.CommonDataKinds.Phone.NUMBER + " LIKE ?";
String[] selectionArgs = new String[]{"%" + charSequence.toString() + "%"};
Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
This code is working fine where there is no space in the phone numbers. For example if i enter '123' in my autocompleteView, it is able to find phone numbers like '9123456789' or '8283929383' but it is not able to find numbers '9123 456 789' or '912 3456 789'
I even tried implementing this with ContactsContract.PhoneLookup API but with this, it didnt work at all.
Code with ContactsContract.PhoneLookup API:
String[] projection = new String[]{ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup.NUMBER, ContactsContract.PhoneLookup.TYPE};
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(charSequence.toString()));
Cursor cursor = context.getContentResolver().query(uri, projection, null, null, ContactsContract.PhoneLookup.DISPLAY_NAME + " ASC");
Any help is appreciated.
Instead of using ContactsContract.CommonDataKinds.Phone.NUMBER, use ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER (this return phone numbers in E164 format)
I have a contact list in a sort order. But in my contact list the name is duplicating with same number. I think the issue is because of the contact list sync with different account.
I check with Hash map. But when I using hash map the result is not sorted with name .
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION,
null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE NOCASE ASC");
if (cursor != null) {
try {
int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
String nameContact = cursor.getString(nameIndex);
finally {
cursor.close();
}
}
Adapter
holder.name.setText(itemListPogo.get(position).getItemName());
Can anyone please help to avoid the duplication in name.
You're seeing duplicate contacts because they belong to different accounts. i.e. Same number can show up 3 times if it is synced with Facebook, WhatsApp, and Google account. You can find more information here Android Account Manager
This is how you can use column ContactsContract.RawContacts.ACCOUNT_TYPE to filter and retrieve contacts associated with a single account only.
String[] projection = new String[] {
ContactsContract.RawContacts._ID,
ContactsContract.RawContacts.ACCOUNT_TYPE,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.PHOTO_URI,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Photo.CONTACT_ID };
String selectionFields = ContactsContract.RawContacts.ACCOUNT_TYPE + " = ?";
String[] selectionArgs = new String[]{"com.google"};
Cursor cursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection,
selectionFields,
selectionArgs,
ContactsContract.Contacts.DISPLAY_NAME
);
In this code, only contacts that are associated with Google Account are selected. Similarly, if you want to get list of WhatsApp Contacts only you can replace "com.google" with "com.whatsapp"
I will recommend you to use where my searching ends, it will give you fastest result.
public static List<ContactDTO> getPhone(Context context) {
List<ContactDTO> contactList = new ArrayList<ContactDTO>();
ContentResolver cr = context.getContentResolver();
String[] PROJECTION = new String[] {
ContactsContract.RawContacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.PHOTO_URI,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Photo.CONTACT_ID };
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String filter = ""+ ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0 and " + Phone.TYPE +"=" + Phone.TYPE_MOBILE;
String order = ContactsContract.Contacts.DISPLAY_NAME + " ASC";// LIMIT " + limit + " offset " + lastId + "";
Cursor phoneCur = cr.query(uri, PROJECTION, filter, null, order);
while(phoneCur.moveToNext()) {
ContactDTO dto = new ContactDTO();
dto.setName("" + phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
dto.setMobileNo("" + phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
dto.setPhotoUrl("" + phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI)));
dto.setContactId("" + phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID)));
contactList.add(dto);
}
phoneCur.close();
return contactList;
}
where ContactDTO is Simple POJO class.
I think the issue is because of the contact list sync with different
account.
Yes, your contact list sync many account. You should filter contact with Account type : ContactsContract.CommonDataKinds.Phone.ACCOUNT_TYPE_AND_DATA_SET.
Account you can research in :
https://developer.android.com/reference/android/accounts/AccountManager.html
You can search for the aggregated Contact instead of all RawContacts. This will give you only 1 contact with the given name (like in the Contacts app).
Example (changing your code):
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, // Honeycomb+ should use this
ContactsContract.CommonDataKinds.Phone.NUMBER
};
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(
ContactsContract.Contacts.CONTENT_URI,
PROJECTION,
null,
null,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " COLLATE NOCASE ASC");
if (cursor != null) {
try {
int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY);
String nameContact = cursor.getString(nameIndex);
finally {
cursor.close();
}
}
Source: https://developer.android.com/reference/android/provider/ContactsContract.Contacts.html
I'm trying do retrieve a list of contacts in phonebook and SIM, excluding contacts from skype, google, facebook and so on. I use the following code, but it works only on Samsung devices, I think because "vnd.sec.contact.phone" and "vnd.sec.contact.sim" used as selection arguments for ACCOUNT_TYPE field are both vendor related. How rewrite this code in a more "generic" way?
private Cursor getContactsNew()
{
// Run query
Uri uri = ContactsContract.RawContacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.RawContacts._ID,
ContactsContract.RawContacts.CONTACT_ID,
ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY,
ContactsContract.RawContacts.ACCOUNT_TYPE
};
String selection = ContactsContract.RawContacts.ACCOUNT_TYPE + "= ? OR " + ContactsContract.RawContacts.ACCOUNT_TYPE + "= ?";
String selectionArgs = new String[] { "vnd.sec.contact.phone", "vnd.sec.contact.sim" };
String sortOrder = ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY + " COLLATE LOCALIZED ASC";
ContentResolver cr = getContentResolver();
return cr.query(uri, projection, selection, selectionArgs, sortOrder);
}
This tutorial should help you out to fetch contacts from an android device :
http://www.c-sharpcorner.com/UploadFile/1e5156/fetch-contacts-from-android-phone-in-android-studio/
Lemme know if it helped out
I'm trying to write a very basic app that reads from the contacts content provider and pulls the contacts from a specific group name. How do I set the selection arguments so that the contacts information is pulled from a specific group?
I apologize if this has been answered elsewhere. I have searched and failed to find a good example on how to set selectionArgs so sort through information.
private Cursor getContacts() {
// Run query
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME};
String selection = ContactsContract.Contacts.STARRED + " = '"
+ ("1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC";
return managedQuery(uri, projection, selection, selectionArgs,
sortOrder);
}
Thanks for the help!