I'm running a query against CommonDataKinds.Phone.CONTENT_URI and I'm getting all the results that have a NOT NULL phone id.
pretty much the code is :
String[] projection2 = new String[] {
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
};
String where2 = ContactsContract.CommonDataKinds.Phone._ID + " != ''" ;
Cursor phoneCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection2, where2, null, null);
and then I iterate through each cursor result and getting the columns I want.
The code is :
if (phoneCursor.getCount() > 0) {
while (phoneCursor.moveToNext()) {
String contacts_id = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.Contacts._ID));
String phone_id = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
Log.i("phonecursor", "contacts_id= " + contacts_id + " phone_id " + phone_id
+ " contacts_name= " + contacts_name + " phone_name= " + phone_name
+ " Phone= " + phone );
}
phoneCursor.close();
}
What I dont get is why Phone.CONTACT_ID is different from the corresponding Contacts._ID from the same row...
Shouldn't both be the same? There are a lot of examples that use those exact columns to run queries. For example here and here if you check the Key pointers.
ContactsContract.Contacts._ID returns unique ID for a row
This is very good example
Image from Get Contact Emails By Content Provider - Android Example
ContactsContract.Contacts._ID returns unique ID for a row.
Now the output will vary based on which cursor you are querying ContactsContract.Contacts._ID.
If you query ContactsContract.Contacts._ID from ContactsContract.Contacts.CONTENT_URI , you will get ContactsContract.Contacts._ID and ContactsContract.CommonDataKinds.Phone.CONTACT_ID same.
But if you query ContactsContract.Contacts._ID from ContactsContract.CommonDataKinds.Phone.CONTENT_URI you will get ContactsContract.Contacts._ID and ContactsContract.CommonDataKinds.Phone.CONTACT_ID different as on each phone entry ContactsContract.Contacts._ID is incremented.
So if you want same _ID and Phone._ID then query from ContactsContract.Contacts.CONTENT_URI instead of ContactsContract.CommonDataKinds.Phone.CONTENT_URI
Related
I can select all contacts using the query below
cr = mActivity.getContentResolver();
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0";
String orderBy = ContactsContract.Contacts.DISPLAY_NAME + " ASC ";
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, selection, null, orderBy);
However, I have a phone number list and I want to create this query like
String selection = ContactsContract.Contacts.PhoneNumber_or_something_else in (MyPhoneNumberArray)
Is that possible to do this?
A worst-case scenario, I can remove the related item using do while after I create my cursor, but, as far as I know, I cannot remove any record from the cursor.
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 entries
Data - The actual data about a contact, emails, phones, etc. each line is a single piece of data that belongs to a single RawContact
All phone numbers in the Contacts DB are in the Data table, so that's what you need to query, you can get the list of CONTACT_IDs from that query and use it to get general info about contacts if you need.
String[] phonesList = new String[] { "+121212345" }; // will work better if all phones in this list are in e164 format
String[] projection = { Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER, Phone.NORMALIZED_NUMBER };
String selection = Phone.NUMBER + " IN ('" + TextUtils.join("','", phonesList) + "') OR " +
Phone.NORMALIZED_NUMBER + " IN ('" + TextUtils.join("','", phonesList) + "')";
Cursor cur = cr.query(Phone.CONTENT_URI, projection, selection, null, null);
while (cur != null && cur.moveToNext()) {
long id = cur.getLong(0);
String name = cur.getString(1);
String phone = cur.getString(2);
Log.d(TAG, "got " + id + ", " + name + ", " + phone;
}
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 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