my app creates new contacts with ContentProviderOperation. The problem is, I need a reference to the new contact because I need some information of it to display it in a listview and go with intent into the contact app to the contact.
The best thing would be the ID, but I´ve read that it might change during operations on the database, which won´t be helpful to me.
Now I thought, the Uri might be the best thing, because I could later retrieve the contactID or lookup key.
How do I get the Uri directly after calling applyBatch() ?
EDIT:
Here is a solution, but not really a good one.
He is putting a randomly generated token into each contact, then he makes a new query with it.
I want neither put some extra data into the contacts, nor starting a second query. But if there is no other possibility I´ll do it that way.
simply call
private String retrieveContactId(String phoneNo) {
try {
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNo));
String[] projection = new String[] { ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.DISPLAY_NAME };
String selection = null;
String[] selectionArgs = null;
String sortOrder = ContactsContract.PhoneLookup.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
ContentResolver cr = getApplicationContext().getApplicationContext().getContentResolver();
String contactId = null;
if (cr != null) {
Cursor resultCur = cr.query(uri, projection, selection, selectionArgs, sortOrder);
if (resultCur != null) {
while (resultCur.moveToNext()) {
contactId = resultCur.getString(resultCur.getColumnIndex(ContactsContract.PhoneLookup._ID));
Log.e("Info Incoming", "Contact Id : " + contactId);
return contactId;
}
resultCur.close();
}
}
} catch (Exception sfg) {
Log.e("Error", "Error in loadContactRecord : " + sfg.toString());
}
return null;
}
and for the uri
Uri contactUri = Contacts.getLookupUri(
Integer.valueOf(rawContactId), clookup);
Related
So I've written a query to extract the WhatsApp contacts of a phone. My initial query goes like this:
Cursor c = con.getContentResolver().query(
ContactsContract.RawContacts.CONTENT_URI,
new String[]{ContactsContract.RawContacts.CONTACT_ID, ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY},
ContactsContract.RawContacts.ACCOUNT_TYPE + "= ?",
new String[]{"com.whatsapp"},
null
);
ArrayList<String> myWhatsappContacts = new ArrayList<String>();
int contactNameColumn = c.getColumnIndex(ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY);
while (c.moveToNext()) {
// You can also read RawContacts.CONTACT_ID to read the
// ContactsContract.Contacts table or any of the other related ones.
myWhatsappContacts.add(c.getString(contactNameColumn));
}
The purpose of this is to find out how many WhatsApp contacts the phone has at any one time. When I do:
Log.i("WhatsApp contacts found:", Integer.toString(myWhatsappContacts.size());
It should print out how many WhatsApp contacts there were into LogCat. And this works - up to a point.
Let's say for example that the number of WhatsApp contacts I have now is 101. The next phase of this little project is to delete away ALL contacts if there are more than 100 of them. In which case, we go:
if (myWhatsappContacts.size() > 100) {
//Delete all contacts code here
}
I've tested the delete contacts code, it works. I check the contacts directory of the phone via the contacts app, and it says 0. But now when I do the query again (refer to code above), it still shows 101! What's going on?
If it helps, my DeleteContacts method is as follows:
private void deleteContact(Context ctx, String phone, String name) {
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone));
Cursor cur = ctx.getContentResolver().query(contactUri, null, null, null, null);
try {
if (cur.moveToFirst()) {
do {
if (cur.getString(cur.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME)).equalsIgnoreCase(name)) {
String lookupKey = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
ctx.getContentResolver().delete(uri, null, null);
return;
}
} while (cur.moveToNext());
}
} catch (Exception e) {
System.out.println(e.getStackTrace());
} finally {
cur.close();
}
return;
}
What am I doing wrong? Is my DeleteContacts code faulty? Or is the query itself faulty?
in my app i am listing contacts in a listview. no of contacts is 1000+. i get the contacts
by using ContentResolver query that is cr.query(...),store the values in an arraylist
and after that load the array list in setListAdapter(...). to display the all contacts my
apps takes nearly 1 minute so that i use Async task but there is no big differences by using the async task.
i need to display all contacts within 2 to 4 seconds. i check in the default contacts
application on android simulator which is load within in 2 to 4 seconds. i have spend
long time in google. but i could not get any helpful solution. please help me how to fast the loading contacts on listview. please help me.
my coding sample:
private ArrayList<ContactListEntry> loadContactListInternal(String searchString) {
ArrayList<ContactListEntry> contactList = new ArrayList<ContactListEntry>();
ContentResolver cr = getContentResolver();
Cursor cur = null;
String[] projection = new String[] {BaseColumns._ID,ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.Contacts.PHOTO_ID};
....
cur=cr.query(ContactsContract.Contacts.CONTENT_URI, projection, selection, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");
while (cur.moveToNext()) {
int id = Integer.parseInt(cur.getString(0));
....
if (input !=null)
photo = BitmapFactory.decodeStream(input);
....
ArrayList<ContactListEntry.PhoneEntry> phoneEntries = new ArrayList<ContactListEntry.PhoneEntry>();
String[] projection1 = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER,ContactsContract.CommonDataKinds.Phone.TYPE};
Cursor pcur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,projection1, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { String.valueOf(id) }, null);
while (pcur.moveToNext()) {
...
}
pcur.close();
ContactListEntry entry = new ContactListEntry(id, name, photo, phoneEntries);
contactList.add(entry);
}
cur.close();
return contactList;
}
.....
in another class
private void selectionUpdated() {
....
setListAdapter(new SelectedArrayAdapter(this, app.selectedContacts));
...
}
Use the Concept of projections and selection arguments to retrive the contacts in my case for 500 contacts intially it was taking 12 sec.
Now it is taking 350ms(lessthan second)
void getAllContacts() {
long startnow;
long endnow;
startnow = android.os.SystemClock.uptimeMillis();
ArrayList arrContacts = new ArrayList();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Cursor cursor = ctx.getContentResolver().query(uri, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.Contacts._ID}, selection, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
cursor.moveToFirst();
while (cursor.isAfterLast() == false) {
String contactNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
int phoneContactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
int contactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Log.d("con ", "name " + contactName + " " + " PhoeContactID " + phoneContactID + " ContactID " + contactID)
cursor.moveToNext();
}
cursor.close();
cursor = null;
endnow = android.os.SystemClock.uptimeMillis();
Log.d("END", "TimeForContacts " + (endnow - startnow) + " ms");
}
More information on this link http://www.blazin.in/2016/02/loading-contacts-fast-from-android.html ....
So your problem is that you do a lot of subqueries for each contact. I has the same issue once upon a time. My case was that I showed many contacts and allowed the user to click on any of them. After that I started processing the contact in another activity.
Back then I finally decided that I should display only the name and lazily fetch all the other data later on, just before I launch the next activity. This was amazing: decreased the speed of my program almost by a factor of 200, and the operations became completely invisible to the user.
The default android list does the same if I am not wrong - it displays only the name, and later on loads all the other contact-related data.
i use cursor adapter and i cut the databse,arrayadapter and optimize the code.
Consider having just one query and getting rid of the sub query idea (as already suggested). You can achieve speed by just querying using the Content Uri:
"ContactsContract.CommonDataKinds.Phone.CONTENT_URI"
This URI also has the "ContactsContract.Contacts.DISPLAY_NAME" field.
You might also want to consider doing this query and working with your adapter in a seperate thread to make it completely transparent.
This worked for me.
OPTIMIZED SOLUTION HERE.....
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, null);
if (cursor != null) {
try {
final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String name, number;
while (cursor.moveToNext()) {
name = cursor.getString(nameIndex);
number = cursor.getString(numberIndex);
}
} finally {
cursor.close();
}
}
CHEERS...:)
I'm trying to find a contact by display name. The goal is to open this contact and add more data to it (specifically more phone numbers), but I'm struggling to even find the contact I want to update.
This is the code I'm using:
public static String findContact(Context context) {
ContentResolver contentResolver = context.getContentResolver();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI;
String[] projection = new String[] { PhoneLookup._ID };
String selection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " = ?";
String[] selectionArguments = { "John Johnson" };
Cursor cursor = contentResolver.query(uri, projection, selection, selectionArguments, null);
if (cursor != null) {
while (cursor.moveToNext()) {
return cursor.getString(0);
}
}
return "John Johnson not found";
}
I do have a contact called "John Johnson", but the method always returns "not found". I also tried searching for a contact with just one name, so that makes no difference.
I suspect that it's something wrong with the uri, selection or selection arguments, because I couldn't find any example online of searching for contacts with a given display name, and it seems display name is a special kind of information, different from for example a phone number.
Any ideas how I can achieve to find John Johnson?
UPDATE: I found out how to find a contact by display name:
ContentResolver contentResolver = context.getContentResolver();
Uri uri = Data.CONTENT_URI;
String[] projection = new String[] { PhoneLookup._ID };
String selection = StructuredName.DISPLAY_NAME + " = ?";
String[] selectionArguments = { "John Johnson" };
Cursor cursor = contentResolver.query(uri, projection, selection, selectionArguments, null);
if (cursor != null) {
while (cursor.moveToNext()) {
return cursor.getString(0);
}
}
return "John Johnson not found";
This code returns the contact id of the first contact with display name "John Johnson". In my original code I had the wrong uri and the wrong selection in my query.
I thinks the issue may caused by the projection you set. Projection is used to tell android which column of data you want to query then you only give the id column so the display name won't return. Try to remove the projection to see whether it works.
-- Cursor cursor = contentResolver.query(uri, projection, selection, selectionArguments, null);
++ Cursor cursor = contentResolver.query(uri, null, selection, selectionArguments, null);
Change Your Query URI.
You are using a URI that is meant to filter only phones numbers:
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI;
You need to use a URI that has access to the display_name column, like this:
Uri uri = ContactsContract.Data.CONTENT_URI;
There's a decent breakdown of what URIs to use and when to use them on the Android SDK Documentation:
If you need to read an individual contact, consider using CONTENT_LOOKUP_URI instead of CONTENT_URI.
If you need to look up a contact by the phone number, use PhoneLookup.CONTENT_FILTER_URI, which is optimized for this purpose.
If you need to look up a contact by partial name, e.g. to produce filter-as-you-type suggestions, use the CONTENT_FILTER_URI URI.
If you need to look up a contact by some data element like email address, nickname, etc, use a query against the ContactsContract.Data table. The result will contain contact ID, name etc.
//method for gaining id
//this method get a name and make fetch it's id and then send the id to other method //named "showinformation" and that method print information of that contact
public void id_return(String name) {
String id_name=null;
Uri resultUri = ContactsContract.Contacts.CONTENT_URI;
Cursor cont = getContentResolver().query(resultUri, null, null, null, null);
String whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME + " = ?" ;
String[] whereNameParams = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE,name};
Cursor nameCur = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
while (nameCur.moveToNext()) {
id_name = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID));}
nameCur.close();
cont.close();
nameCur.close();
//for calling of following method
showinformation(id_name);
}
//method for showing information like name ,phone, email and other thing you want
public void showinformation(String id) {
String name=null;
String phone=null;
String email=null;
Uri resultUri = ContactsContract.Contacts.CONTENT_URI;
Cursor cont = getContentResolver().query(resultUri, null, null, null, null);
String whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID+ " = ?" ;
String[] whereNameParams1 = new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE,id};
Cursor nameCur1 = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams1, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
while (nameCur1.moveToNext()) {
name = nameCur1.getString(nameCur1.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));}
nameCur1.close();
cont.close();
nameCur1.close();
String[] whereNameParams2 = new String[] { ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,id};
Cursor nameCur2 = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams2, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
while (nameCur2.moveToNext()) {
phone = nameCur2.getString(nameCur2.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));}
nameCur2.close();
cont.close();
nameCur2.close();
String[] whereNameParams3 = new String[] { ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,id};
Cursor nameCur3 = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams3, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
while (nameCur3.moveToNext()) {
email = nameCur3.getString(nameCur3.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));}
nameCur3.close();
cont.close();
nameCur3.close();
String[] whereNameParams4 = new String[] { ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE,id};
Cursor nameCur4 = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, whereName, whereNameParams4, ContactsContract.CommonDataKinds.StructuredPostal.DATA);
while (nameCur4.moveToNext()) {
phone = nameCur4.getString(nameCur4.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.DATA));}
nameCur4.close();
cont.close();
nameCur4.close();
//showing result
txadd.setText("Name= "+ name+"\nPhone= "+phone+"\nEmail= "+email);
}
//thank all persons in this site because of many help of me to learn and correction my warn and errors this is only a gift for all of you and ...
The below code should do the trick
if (displayName != null) {
Uri lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI, Uri.encode(displayName));
String[] displayNameProjection = { ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY, Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME };
Cursor cur = context.getContentResolver().query(lookupUri, displayNameProjection, null, null, null);
try {
if (cur.moveToFirst()) {
return true;
}
} finally {
if (cur != null)
cur.close();
}
return false;
} else {
return false;
}
Reference: Retrieving a List of Contacts Article
I am having a problem getting a contact photo, the kind you see in the messaging app and new gmail notification. I have looked at a few example codes but nothing has worked for me, this is what I currently have
this should get the photo uri and turn it into a bitmap image to use or at least it seems
public static Bitmap getContactImage(long id,Context context){
InputStream input = getPhoto(id,context);
if(input == null){
return null;
}
return BitmapFactory.decodeStream(input);
}
public static InputStream getPhoto(long contactId,Context context){
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
InputStream in = null;
try{
in = context.getContentResolver().openInputStream(photoUri);
}catch(FileNotFoundException e){
Log.d(TAG, e.toString());
}
return in;
}
and this is how I call
long contactID = 0;
Bitmap image = BitmapFactory.decodeResource(context.getResources(),R.drawable.ic_contact_picture);
Cursor contact = context.getContentResolver().query(Data.CONTENT_URI,new String[] {Data.CONTACT_ID},Email.ADDRESS + "='" + from + "'",null,null);
if(contact.moveToFirst() && contact != null){
contactID = contact.getLong(0);
image = getContactImage(contactID,context);
}
I get the contact id fine (checked by searching the number for the person querying against) but then it does not find the contact photo. I know there is a photo because I am testing it against myself to make sure and I have a contact photo so I dont know what else I should do.
I always find navigating the contact provider very troublesome because there is so much to it.
I got it, I did a query against the RAW_CONTACT_ID with the MIMETYPE and that gave me the photo I was looking for
Cursor p = context.getContentResolver().query(Data.CONTENT_URI,new String[] {Photo.PHOTO},
Data.RAW_CONTACT_ID + "=" + contactId + " AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE+"'"
,null,null);
You're doing it wrong.
First, get an ID of the photo from the PHOTO_ID column of ContactsContract.Contacts table. Next, retrieve a byte array from PHOTO column (which is actually alias to DATA15) from ContactsContract.Data by ID you got in previous step. And, finally, decode that byte array using BitmapFactory to get a bitmap.
Here are docs about this.
This works for me.
//Querying for all contacts(Apply selection parameter in query to get a specific contact)
Uri contacts = ContactsContract.Contacts.CONTENT_URI;
cur = null;
cur = Main.context.getContentResolver().query(contacts, null, null,
null, null);
int contactIdIndex = cur.getColumnIndex(ContactsContract.PhoneLookup._ID);
int contactId = cur.getInt(contactIdIndex);
// Photo
Uri contactUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri,
ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = cr
.query(
photoUri,
new String[] { ContactsContract.CommonDataKinds.Photo.PHOTO },
null, null, null);
if (cursor != null && cursor.moveToFirst()) {
byte[] data = cursor.getBlob(0);
_conEntry.setPhoto(data);
//Data is the photo bytes for you
}
if (cursor != null)
cursor.close();
I am querying the Contacts out of the built in Contacts provider URI in Android. I want to get just the PHONE contacts; is there any consistent way to do this? It seems from what I can find that the account name for phone contacts differs from manufacturer to manufacturer (see this question). Is there a way to get PHONE contacts (not SIM, Facebook, Twitter or others) in a consistent, reliable, manufacturer- and device- agnostic way?
Cursor cursor = null;
try {
String selection = ContactsContract.Data._ID + " = ?";
String[] selectionArgs = new String[] { id };
String[] projection = new String[] { ContactsContract.PhoneLookup.NUMBER};
cursor = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI,
projection, selection, selectionArgs, null);
if (cursor == null || !cursor.moveToFirst())
return;
String phone = cursor.getString(0);
} finally {
if (cursor != null && !cursor.isClosed())
try {
cursor.close();
} catch (Throwable ignore) {
// Ignored.
}
}
Where "?" is user ID, you can put this code into a loop.