8Answers
  • 8
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

Getting a Photo from a Contact

Alright, I'm just trying to learn about using Contact information, but I'm a bit stuck. I would like to be able to display a picture for the contact. Using the following code that I have, how would I be able to put the photo for the contact in the ImageView in contact_entry?

ListView contacts_list = (ListView) findViewById(R.id.contacts_list);

// Gets the URI of the db
Uri uri = ContactsContract.Contacts.CONTENT_URI;
// What to grab from the db
String[] projection = new String[] {
        ContactsContract.Contacts._ID,
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.Contacts.PHOTO_ID
};

String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

Cursor cursor = managedQuery(uri, projection, null, null, sortOrder);

String[] fields = new String[] {
        ContactsContract.Data.DISPLAY_NAME
};

int[] values = { 
        R.id.contactEntryText
};

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, cursor,
        fields, values);
contacts_list.setAdapter(adapter);

contact_entry.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="54px">
    <ImageView
        android:id="@+id/contactPhoto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:src="@drawable/ic_contact_picture_3"/>
    <TextView 
        android:text="@+id/contactEntryText"
        android:id="@+id/contactEntryText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

Probably this will help you(contact is identified by getId()):

/**
 * @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);
}

Usage is:

Uri u = objItem.getPhotoUri();
if (u != null) {
        mPhotoView.setImageURI(u);
} else {
        mPhotoView.setImageResource(R.drawable.ic_contact_picture_2);
}
  • 58
Reply Report

Android documentation says, that we should do it in this way.

public Bitmap openPhoto(long contactId) {
        Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
        Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
        Cursor cursor = getContentResolver().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 BitmapFactory.decodeStream(new ByteArrayInputStream(data));
                }
            }
        } finally {
            cursor.close();
        }
        return null;

}

For contactId you can use:

 public static long getContactIDFromNumber(String contactNumber, Context context) {
    String UriContactNumber = Uri.encode(contactNumber);
    long phoneContactID = new Random().nextInt();
    Cursor contactLookupCursor = context.getContentResolver().query(Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, UriContactNumber),
            new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup._ID}, null, null, null);
    while (contactLookupCursor.moveToNext()) {
        phoneContactID = contactLookupCursor.getLong(contactLookupCursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
    }
    contactLookupCursor.close();

    return phoneContactID;
}

Source: https://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo.html

  • 16
Reply Report

Don't know why but this works on 2.2 and 4.1:

Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, Long.parseLong(photoId));
imageView.setImageURI(photoUri);

The photo Uri has the following form: content://com.android.contacts/data/3345, where the number is the photoId.

  • 13
Reply Report

This code will take an image from a contact and then will display in your imageView, it is so easy and it works perfect, in this case I am getting image from a contact and display if, if there is still query then post a comment

             ImageView profile  = (ImageView)findViewById(R.id.imageView1);                 
             Uri my_contact_Uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(Contact_Id));
                      InputStream photo_stream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), my_contact_Uri);            
                      BufferedInputStream buf = new BufferedInputStream(photo_stream);
                      Bitmap my_btmp = BitmapFactory.decodeStream(buf);
                         profile.setImageBitmap(my_btmp);                      
  • 4
Reply Report
      • 2
    • @PirFahimShah you should be closing the BufferedInputStream since it manages the InputStream. So calling close on the BufferedInputStream will close the InputStream also. And the close() should be in a finally block. If the stream is not closed then it can cause a resource leak.

For future readers, loading all contacts with images takes too much time and memory if you load the images with full size. From experience, on Nexus 5 it takes up to 3 seconds to load ~500 contacts. Because of this intensity, we need to avoid fetching contacts in UI thread.

This is mainly because the thumbnail photos are in an other table, which forces us to query more. If you don't need to load any image, it takes ~400ms in the case mentioned above.

I have created a gist that fetches all contacts, with their respective thumbnail references in ~500-700ms for 500 contacts;

https://gist.github.com/bugraoral/a4d36d79621455fa3dd860ff994ae796

The key point is to query and get all thumbnail references once, load them to memory, and use the memory for querying images of contacts individually.

  • 3
Reply Report

According to Android Developers' documentation:

A read-only sub-directory of a single contact that contains the contact's primary photo. The photo may be stored in up to two ways - the default "photo" is a thumbnail-sized image stored directly in the data row, while the "display photo", if present, is a larger version stored as a file.

https://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo

You can use the following method to get thumbnail version of contact photo:

@Nullable
public Bitmap getContactPhotoThumbnail(Context context, long contactId) {
    Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
    InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), contactUri);

    return BitmapFactory.decodeStream(is);
}

You can use the following method to the full sized contact photo:

@Nullable
public Bitmap getContactPhoto(Context context, long contactId) {
    Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
    Uri displayPhotoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
    try {
        AssetFileDescriptor fd =
                context.getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
        return BitmapFactory.decodeStream(fd.createInputStream());
    } catch (IOException e) {
        return null;
    }
}
  • 3
Reply Report

You need to use permission like this in your manifest file

 <uses-permission android:name="android.permission.READ_CONTACTS" /> 
  • 1
Reply Report
      • 1
    • on my personal experience,in android studio just write your code and if your project need any permission and if you don't declare it in your manifest, you will front with an error and if you read your trace error, the trace will tell you what permission you need. however base on accept answer, you need just read-contacts permission

I know it is a very old question but so are some of the answers here as few things here have now been deprecated. As the question showed up in searches while I was looking for similar solution, I though I will add my two cents here...

I have created a simple contacts list with their names and photos from ContactsContract. Please check my answer at... https://stackoverflow.com/a/37710199/1209544

  • 0
Reply Report