how can I retrieve a single contact and some associated data (e.g. emails, phonenumbers, addresses...) by its id/lookupkey?
This is the code I use to add contacts (actually its from the internet and is working for me).
// Asking the Contact provider to create a new contact
try {
result = this.context.getContentResolver().applyBatch(
ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this.context, "Exception: " + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
Uri myContactUri = result[0].uri;
int lastSlash = myContactUri.toString().lastIndexOf("/");
int length = myContactUri.toString().length();
int contactID = Integer.parseInt((String) myContactUri.toString()
.subSequence(lastSlash + 1, length));
return contactID;
Now I want to fetch this new contact. How do I do it? All I came up with is this:
ContentResolver content = context.getContentResolver();
String[] projection = { Data.LOOKUP_KEY, Data.MIMETYPE,
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Email.ADDRESS };
// Defines the selection clause
String selection = Data.LOOKUP_KEY + " = ?";
// Defines the sort order
String sortOrder = Data.LOOKUP_KEY;
String[] args = {"2400"};
Cursor cursor = content.query(Data.CONTENT_URI, projection, selection,
args, sortOrder);
When I remove the selection I get all contacts+all their data. So I looked up the key 2400 in my case and wanted to fetch this contact by its lookupkey. Well, does not work. cursor.getCount() return 0.
Any ideas?
My solution now is to use to following:
String[] projection = { Data.MIMETYPE,
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Email.ADDRESS };
// Defines the selection clause
String selection = ContactsContract.Data.RAW_CONTACT_ID + "=?";
// Defines the sort order
String sortOrder = Data.LOOKUP_KEY;
String[] args = { id+"" };
Cursor cursor = content.query(Data.CONTENT_URI, projection, selection,
args, sortOrder);
Sort order doesnt matter, but I use the RAW_CONTACT_ID, which works well!
Related
I try to implement a live search over the users contacts, and I want to get the name, thumbnail and address (if there is one) of each matching contact.
The live search is running while the user is typing.
So he types ma and will get 'martin', 'matthews'...
He'll continue with mat and will only see 'matthews'
I try to achieve this with a single query like the following, but I always get the contact number in the FORMATTED_ADRESS field. I guess I have a JOIN problem, because I'm using ContactsContract.CommonDataKinds and ContactsContract.Contacts in the same query?
public static List<ContactModel> getContactsForQuery(Context context, String query) {
String[] projection = new String[] {
ContactsContract.Contacts.DISPLAY_NAME,
Contacts.PHOTO_THUMBNAIL_URI,
ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS
};
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String selection = ContactsContract.Contacts.DISPLAY_NAME + " LIKE '%" + query + "%'";
Cursor cursor = context.getContentResolver().query(uri, projection, selection, null,null);
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(0);
String thumbail = cursor.getString(1);
String formattedADress = cursor.getString(2);
}
while (cursor.moveToNext());
}
I actually solved my issue, with
querying for Contacts._ID, Contacts.DISPLAY_NAME
start a second query with the Contacts._ID like the following
Cursor detailCursor = context.getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
new String[]{
CommonDataKinds.StructuredPostal.STREET,
CommonDataKinds.StructuredPostal.CITY,
CommonDataKinds.StructuredPostal.POSTCODE
},
ContactsContract.Data.CONTACT_ID + "=? AND "
+ CommonDataKinds.StructuredPostal.MIMETYPE + "=?",
new String[]{
String.valueOf(contactID),
CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE
},
null);
but this will start a second query for every contact, which might not be the best approach.
So my final question is: is it possible to get this work with the first query?
Mmmh, very sad, that no one was able to answer my question and grab the bounty points ;-(
For the record, here's my working example. It solves the issue but I still think it's producing a big overload. On every user entry (afterTextchange) I call the getContactsDetailsQuery which first gets all users with their ID containing the query in their name (cursor) and afterwards I start another query (detailCursor) for every user to get the adress. To prevent the overload, i added an limit..
public static List<SearchModel> getContactDetailsForQuery(Context context, String query, int limit) {
final int CONTACT_ID_INDEX = 0;
final int CONTACT_NAME_INDEX = 1;
final int CONTACT_THUMBNAIL_INDEX = 2;
//my custom model to hold my results
List<SearchModel> results = new ArrayList<SearchModel>();
final String[] selectUser = new String[]{
Contacts._ID,
Contacts.DISPLAY_NAME,
Contacts.PHOTO_THUMBNAIL_URI};
String selection = Contacts.DISPLAY_NAME + " LIKE ?";
String[] selectionArgs = new String[]{"%" + query + "%"};
String sortOrder = Contacts.DISPLAY_NAME + " ASC";
Cursor cursor = context.getContentResolver().query(Contacts.CONTENT_URI, selectUser, selection, selectionArgs, sortOrder, null);
int contactCounter = 0;
if (cursor != null && cursor.moveToFirst()) {
do {
String contactID = cursor.getString(CONTACT_ID_INDEX);
String displayName = cursor.getString(CONTACT_NAME_INDEX);
String thumbnail = cursor.getString(CONTACT_THUMBNAIL_INDEX);
//get user details with user id (this is the query i wanted to change in my question!!)
Cursor detailCursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
new String[]{
CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS},
ContactsContract.Data.CONTACT_ID + "=? AND " +
CommonDataKinds.StructuredPostal.MIMETYPE + "=?",
new String[]{String.valueOf(contactID), CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE},
null);
if (detailCursor != null && detailCursor.moveToFirst()) {
//special case: user has several address, query all of them
do {
String formattedAddress = detailCursor.getString(detailCursor.getColumnIndex(CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS));
//user has serveral adress -> init model for each adress
SearchModel contact = new SearchModel();
results.add(contact);
contactCounter++;
} while (detailCursor.moveToNext() && contactCounter < limit);
} else {
//user has no adress -> init model
SearchModel contact = new SearchModel();
results.add(contact);
contactCounter++;
}
detailCursor.close();
} while (cursor.moveToNext() && contactCounter < limit);
}
cursor.close();
return results;
}
For a given number from my address book, I need to look-up if the number has whatsapp enabled.
(The idea is to choose SMS/WhatsApp for initiating a text intent)
Lets say, I have two numbers under a contact, And I need to know which one has whatsapp enabled.
The "People" app on the Nexus 4 shows both contact numbers,
And also a little below has a CONNECTIONS section, which shows only the WhatsApp possible contact.
Is there a way to look up(like how People app does) ?
If you want to know if this contact has WhatsApp:
String[] projection = new String[] { RawContacts._ID };
String selection = ContactsContract.Data.CONTACT_ID + " = ? AND account_type IN (?)";
String[] selectionArgs = new String[] { "THE_CONTACT_DEVICE_ID", "com.whatsapp" };
Cursor cursor = activity.getContentResolver().query(RawContacts.CONTENT_URI, projection, selection, selectionArgs, null);
boolean hasWhatsApp = cursor.moveToNext();
if (hasWhatsApp){
String rowContactId = cursor.getString(0);
}
And to find to which number of this contact has WhatsApp
projection = new String[] { ContactsContract.Data.DATA3 };
selection = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.Data.RAW_CONTACT_ID + " = ? ";
selectionArgs = new String[] { "vnd.android.cursor.item/vnd.com.whatsapp.profile", rawContactId };
cursor = CallAppApplication.get().getContentResolver().query(ContactsContract.Data.CONTENT_URI, projection, selection, selectionArgs, "1 LIMIT 1");
String phoneNumber = null;
if (cursor.moveToNext()) {
phoneNumber = cursor.getString(0);
}
Using #idog's method, I improved code to work easier. contactID is a string variable to be passed. If contact hasn't WhatsApp returns null, otherwise returns with contactID which has been passed as variable.
public String hasWhatsapp(String contactID) {
String rowContactId = null;
boolean hasWhatsApp;
String[] projection = new String[]{ContactsContract.RawContacts._ID};
String selection = ContactsContract.Data.CONTACT_ID + " = ? AND account_type IN (?)";
String[] selectionArgs = new String[]{contactID, "com.whatsapp"};
Cursor cursor = getActivity().getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, projection, selection, selectionArgs, null);
if (cursor != null) {
hasWhatsApp = cursor.moveToNext();
if (hasWhatsApp) {
rowContactId = cursor.getString(0);
}
cursor.close();
}
return rowContactId;
}
public int hasWhatsApp(String contactID) {
int whatsAppExists = 0;
boolean hasWhatsApp;
String[] projection = new String[]{ContactsContract.RawContacts._ID};
String selection = ContactsContract.Data.CONTACT_ID + " = ? AND account_type IN (?)";
String[] selectionArgs = new String[]{contactID, "com.whatsapp"};
Cursor cursor = getActivity().getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, projection, selection, selectionArgs, null);
if (cursor != null) {
hasWhatsApp = cursor.moveToNext();
if (hasWhatsApp) {
whatsAppExists = 1;
}
cursor.close();
}
return whatsAppExists;
}
I need to fetch the members for a specific group in android contacts.
I have the contact group names and their ID's
Can anyone provide me how to query the contacts provider for members in a particular group ?
Try this method:
private Cursor getContacts(String groupID) {
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.DISPLAY_NAME
};
String selection = null;
String[] selectionArgs = null;
if(groupID != null && !"".equals(groupID)) {
selection = ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID
+ " = ?";
selectionArgs = new String[] { groupID };
}
else
selection = "1) GROUP BY (" + ContactsContract.Data.CONTACT_ID;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC ";
return getContentResolver().query(uri, projection,
selection, selectionArgs, sortOrder);
}
This works on Android 2.3.3 and lower, but doesn't work on Android 4+ and I don't currently know why.
UPD.
Adding custom string parameter "GROUP BY" to SQL query is denied in Android 4+, so I've founded this workaround:
private Cursor getContacts(String groupID) {
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.DISPLAY_NAME
};
String selection = null;
String[] selectionArgs = null;
if(groupID != null && !"".equals(groupID)) {
selection = ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID
+ " = ?";
selectionArgs = new String[] { groupID };
}
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC ";
Cursor cursor = getContentResolver().query(uri, projection,
selection, selectionArgs, sortOrder);
MatrixCursor result = new MatrixCursor(projection);
Set<Long> seen = new HashSet<Long>();
while (cursor.moveToNext()) {
long raw = cursor.getLong(1);
if (!seen.contains(raw)) {
seen.add(raw);
result.addRow(new Object[] { cursor.getLong(0),
cursor.getLong(1), cursor.getString(2) });
}
}
return result;
Here is the code which iam using
private String getContactNameFromNumber(String number) {
// define the columns I want the query to return
String[] projection = new String[] {
Contacts.Phones.DISPLAY_NAME,
Contacts.Phones.NUMBER };
// encode the phone number and build the filter URI
Uri contactUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, Uri.encode(number));
// query time
Cursor c = getContentResolver().query(contactUri, projection, null,
null, null);
// if the query returns 1 or more results
// return the first result
if (c.moveToFirst()) {
String name = c.getString(c
.getColumnIndex(Contacts.Phones.DISPLAY_NAME));
return name;
}
// return the original number if no match was found
return number;
}
but this code returns only number exactly equal to contact number.
i want to use like statement so that even last 7 numbers matches i should be able to get the name..
how to write that..?
Retrieving Name from Phones Contacts using Phone Number
private String getContactNameFromNumber(String number) {
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
Cursor cursor = context.getContentResolver().query(uri, new String[]{PhoneLookup.DISPLAY_NAME},null,null,null);
if (cursor.moveToFirst())
{
name = cursor.getString(cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME));
}
return name;
//proceed as you need
}
try this
private String getContactNameFromNumber(String number) {
ContentResolver cr = getContentResolver();
String [] projection = new String []{
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
};
String selection = ContactsContract.CommonDataKinds.Phone.NUMBER + " LIKE ? ";;
String[] selectionArgs = new String[]{"%"+number+ "%"};
Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection,
selection,
selectionArgs,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
//proceed as you need
...
}
Friends I want Contacts which have email and also sort in ascending order..
any one know how to get this list and sort..
Please help me and thanks in advance.
I am using this code.
MatrixCursor matCur = new MatrixCursor(new String[] { Contacts._ID,
Contacts.DISPLAY_NAME, "photo_id", "starred" });
Cursor cEmail = WP7Main.this.managedQuery(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
cEmail.moveToFirst();
if (cEmail.moveToFirst())
{
// String name =
// cursor.getString(cursor.getColumnIndexOrThrow(People.NAME));
String contactId = cEmail.getString(cEmail.getColumnIndex(ContactsContract.Contacts._ID));
Cursor emails = WP7Main.this.getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,ContactsContract.CommonDataKinds.Email.CONTACT_ID+ " = " + contactId, null, null);
String emailAddress = "";
while (emails.moveToNext())
{
// This would allow you get several email addresses
if (emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)) != null)
{
String[] columnValues = {
cEmail.getString(cEmail
.getColumnIndex("_id")),
cEmail.getString(cEmail
.getColumnIndex("display_name")),
cEmail.getString(cEmail
.getColumnIndex("photo_id")),
cEmail.getString(cEmail
.getColumnIndex("starred")) };
matCur.addRow(columnValues);
}
}
emails.close();
}
Try this:
/**
* #return A managed cursor of email contacts for the given activity.
*/
public static Cursor buildFilteredEmailCursor(Activity activity) {
final String my_sort_order = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
String my_selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '1'";
String[] eproj = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Email.DATA};
Uri uri = android.provider.ContactsContract.CommonDataKinds.Email.CONTENT_URI;
return activity.managedQuery(uri, eproj, my_selection, null, my_sort_order);
}
Use this query :
Cursor c = getContentResolver().query(Data.CONTENT_URI,
new String[]{Data.CONTACT_ID, Data.DISPLAY_NAME, Email.ADDRESS},
Data.MIMETYPE + "=?", new String[] {Email.CONTENT_TYPE}, Data.DISPLAY_NAME /* use Email.ADDRESS if you want to sort it using that*/);