In my code I should display only phone contacts: I followed previous posts but I still display both phone and sim contacts. Here it is my code:
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String columIndex = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME;
String columIndexId = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
String numIndex = ContactsContract.CommonDataKinds.Phone.NUMBER;
Cursor cursor = getContentResolver().query(uri, null, null, null,ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC");
if(cursor!=null){
while(cursor.moveToNext()) {
ContactInfo ci = new ContactInfo();
ci.setIdContact(Integer.parseInt(cursor.getString(cursor.getColumnIndex(columIndexId))));
ci.setName(cursor.getString(cursor.getColumnIndex(columIndex)));
ci.setNumberTel(cursor.getString(cursor.getColumnIndex(numIndex)));
//if(!cursor.getString(cursor.getColumnIndex(columIndex)).equalsIgnoreCase(nome))
listContact.add(ci);
}
cursor.close();
}
These are all ContactInfo object and they will be showed in a list (listContact, which is an ArrayList).
It is really important for me because my application works good only on phone contacts and not on sim contacts.
You can try to replace your Cursor with this to exclude contacts on sim:
import android.provider.ContactsContract.RawContacts;
Cursor cursor = getContentResolver().query(
RawContacts.CONTENT_URI,
new String[] { RawContacts._ID, RawContacts.ACCOUNT_TYPE },
RawContacts.ACCOUNT_TYPE + " <> 'com.android.contacts.sim' AND "
+ RawContacts.ACCOUNT_TYPE + " <> 'com.anddroid.contacts.sim' AND " // HTC
+ RawContacts.ACCOUNT_TYPE + " <> 'vnd.sec.contact.sim' AND "
+ RawContacts.ACCOUNT_TYPE + " <> 'USIM Account' ",
null,
null);
I haven't tried this, modified from https://stackoverflow.com/a/4409453/262462
Note: on some phones you may need to exclude few other RawContacts.ACCOUNT_TYPE like com.anddroid.contacts.sim and vnd.sec.contact.sim, see https://stackoverflow.com/a/13656077/262462
Related
I am trying to fetch my phone contacts in alphabetical sort order.Its fetch name by fast but not getting sort order .I tried ContactsContract.Contacts.SORT_KEY_PRIMARY + " ASC" also ContactsContract.Contacts.DISPLAY_NAME + " ASC" but not getting good result.
My code is
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null,ContactsContract.Contacts.DISPLAY_NAME + " ASC");
while (phones.moveToNext())
{
String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.e("Tag ","Name " + name);
}
phones.close();
you have to get the sort order of your phone contacts like this:
int sort_order=Settings.system.getInt (getApplicationContext ().getContentResolver (),"android.contacts.SORT_ORDER");
now your cursor query will be like this:
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null,sort_order);
you can get contacts in alphabatical order:
Cursor cursor = getContentResolver.query(Phone.CONTENT_URI, null, null, null, Phone.DISPLAY_NAME + " ASC");
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 the following code to get contacts from content provider
String[] columns = new String[] {
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts._ID,
ContactsContract.Contacts.PHOTO_ID };
Cursor cursor = managedQuery(ContactsContract.Contacts.CONTENT_URI,
columns, null, null, null);
and i use this one to get the emails for a specific contact by their id:
Cursor emails = getContentResolver().query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID
+ " = " + contact.getContactId(), null, null);
my current implementation passes every row in the cursor and aquires its emails and stores them in an arrayList of java objects.
what i was wondering if it was possible to do is just query the content provider and return a cursor of just contacts with ids/name etc that have an email address listed.
this way has a long waiting period for getting the contact list. i am using this list for a list adapter. if i can get only the contacts that have an email i can use a cursor adapter in my list.
Is something like this possible? how can i speed up the process?
#CapDroid
Fixed working code from DArkO's post:
ContentResolver cr = context.getContentResolver();
String[] PROJECTION = new String[] { ContactsContract.RawContacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_ID,
ContactsContract.CommonDataKinds.Email.DATA,
ContactsContract.CommonDataKinds.Photo.CONTACT_ID };
String order = "CASE WHEN "
+ ContactsContract.Contacts.DISPLAY_NAME
+ " NOT LIKE '%#%' THEN 1 ELSE 2 END, "
+ ContactsContract.Contacts.DISPLAY_NAME
+ ", "
+ ContactsContract.CommonDataKinds.Email.DATA
+ " COLLATE NOCASE";
String filter = ContactsContract.CommonDataKinds.Email.DATA + " NOT LIKE ''";
Cursor cur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, PROJECTION, filter, null, order);
Your cursor will have essential IDs as well as names and email addresses. The performance of this code is great because it requests few columns only.
I solved this one, here is how its done:
UPDATE
String[] PROJECTION = new String[] { ContactsContract.RawContacts._ID,
ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.PHOTO_ID,
Email.DATA, ContactsContract.CommonDataKinds.Photo.CONTACT_ID };
String order = " CASE WHEN " + ContactsContract.Contacts.DISPLAY_NAME
+ " NOT LIKE '%#%' THEN 1" + " ELSE 2 END, "
+ ContactsContract.Contacts.DISPLAY_NAME + " COLLATE NOCASE";
String filter = Email.DATA + " NOT LIKE '' ) GROUP BY ( " + Email.DATA;
return mContent.query(Email.CONTENT_URI,
PROJECTION, filter, null, order);
I have setup 2 test contacts in my emulator.
I'm running the following query, it should pick them both out, populate my domain object, and add to a list. The output at the bottom should therefore be 2, but it is 5, why is this? (cursor.getCount() is 5 instead of 2)
I have stepped through each iteration of the while loop and it is retreving the same contact multiple times, but with different values for POSTCODE, such as the phone number
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
null, null, null, null);
List<MeCercanaContact> contacts = new ArrayList<MeCercanaContact>();
if (cursor.getCount() > 0)
{
while (cursor.moveToNext())
{
MyContact myContact = new MyContact();
String givenName = cursor.getString(cursor.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
String postcode = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
myContact.setFirstName(givenName);
myContact.setLastName(postcode);
contacts.add(myContact);
}
}
System.out.println(contacts.size());
After API 21 We Write this Query for remove contact duplicacy.
String select = ContactsContract.Data.HAS_PHONE_NUMBER + " != 0 AND " +
ContactsContract.Data.MIMETYPE
+ " = " + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "
AND "+ ContactsContract.Data.RAW_CONTACT_ID + " = " +
ContactsContract.Data.NAME_RAW_CONTACT_ID;
Cursor cursor = mContent.query(ContactsContract.Data.CONTENT_URI, null, select,
null, null);
You are querying ContactsContract.Data, which is a generic container that holds a list of various contact details, such as phone numbers, postal codes etc.. You must filter the results for the rows whose ContactsContract.Data.MIMETYPE column equals StructuredPostal.CONTENT_ITEM_TYPE:
So change the query to:
Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
null, null, ContacsContract.Data.MIMETYPE + "='" +
ContactsContract.StructuredPostal.CONTENT_ITEM_TYPE + "'", null);
See ContactsContract.Data
a contact that is registered to multiple groups will show up multiple times
if you query the Uri CONTENT_URI = ContactsContract.Data.CONTENT_URI
Add this to your SELECTION:
+ ContactsContract.Data.DATA1 + " = 1 " ; //show only contacts in group 1