This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to look-up a contact's name from their phone number on Android?
How to get nick name from phone number in android.What are content provider used.
Use the following code:
String [] projection = { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME };
Cursor cursor =
this.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
projection, null, null, null);
if (cursor.moveToNext()) {
int displayNameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
String displayName = cursor.getString(displayNameIdx);
}
I am not entirely sure you need the display name, but you can get further details if you get to use ContactsContract.CommonDataKinds.StructuredName:
String [] projection = { ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME };
String where = ContactsContract.Data.CONTACT_ID
+ " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
String[] whereParameters =
{ contactId, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE };
Cursor cursor =
this.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
projection, where, whereParameters, null);
EDIT: Ah and now as I see you want to map the nickname to a phone number. This is how you select the contact_id out of given phone number:
String [] projection =
{ ContactsContract.CommonDataKinds.Phone.CONTACT_ID };
Cursor phoneCursor =
this.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, ContactsContract.CommonDataKinds.Phone.NUMBER + " = ?",
new String[]{number}, null);
int idIndex = phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID);
while (phoneCursor.moveToNext()) {
String id = phoneCursor.getString(numberIndex);
Log.i(LOG_TAG, "This is the contact id associatated with the given number" + id);
}
phoneCursor.close();
Related
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 am developing an Android app and want to receive my local contacts. To be exact I want to display all contacts which have an email address. My current approach looks like this
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
private static final String[] CONTACT_PROJECTION = new String[] {
Email.CONTACT_ID,
Contacts.DISPLAY_NAME_PRIMARY,
Email.ADDRESS,
};
Cursor data = mResolver.query(Data.CONTENT_URI,
CONTACT_PROJECTION,
Data.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "'",
null, Contacts.DISPLAY_NAME_PRIMARY + " ASC");
The problem using this query is, that the result contains rows that doesn't match a contact in my local address book. Probably I used those email addresses before but didn't saved it to my address book.
I have already tried another approach where I made a query on Contacts.CONTENT_URI with Contacts._ID. This id is used as a foreign key to match the contacts in a second query against their emails. The solution was a nested cursor and the runtime was really slow. For a hundred contacts the query took more than two seconds to match. This is a reason for using the async CursorLoader but I want to avoid it if possible.
Any suggestions? Thanks in advance
#Edit 1:
Unfortunately both solutions don't archive the desired improvement.
For example, when I write a new email to a previous unknown address with my gmail app afterwards the address shows up in both querys with an contact id but not in my normal address book. This kind of "contacts" flood my query.
Could it be related to the value of ContactsContract.CommonDataKinds.Email.TYPE?
#Edit 2:
I found an interesting flag Contacts.IN_VISIBLE_GROUP + "=1". It seems to filter the unwanted addresses.
Has somebody any experience with it? I don't want to filter to much.
This is what I am using in my app:
public void readContacts(){
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
System.out.println("name : " + name + ", ID : " + id);
// get the phone number
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
String phone = pCur.getString(
pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
System.out.println("phone" + phone);
}
pCur.close();
// get email and type
Cursor emailCur = cr.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
new String[]{id}, null);
while (emailCur.moveToNext()) {
// This would allow you get several email addresses
// if the email addresses were stored in an array
String email = emailCur.getString(
emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
String emailType = emailCur.getString(
emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
System.out.println("Email " + email + " Email Type : " + emailType);
}
emailCur.close();
}
}
}
}
I have attached one of the functions used in my project. Point of intrest would be selection and selection args.
Snippet
selection = ContactsContract.CommonDataKinds.Email.DATA + " != ?";
selectionArgs = new String[]{""};
This says selection is based on email data and it should not be null.
Similarly you can add any of the selection params as per your need.
Entire Function
public Cursor getInitCursorLoader() {
String[] PROJECTION = null;
String selection = null;
String[] selectionArgs = new String[0];
String order = null;
Uri contentURI = null;
switch (mFriendType) {
case EMAIL:
PROJECTION = new String[]{
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts._ID,
ContactsContract.Contacts.PHOTO_ID,
ContactsContract.CommonDataKinds.Email.TIMES_CONTACTED,
ContactsContract.CommonDataKinds.Email.DATA};
selection = ContactsContract.CommonDataKinds.Email.DATA + " != ?";
selectionArgs = new String[]{""};
contentURI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
order = ContactsContract.CommonDataKinds.Email.TIMES_CONTACTED + " DESC";
break;
case SMS:
PROJECTION = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.PHOTO_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.TIMES_CONTACTED,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.TYPE};
selection = ContactsContract.CommonDataKinds.Phone.TYPE + " = ?";
selectionArgs = new String[]{String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)};
contentURI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
order = ContactsContract.CommonDataKinds.Phone.TIMES_CONTACTED + " DESC";
break;
}
return mContext.getContentResolver().query(contentURI, PROJECTION, selection, selectionArgs, order);
}
i have an HTC legend.In its phone contacts it shows 4-5 contacts.But when i query it in my application it shows nearly 45 contacts.I think its gmail contacts.
String[] Projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_ID,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.STARRED};
Cursor cursor = managedQuery(ContactsContract.Contacts.CONTENT_URI, Projection, null, null, null);
I am getting all the details with photo as well in a listview. Now i need to get particular contact details like all his phone numbers,emails,photo etc.For this i am writing this query
final String[] projection = new String[] {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.IS_PRIMARY,
};
final Cursor phone = managedQuery(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?",
new String[]{contactId},
null);
> if(phone.moveToFirst()) {
> final int contactNumberColumnIndex =
> phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
> final int contactTypeColumnIndex =
> phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
i am getting all the details of the phone contact but not all other contacts.
i have read that all these details are stored in shared table(ContactsContract.Data.CONTENT_URI), but i am not getting exactly what to do go get this done.
Can someone help me figure out how to do this.
Thanks
You can do something like:
getContentResolver().query(
RawContactsEntity.CONTENT_URI,
// projection
new String[] {
BaseColumns._ID,
RawContactsEntity.MIMETYPE,
// DATA columns are interpreted according to MIMETYPE
// Project only union of data columns needed
RawContactsEntity.DATA1,
RawContactsEntity.DATA2,
RawContactsEntity.DATA3,
RawContactsEntity.DATA4,
RawContactsEntity.DATA7,
RawContactsEntity.DATA9,
RawContactsEntity.DATA10,
},
// selection
RawContactsEntity.DELETED + "<>1 AND " +
RawContactsEntity.MIMETYPE + " IN ('" +
StructuredName.CONTENT_ITEM_TYPE + "','" +
Email.CONTENT_ITEM_TYPE + "','" +
Phone.CONTENT_ITEM_TYPE + "','" +
StructuredPostal.CONTENT_ITEM_TYPE + "','" +
Organization.CONTENT_ITEM_TYPE + "')",
// selection params
null,
// sorting
null);
Next iterate through cursor, and first read MIME type:
final String mimeType = cursor.getString(cursor.getColumnIndex(
RawContactsEntity.MIMETYPE));
And depends on MIME type read corresponding data kind:
if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
readNameData(cursor);
} else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
addEmailData(cursor);
}
and so on.
I have a big performance issue in my app. After going through traceview i found that most of my app's performance has been consumed by cursors. So i was wondering is there any alternative to Cursors for dealing with device contact list. And if there is no alternative then please advise me how to deal with cursors so it won't slow down your app.
Please HELP!!
Thanks.
This part of my code has performance issue :-
public void getDisplayName()
{
Cursor c1 = this.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
String personName = null, number = null;
try
{
Log.e(TAG, "I am here!!");
if(c1.getCount() > 0)
{
Log.e(TAG, "I am here2!!");
while(c1.moveToNext())
{
HashMap<String,String> item = new HashMap<String,String>();
String id = c1.getString(c1.getColumnIndex(Contacts._ID));
personName = c1.getString(c1.getColumnIndex(Contacts.DISPLAY_NAME));
item.put("Name", personName);
Cursor cur = this.getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI, null, CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{id}, null);
while(cur.moveToNext())
{
Log.e(TAG, "I am here!!3");
number = cur.getString(cur.getColumnIndex(CommonDataKinds.Phone.NUMBER));
item.put("Number", number);
}
displayName.add(item);
}
}
}
finally
{
c1.close();
}
}
How to fetch a contact name and number without using Cursors?
That is not possible.
I have a big performance issue in my app.
Rather than using a single query, you use N+1 queries, where N is the number of rows returned by the other query. This is guaranteed to give you poor performance compared to just doing a single query.
You can get the user's name and _ID along with the phone numbers:
String[] PROJECTION=new String[] { Contacts._ID,
Contacts.DISPLAY_NAME,
Phone.NUMBER
};
Cursor c=a.managedQuery(Phone.CONTENT_URI, PROJECTION, null, null, null);
Also, never call getColumnIndex() in a loop, since the value never changes.
I was working on same code and I need email and phone numbers both in first approach It took around 35 seconds to fetch 612 contacts, when I optimized it, it took 2 seconds to fetch 612 contacts
my code.
ContentResolver cr = context.getContentResolver();
String[] projection = new String[] { Contacts.DISPLAY_NAME, Phone.NUMBER };
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?";
String[] selectionArgs = { String.valueOf(1) };
Cursor cur = cr.query(Phone.CONTENT_URI, projection, selection, selectionArgs, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String phNo = cur.getString(cur.getColumnIndex(Phone.NUMBER));
ContactModel contactModel = new ContactModel();
contactModel.setName(name);
contactModel.setPhoneNumber(phNo);
contactList.add(contactModel);
}
}
String[] projectionEmail = new String[] { Contacts.DISPLAY_NAME, Email.ADDRESS };
String selectionEmail = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?";
String[] selectionArgsEmail = { String.valueOf(1) };
Cursor curEmail = cr.query(Email.CONTENT_URI, projectionEmail, selectionEmail, selectionArgsEmail, null);
if (curEmail.getCount() > 0) {
while (curEmail.moveToNext()) {
String Emailname = curEmail.getString(curEmail.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String email = curEmail.getString(curEmail.getColumnIndex(Email.ADDRESS));
ContactModel contactModel = new ContactModel();
contactModel.setName(Emailname);
contactModel.setEmailId(email);
contactList.add(contactModel);
}
}
`
I'm working on android application in which I take backup of all contact information and then restore, I retrieve all information of contact,
For example:
Display Name
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null,null, null, null)
String name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
Phone Number
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId,null, null);
Similary
But I unable to get "Internet Call" value.
Kindly anyone tell in which class I will get information about Internet Call information.
Dont know if this is the best way, but it worked, I am fairly new new to android.
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS,
ContactsContract.CommonDataKinds.SipAddress.TYPE,
};
String selection =
ContactsContract.Data.MIMETYPE+" ='"
+ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE+"'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME+ " COLLATE LOCALIZED ASC";
Cursor cursor = managedQuery(uri, projection, selection, selectionArgs, sortOrder);
It seems that the phone number is stored in misc information data and you have search on the mime type.
HTH
g.
i have tested. i am able to get internet call value. try below code.
Uri uri = ContactsContract.Contacts.CONTENT_URI;
ContentResolver cr = getContentResolver();
Cursor cur=cr.query(uri, null, null, null, sortOrder);
if(cur.getCount()>0){
while(cur.moveToNext()){
if(Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)))> 0) {
String internetWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
String[] internetWhereParams = new String[]{id,ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE};
Cursor internetCur = cr.query(ContactsContract.Data.CONTENT_URI, null, internetWhere, internetWhereParams, null);
if (internetCur.moveToFirst()) {
String internetCall = internetCur.getString(internetCur.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS));
Log.e(TAG, "internet Call: " + internetCall);
} internetCur.close();
}
}
} cur.close();