I'm trying to delete all contacts from a defined group but I don't know how to do a join from the contact table and group table (if it's possible).
ContentResolver cr = getContentResolver();
String where = ContactsContract.Groups.TITLE + " =='LolGroup'";
Cursor cursor = cr.query(
ContactsContract.Contacts.CONTENT_URI, null, where, null, null);
while (cursor.moveToNext()) {
String lookupKey = cursor.getString(
cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri uri = Uri.withAppendedPath(
ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
cr.delete(uri, null, null);
}
Of course it gives me an error because there is no "title" in the contacts group, but if I do a join with the ID I should get what i want.
Any idea how to do that join?
It looks strange because ContactsContract.Contacts does not have ContactsContract.Groups.TITLE column. So I think that you can get group id with the group title you want and then search contacts with the group id. The idea might go like following:
public String getGroupIdByTitle(String groupTitle){
try {
cursor = mContentResolver.query(
ContactsContract.Groups.CONTENT_URI,
new String[] {Groups._ID},
Groups.TITLE + "=?",
new String[]{groupTitle},
null);
while (cursor.moveToNext()){
return cursor.getString(cursor.getColumnIndex(0);
}
} finally {
if (cursor!=null) cursor.close();
}
return "";
}
public String getGroupIdOfContact(String lookupKey) {
String where = String.format("%s=? AND %s=?", Data.LOOKUP_KEY, Data.MIMETYPE);
String[] whereArgs = {lookupKey, GroupMembership.CONTENT_ITEM_TYPE};
String groupRowId = "";
Cursor cursor = mContentResolver.query(
Data.CONTENT_URI,
new String[]{GroupMembership.GROUP_ROW_ID},
where, whereArgs, null);
try {
if (cursor.moveToNext()) {
return cursor.getString(cursor.getColumnIndex(GroupMembership.GROUP_ROW_ID));
}
} finally {
if (cursor!=null) cursor.close();
}
return "";
}
public void deleteContactByGroupTitle(String groupTitle) {
String targetGroupId = getGroupIdByTitle(groupTitle);
Cursor cursor = null;
try {
cursor = mContentResolver.query(Contacts.CONTENT_URI, null, null, null, null);
while (cursor.moveToNext()){
String lookupKey = cursor.getString(cursor.getColumnIndex(Contacts.LOOKUP_KEY));
String groupId = getGroupIdOfContact(lookupKey);
if (targetGroupId.equals(groupId)){
//TODO. delete this contact
}
}
} finally {
if (cursor!=null) cursor.close();
}
}
The above code has not tested but I think that basic idea would be same.
Related
I'm getting 'name = null' in this code, while cursor has all my contacts in it, i tried many different ways but it all does the same thing.
String[] contact_names, mobile_numbers;
Cursor cursor = getActivity().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null,null, null, null);
while (cursor.moveToFirst()) {
String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
contact_names[contact_names.length] = name;
Cursor phones = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?" + contactId, null, null);
while (phones.moveToNext()) {
String number = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
mobile_numbers[mobile_numbers.length] = number;
}
phones.close();
}
cursor.close();
You don't need to query multiple times, use the following to get it all in one query,
String[] PROJECTION_MAIN = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.Contacts.DISPLAY_NAME
};
Cursor cursor = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
PROJECTION_MAIN, null, null, null);
while (cursor.moveToNext()) {
String contact_id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String phone = cleanNumber(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)), context);
}
folks!
Look I broke my mind with problem -
how get display_name from ContactContract via _ID I got earlier???
Here is the code:
public static long getId(Context context, String number) {
long id = 0;
String displayName;
// define the columns I want the query to return
final String[] projection = new String[] {
ContactsContract.PhoneLookup.DISPLAY_NAME,
ContactsContract.PhoneLookup._ID};
// encode the phone number and build the filter URI
final Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
// query time
final Cursor cursor = context.getContentResolver().query(contactUri, projection, null, null, null);
if(cursor != null) {
if (cursor.moveToFirst()) {
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
// HERE IS GOOD _ID!
id = cursor.getLong(cursor.getColumnIndex(ContactsContract.PhoneLookup._ID));
Log.d("_TAG_", displayName);
{
//
// v. N-1
//
Cursor cursor2 = context.getContentResolver().query(
contactUri,
projection,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{String.valueOf(id)}, null);
if(cursor2 != null) {
// Cursor valid but string below got error "android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1 : )"
displayName = cursor2.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
Log.d("_TAG_", displayName);
}
}
{
//
// v. N
//
Uri myPhoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(String.valueOf(id)));
Cursor phoneCursor = context.getContentResolver().query(
myPhoneUri, null, null, null, null);
for (phoneCursor.moveToFirst(); !phoneCursor.isAfterLast(); phoneCursor.moveToNext()) {
// No steps inside!
String str = phoneCursor.getString(phoneCursor
.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Nickname.NAME));
Log.d(App.LOG_TAG, "ContactUtils.getId: " + str);
}
if(phoneCursor != null) {
phoneCursor.close();
}
}
} else {
Log.d("_TAG_", "Contact Not Found # " + number);
}
cursor.close();
}
return id;
}
"v.N-1" and "v.N" are just 2 ones from a million attempts before.
See - I got _ID, so why it doesn't work back as valid query???
Here is decision i found.
public static String getDisplayName(Context context, long id) {
String displayName = null;
// define the columns I want the query to return
final String[] projection = new String[] {
ContactsContract.Contacts.DISPLAY_NAME,
};
final Cursor cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id + "" }, null);
if(cursor != null) {
if (cursor.moveToFirst()) {
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
cursor.close();
}
return displayName;
}
It works...
I'm implementing an AutoCompleteTextView and I need Name and E-Mail of all my contacts.
I found this snippet that I'm running asynchronously but it's very slow.
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));
Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{id}, null);
while (emailCur.moveToNext()) {
String email = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
autoCompleteAdapter.add(name + " - " + email);
}
emailCur.close();
}
}
}
I'm performing a sort of inner query and I think that's the problem. Is there a way to tune it and make it faster?
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Email.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Email.DATA
};
...
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, PROJECTION, null, null, null);
if (cursor != null) {
try {
final int contactIdIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.CONTACT_ID);
final int displayNameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int emailIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
long contactId;
String displayName, address;
while (cursor.moveToNext()) {
contactId = cursor.getLong(contactIdIndex);
displayName = cursor.getString(displayNameIndex);
address = cursor.getString(emailIndex);
...
}
} finally {
cursor.close();
}
}
few notes:
use just ContactsContract.CommonDataKinds.Email.CONTENT_URI to get information you need, see ContactsContract.CommonDataKinds.Email for information what columns you can query
use projection to get only those columns you really need, you save some memory and increase query performance
get column indexes only once, just before the while cycle
You should not query directly the ContactsContract.Contacts
Make just one query on the ContactsContract.CommonDataKinds with the email data kind.
The ContactsContract.CommonDataKinds.Email inherits a lot of other interfaces that you can use to build your projection. (see inherited constants from the documentation)
For example :
import android.provider.ContactsContract.CommonDataKinds.Email;
[...]
public static final String[] EMAILS_PROJECTION = new String[] {
Email._ID,
Email.DISPLAY_NAME_PRIMARY,
Email.ADDRESS
};
to be used with the
Email.CONTENT_URI
You can retrieve a lot of information (such as user id, user display name ...) directly from the email data kind.
EDIT:
I just realized you're trying to build an AutoCompleteTextView.
You should override the runQueryOnBackgroundThread method and the convertToString of your CursorAdapter and use the Email.CONTENT_FILTER_URI
I really strongly suggest you to take a look at the ApiDemo samples.
Especially the AutoComplete4.java sample that you can find HERE.
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, PROJECTION, "HAS_PHONE_NUMBER <> 0", null, null);
if (cursor!= null)
{
final int displayNameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int numberIndex = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
final int idIndex= cursor.getColumnIndex(ContactsContract.Contacts._ID);
String displayName, number = null, idValue;
while (cursor.moveToNext())
{
displayName = cursor.getString(displayNameIndex);
idValue= cursor.getString(idIndex);
Cursor phones = mContext.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, "contact_id = '" + idValue + "'", null, null);
phones.moveToFirst();
try
{
number = phones.getString(phones.getColumnIndex("data1"));
}
catch (CursorIndexOutOfBoundsException e)
{
}
phones.close();
userList.add(new ContactModel(displayName, number, null));
}
}
I would like to query on phonenumber to obtain the rawcontactID.
The only thing I know of the contact is the given phonenumber, but for my function I need to have the rawcontactID. I got a working code but now I did use 2 seperate queries. What I would like to have is 1 query that can do both just to save some query time.
my code:
Uri uri = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
String[] columns = new String[]{Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER, Phone._ID };
Cursor cursor = contentResolver.query(uri, columns, null, null, null);
if(cursor!=null) {
int clenght = cursor.getCount();
while(cursor.moveToNext()){
//contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME));
id = cursor.getString(cursor.getColumnIndex(Phone.CONTACT_ID));
}
cursor.close();
}
Cursor pCur = contentResolver.query(ContactsContract.Data.CONTENT_URI, new String[]{ContactsContract.Data.RAW_CONTACT_ID}, ContactsContract.Data.CONTACT_ID+" = "+ id, null, null);
if(pCur!=null) {
int clenght = pCur.getCount();
while(pCur.moveToNext()){
//contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME));
id = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID));
}
pCur.close();
}
thanks in advance
Edit:
My code above works fine, but I am still looking for increasing speed for large number of contacts. Therefore I will give a bounty if someone comes with a solution to combine my queries.
private String[] getRawContactIdFromNumber(String givenNumber){
List<String> rawIds = new ArrayList<String>();
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[]{ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID},ContactsContract.CommonDataKinds.Phone.NUMBER + "='"+ givenNumber +"'",null, ContactsContract.CommonDataKinds.Phone.NUMBER);
while (phones.moveToNext())
{
rawIds.add( phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID)));
Log.v("contacts","Given Number: " + givenNumber + "Raw ID: " +rawIds.get(rawIds.size() - 1));
}
phones.close();
String[] ret = new String[0];
return rawIds.toArray(ret);
}
Edited to only include the raw id in the cursor for efficiency. Also changed return type to array in case multiple contacts have the same number.
Please try
String phonenumber = "input your phone number";
Cursor pCur = getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
new String[] { ContactsContract.Data.RAW_CONTACT_ID,
Phone.CONTACT_ID }, Phone.NUMBER + " = " + phonenumber,
null, null);
if (pCur != null) {
while (pCur.moveToNext()) {
String contactID = pCur.getString(pCur
.getColumnIndex(Phone.CONTACT_ID));
String Rowid = pCur.getString(pCur
.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID));
Log.e("RAW_CONTACT_ID", Rowid);
Log.e("CONTACT_ID", contactID);
}
pCur.close();
}
Now you can get Both CONTACT_ID & RAW_CONTACT_ID in single query.
I want to get several contact details from a contact list view. I have this code:
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long id) {
//HERE I WANT TO GET CONTACT DETAILS FROM THE ID PARAMETER
Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, Uri.encode(id));
Cursor c = getContentResolver().query(lookupUri, new String[]{Contacts.DISPLAY_NAME}, null,null,null);
try {
c.moveToFirst();
String displayName = c.getString(0);
} finally {
c.close();
}
}
But I get this exception: IllegalArgumentException, Invalid lookup id (when I call query method from cursor).
So I dont know how to get a valid lookup id from the item list.
Any idea? thanks!
Here id means, A contact id for which you want to fetch the contact details,
The simply code for getting phone number for a particular contact id is like,
// Build the Uri to query to table
Uri myPhoneUri = Uri.withAppendedPath(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, id);
// Query the table
Cursor phoneCursor = managedQuery(
myPhoneUri, null, null, null, null);
// Get the phone numbers from the contact
for (phoneCursor.moveToFirst(); !phoneCursor.isAfterLast(); phoneCursor.moveToNext()) {
// Get a phone number
String phoneNumber = phoneCursor.getString(phoneCursor
.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
sb.append("Phone: " + phoneNumber + "\n");
}
}
So, from your question I have to doubt for id parameter which are you sing in your uri just clear that, Also in my example the id is string type...
Hope you will understand it.
Update: Uri.encode(id) instead of just pass id in string format.
Thanks..
Because managedQuery is deprecated you can also use
Cursor phoneCursor = getContentResolver().query(myPhoneUri, null, null, null, null);
Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
int columnIndex = arg2.getColumnIndex(ContactsContract.Contacts._ID);
private void retriveContactImage(ImageView imageView, int columnIndex) {
Bitmap photo = null;
try {
InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(),
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.valueOf(columnIndex)));
if (inputStream != null) {
photo = BitmapFactory.decodeStream(inputStream);
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
imageView.setImageBitmap(photo);
}
private ArrayList<String> retrieveContactNumbers(TextView textView, long contactId) {
ArrayList<String> phoneNum = new ArrayList<String>();
Cursor cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { contactId + "" }, null);
if (cursor.getCount() >= 1) {
while (cursor.moveToNext()) {
// store the numbers in an array
String str = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if (str != null && str.trim().length() > 0) {
phoneNum.add(str);
}
}
}
cursor.close();
textView.setText(phoneNum.get(0));
return phoneNum;
}
private void retrieveContactName(TextView textView, long contactId) {
String contactName = null;
Cursor cursor = context.getContentResolver().query(Contacts.CONTENT_URI, new String[] { ContactsContract.Contacts.DISPLAY_NAME },
ContactsContract.Contacts._ID + " = ?", new String[] { String.valueOf(contactId) }, null);
if (cursor.moveToFirst()) {
contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
cursor.close();
textView.setText(contactName);
}