I have lookupkeys for contact, now I want to obtain Contact Images as Bitmap/InputStream using these lookupkeys. Android documentation helps getting Images but with contacts id not lookupkey.
public InputStream openPhoto(long contactId) {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = getContentResolver().query(photoUri,
new String[] {Contacts.Photo.PHOTO}, null, null, null);
if (cursor == null) {
return null;
}
try {
if (cursor.moveToFirst()) {
byte[] data = cursor.getBlob(0);
if (data != null) {
return new ByteArrayInputStream(data);
}
}
} finally {
cursor.close();
}
return null;
}
Running from pillar to post but no help. Thanks
Edit Dated 04-09-2012
Tried as suggested by #Sreejith Krishnan R but received the following exceptions in logcat
09-04 03:16:26.359: E/AndroidRuntime(24008): java.lang.IllegalArgumentException: URI: content://com.android.contacts/contacts/lookup/0r272-382C544E2C562C382C4E582C42.2649i11.1987r6285-382C544E2C562C382C4E582C42.1987r6440-382C544E2C562C382C4E582C42.2829r6475-382C544E2C562C382C4E582C42/photo, calling user: com.xyz, calling package:com.xyz
09-04 03:16:26.359: E/AndroidRuntime(24008): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:144)
09-04 03:16:26.359: E/AndroidRuntime(24008): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:114)
[Updated]
Now this can be used since API level 5
public Bitmap getAvatar(Context context, String lookupKey){
Uri uri = getDataUri(context, lookupKey);
if (uri == null){
return null;
}
Cursor cursor = context.getContentResolver().query(
uri,
new String[] {ContactsContract.Data.DATA15},
null,
null,
null
);
if (cursor == null){
return null;
}
try{
if (cursor.moveToFirst()){
byte [] bytes = cursor.getBlob(0);
InputStream inputStream = new ByteArrayInputStream(bytes);
return BitmapFactory.decodeStream(inputStream);
}
} finally {
cursor.close();
}
return null;
}
public Uri getDataUri(Context context, String lookupKey){
Cursor cursor = context.getContentResolver().query(
Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey),
new String[] {ContactsContract.Contacts.PHOTO_ID},
null,
null,
null
);
if (cursor == null){
return null;
}
try {
if (cursor.moveToFirst()){
long id = cursor.getLong(0);
/**http://developer.android.com/reference/android/provider/ContactsContract.ContactsColumns.html#PHOTO_ID
* If PHOTO_ID is null, consult PHOTO_URI or PHOTO_THUMBNAIL_URI,
* which is a more generic mechanism for referencing the contact photo,
* especially for contacts returned by non-local directories (see ContactsContract.Directory).
*/
if (id == 0){
if (Build.VERSION.SDK_INT < 11){
return null;
}
return getPhotoThumbnailUri(context, lookupKey);
}
return ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, id);
}
} finally {
cursor.close();
}
return null;
}
//Available only for API level 11+
public Uri getPhotoThumbnailUri(Context context, String lookupKey){
Cursor cursor = context.getContentResolver().query(
Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey),
new String[] {ContactsContract.Contacts.PHOTO_THUMBNAIL_URI},
null,
null,
null
);
if (cursor == null){
return null;
}
try{
if (cursor.moveToFirst()){
return Uri.parse(cursor.getString(0));
}
} finally {
cursor.close();
}
return null;
}
Related
I've seen many answers, have tried many of them, but none with luck, sometimes I get file not found or
java.lang.IllegalArgumentException: URI: content://com.android.contacts/contacts/-166733728/photo, calling user:
Tried the following methods:
public static long getContactIDFromNumber(String contactNumber)
{ contactNumber = Uri.encode(contactNumber);
long phoneContactID = new Random().nextInt();
Cursor contactLookupCursor = myContext.getContentResolver().query(Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,Uri.encode(contactNumber)),new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup._ID}, null, null, null);
while(contactLookupCursor.moveToNext()){
phoneContactID = contactLookupCursor.getInt(contactLookupCursor.getColumnIndexOrThrow(PhoneLookup._ID));
}
contactLookupCursor.close();
return phoneContactID;
}
public InputStream openThumbContact(long contactId) {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = myContext.getContentResolver().query(photoUri,
new String[] {Contacts.Photo.PHOTO}, null, null, null);
if (cursor == null) {
return null;
}
try {
if (cursor.moveToFirst()) {
byte[] data = cursor.getBlob(0);
if (data != null) {
return new ByteArrayInputStream(data);
}
}
} finally {
cursor.close();
}
return null;
}
public InputStream openDisplayPhotoContact(long contactId) {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO);
try {
AssetFileDescriptor fd =
myContext.getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
return fd.createInputStream();
} catch (IOException e) {
return null;
}
}
public static Bitmap loadContactPhoto(ContentResolver cr, long id) {
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
if (input == null) {
return null;
}
return BitmapFactory.decodeStream(input);
}
Ideally I would like to show the thumb in the contacts or the one facebook has stored, does anyone have a working method? The contact photo is available in the contact list, but I can't get it to load.
I need your help for getting my contact photos.
I receive all my contacts with a birthday. Now I have to tried the photo of the person like that:
...
while (contactCursor.moveToNext()) {
Contact c = Contact.createContact(contactCursor);
c.setPhoto(getContactPhoto(contentResolver, c.getId()));
contacts.add(c);
}
..
private static InputStream getContactPhoto(ContentResolver contentResolver, long contactId) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = contentResolver.query(photoUri, new String[] {ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
if (cursor == null) {
return null;
}
try {
if (cursor.moveToFirst()) {
byte[] data = cursor.getBlob(0);
if (data != null) {
return new ByteArrayInputStream(data);
}
}
} finally {
cursor.close();
}
return null;
}
My problem is now that I'm not able to receive any photo of the contacts (cursos size = 0). On the phone (Xperia Z1 Compact) are definitely contact photos.
My aim is then to set the photo like that:
if(contact.getPhoto() != null) {
Bitmap cPhoto = BitmapFactory.decodeStream(contact.getPhoto());
holder.photo.setImageBitmap(cPhoto);
} else {
ShapeDrawable d = new ShapeDrawable(new OvalShape());
d.getPaint().setColor(Color.BLUE);
d.setBounds(10, 10, 20, 20);
holder.photo.setImageDrawable(d);
}
Thank you very much for your help.
try this
public void getContacts(ContentResolver cr) {
Cursor cursor = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null,
null, null);
while (cursor.moveToNext()) {
String name = cursor
.getString(cursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String photoUri = cursor
.getString(cursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
friendsListitem = new FriendsListitem(name, photoUri, phoneNumber);
arrayListFriends.add(friendsListitem);
}
cursor.close();// close cursor
}
load image using Picasso
Picasso.with(getApplicationContext())
.load(Uri.parse(photoUri)).noFade()
.into(imageView);
I am currently working on an Android project where I am attempting to lookup a contact phone number in the device and retrieve the contact information such as contact name and contacts image. Getting the contract name is working fine, however, a null pointer is being thrown when trying to get the photo uri.
Below is the code I am using:
public ContactInformation getContactInfoFromPhoneNumber(String number)
{
ContactInformation contactInformation = new ContactInformation();
if (number == null)
{
return null;
}
number = number.replace(" ", "");
if (number.startsWith("+"))
{
number = number.substring(3);
}
ContentResolver contentResolver = context.getContentResolver();
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = new String[] {ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.DISPLAY_NAME};
String selection = "REPLACE (" + ContactsContract.CommonDataKinds.Phone.NUMBER + ", \" \" , \"\" ) LIKE ?";
String[] selectionArgs = { "%" + number };
Cursor cursor = contentResolver.query(uri, projection, selection, selectionArgs, null);
if (cursor.moveToFirst())
{
contactInformation.contactName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup.DISPLAY_NAME));
contactInformation.photoUri = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
cursor.close();
return contactInformation;
}
else
{
cursor.close();
return null;
}
}
Update
Below is my updated code based on Itzik Samara's answer.
Below is how I am doing my contact lookup:
public ContactInformation getContactInfoFromPhoneNumber(String number)
{
ContactInformation contactInformation = new ContactInformation();
if (number == null)
{
return null;
}
number = number.replace(" ", "");
if (number.startsWith("+"))
{
number = number.substring(3);
}
ContentResolver contentResolver = context.getContentResolver();
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = new String[] {ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.DISPLAY_NAME};
String selection = "REPLACE (" + ContactsContract.CommonDataKinds.Phone.NUMBER + ", \" \" , \"\" ) LIKE ?";
String[] selectionArgs = { "%" + number };
Cursor cursor = contentResolver.query(uri, projection, selection, selectionArgs, null);
if (cursor.moveToFirst())
{
contactInformation.contactName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup.DISPLAY_NAME));
contactInformation.photoBase64String = getContactPhoto(cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID)));
cursor.close();
return contactInformation;
}
else
{
cursor.close();
return null;
}
}
Below is my getContactPhoto function:
private String getContactPhoto(int contactID)
{
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactID);
Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = context.getContentResolver().query(photoUri, new String[]{ContactsContract.Contacts.Photo.PHOTO},
null, null, null);
if (cursor == null)
{
return null;
}
if (cursor.getCount() > 0)
{
while (cursor.moveToNext()) {
byte[] data = cursor.getBlob(0);
String base64String = Base64.encodeToString(data, Base64.DEFAULT);
cursor.close();
return base64String;
}
}
return null;
}
It's failing on the if statement and jumping out of the if straight to return null as if there is nothing in the cursor.
this function works for me :
private byte[] getContactPhoto(Context context,long contact_id) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contact_id);
Uri photoUri = Uri.withAppendedPath(contactUri,ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = context.getContentResolver().query(photoUri, new String[]{ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
if(cursor == null)
return null;
try {
if(cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
byte[] data = cursor.getBlob(0);
cursor.close();
if (data != null)
return data;
}
}
}
finally {
cursor.close();
}
return null;
}
private void getContacts(Context context) {
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null);
try {
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
long contact_id = cursor.getLong(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Contact friend = new Contact();
String name= cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String email = getContactEmail(context, contact_id);
if(!name.contains("#") && !email.matches("")) {
friend.setName(name);
friend.setEmail(email);
friend.setImage(getContactPhoto(context, contact_id));
friend.setPhone(getContactMobilePhoneNumber(context, contact_id));
mContacts.add(friend);
}
}
}
}
finally {
cursor.close();
}
}
I am currently passing contact name and number with an intent. Which works fine. I am however unable to find out how I can pass a contacts photo and assign it to an ImageView in activity.
I've searched around here and not found an easy answer to this at all.
In case it's neccessary, my method to get name and number of whomever is calling:
private String getContactName(String number) {
String name = null;
String[] projection = new String[]{
ContactsContract.PhoneLookup.DISPLAY_NAME,
ContactsContract.PhoneLookup._ID};
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
Cursor cursor = this.c.getContentResolver().query(contactUri, projection, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
name = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
}
cursor.close();
}
return name;
}
It gets passed to my activity:
Bundle bundle = new Bundle();
bundle.putString("Number", number);
bundle.putString("Name", this.getContactName(number));
intent.putExtras(bundle);
Received with
Bundle bundle = this.getIntent().getExtras();
if (bundle.getString("Name").isEmpty()) {
this.name.setText("Unknown Caller");
} else {
this.name.setText(bundle.getString("Name"));
}
if (bundle.getString("Number").isEmpty()) {
this.number.setText(bundle.getString("Number"));
} else {
this.number.setText(bundle.getString("Name"));
}
try this you will get byte[] of contact photo pass it to intent and decode in second activity
private byte[] queryContactImage(int imageDataRow) {
Cursor c = getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[] {
ContactsContract.CommonDataKinds.Photo.PHOTO
}, ContactsContract.Data._ID + "=?", new String[] {
Integer.toString(imageDataRow)
}, null);
byte[] imageBytes = null;
if (c != null) {
if (c.moveToFirst()) {
imageBytes = c.getBlob(0);
}
c.close();
}
return imageBytes;
}
and in second activity
if (imagebyte != null) {
Bitmap bitimg2 = BitmapFactory.decodeByteArray(imagebyte, 0, imagebyte.length);
yourimageview.setImageBitmap(bitimg2);
}
hope this will help you
You can take contactID from this cursor or your code. This is my method which will give you contact photo, just pass contact ID in it:
public InputStream openPhoto(long contactId) {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = getContentResolver().query(photoUri,
new String[] {Contacts.Photo.PHOTO}, null, null, null);
if (cursor == null) {
return null;
}
try {
if (cursor.moveToFirst()) {
byte[] data = cursor.getBlob(0);
if (data != null) {
return new ByteArrayInputStream(data);
}
}
} finally {
cursor.close();
}
return null;
}
I'm trying to get a contact image using its lookup URI.
I succeed getting the DISPLAY_NAME using this code:
Cursor c = context.getContentResolver().query(contactLookupUri,
new String[] { ContactsContract.Contacts.DISPLAY_NAME }, null,
null, null);
But I didn't find a way to get the photo. The Photo.PHOTO option is not valid for the API I'm using, and trying to get it using an inputStream didn't work as well (perhaps I did something wrong there):
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(context.getContentResolver(),
contactUri);
Thanks,
Yoel
Eventually I solved it by getting the contact ID and using an inputStream:
public static Uri getContactLookupUri(String contactLookupKey) {
return Uri.withAppendedPath(
ContactsContract.Contacts.CONTENT_LOOKUP_URI, contactLookupKey);
}
public static Bitmap getContactImage(Context context, String contactLookupKey) {
long contactId;
try {
Uri contactLookupUri = getContactLookupUri(contactLookupKey);
Cursor c = context.getContentResolver().query(contactLookupUri,
new String[] { ContactsContract.Contacts._ID }, null, null,
null);
try {
if (c == null || c.moveToFirst() == false) {
return null;
}
contactId = c.getLong(0);
} finally {
c.close();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
Uri contactUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, contactId);
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(context.getContentResolver(),
contactUri);
if (input != null) {
return BitmapFactory.decodeStream(input);
} else {
return null;
}
}
The below function return the image uri of your contact_id
/**
* #return the photo URI
*/
public Uri getPhotoUri() {
try {
Cursor cur = this.ctx.getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.Data.CONTACT_ID + "=" + this.getId() + " AND "
+ ContactsContract.Data.MIMETYPE + "='"
+ ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'", null,
null);
if (cur != null) {
if (!cur.moveToFirst()) {
return null; // no photo
}
} else {
return null; // error in cursor process
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long
.parseLong(getId()));
return Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
}
Also refer this LINK