43 votes

Comment charger une photo de contact?

Je vais avoir des problèmes pour charger une photo à un contact dans Android. J'ai googlé pour une réponse, mais ont rencontré jusqu'à présent vide. Quelqu'un aurait-il un exemple d'interrogation pour un Contact, puis le chargement de la Photo?

Donc, étant donné un contactUri qui provient d'une Activité résultat appelé à l'aide

startActivityForResult(new Intent(Intent.ACTION_PICK,ContactsContract.CommonDataKinds.Phone.CONTENT_URI),PICK_CONTACT_REQUEST) 

est:

content://com.android.contacts/data/1557

Le loadContact(..) fonctionne très bien. Cependant lorsque j'appelle la getPhoto(...) la méthode, j'obtiens une valeur null pour la photo InputStream. Il est également source de confusion car l'URI valeurs sont différentes. Le contactPhotoUri donne:

content://com.android.contacts/contacts/1557

Voir les commentaires en ligne dans le code ci-dessous.

class ContactAccessor {

/**
 * Retrieves the contact information.
 */
public ContactInfo loadContact(ContentResolver contentResolver, Uri contactUri) {

    //contactUri --> content://com.android.contacts/data/1557

    ContactInfo contactInfo = new ContactInfo();

    // Load the display name for the specified person
    Cursor cursor = contentResolver.query(contactUri,
                                        new String[]{Contacts._ID, 
                                                     Contacts.DISPLAY_NAME, 
                                                     Phone.NUMBER,
                                                     Contacts.PHOTO_ID}, null, null, null);
    try {
        if (cursor.moveToFirst()) {
            contactInfo.setId(cursor.getLong(0));
            contactInfo.setDisplayName(cursor.getString(1));
            contactInfo.setPhoneNumber(cursor.getString(2));
        }
    } finally {
        cursor.close();
    }        
    return contactInfo;  // <-- returns info for contact
}

public Bitmap getPhoto(ContentResolver contentResolver, Long contactId) {
    Uri contactPhotoUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);

    // contactPhotoUri --> content://com.android.contacts/contacts/1557

    InputStream photoDataStream = Contacts.openContactPhotoInputStream(contentResolver,contactPhotoUri); // <-- always null
    Bitmap photo = BitmapFactory.decodeStream(photoDataStream);
    return photo;
}

public class ContactInfo {

    private long id;
    private String displayName;
    private String phoneNumber;
    private Uri photoUri;

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public Uri getPhotoUri() {
        return this.photoUri;
    }

    public void setPhotoUri(Uri photoUri) {
        this.photoUri = photoUri;
    }

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

}

}

Clairement, je suis en train de faire quelque chose de mal ici, mais je n'arrive pas à comprendre quel est le problème. Merci.

33voto

wrongmissle Points 241

Cela fonctionne pour moi:

 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);
}
 

31voto

Phil Points 1388

Après avoir analysé le nombre de questions et de réponses au problème de l'affichage d'une vignette, j'ai pensé que je poste ma solution à cette énigme que je n'ai pu trouver un couple qui a travaillé à tous, et aucun qui a fourni une bonne conserve solution pour les paresseux développeur.

La classe ci-dessous prend un Contexte, QuickContactBadge et un numéro de téléphone et joindre une image stockée localement sur l'insigne s'il est disponible pour le numéro de téléphone spécifié.

Voici la classe:

public final class QuickContactHelper {

private static final String[] PHOTO_ID_PROJECTION = new String[] {
    ContactsContract.Contacts.PHOTO_ID
};

private static final String[] PHOTO_BITMAP_PROJECTION = new String[] {
    ContactsContract.CommonDataKinds.Photo.PHOTO
};

private final QuickContactBadge badge;

private final String phoneNumber;

private final ContentResolver contentResolver;

public QuickContactHelper(final Context context, final QuickContactBadge badge, final String phoneNumber) {

    this.badge = badge;
    this.phoneNumber = phoneNumber;
    contentResolver = context.getContentResolver();

}

public void addThumbnail() {

    final Integer thumbnailId = fetchThumbnailId();
    if (thumbnailId != null) {
        final Bitmap thumbnail = fetchThumbnail(thumbnailId);
        if (thumbnail != null) {
            badge.setImageBitmap(thumbnail);
        }
    }

}

private Integer fetchThumbnailId() {

    final Uri uri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
    final Cursor cursor = contentResolver.query(uri, PHOTO_ID_PROJECTION, null, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");

    try {
        Integer thumbnailId = null;
        if (cursor.moveToFirst()) {
            thumbnailId = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID));
        }
        return thumbnailId;
    }
    finally {
        cursor.close();
    }

}

final Bitmap fetchThumbnail(final int thumbnailId) {

    final Uri uri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, thumbnailId);
    final Cursor cursor = contentResolver.query(uri, PHOTO_BITMAP_PROJECTION, null, null, null);

    try {
        Bitmap thumbnail = null;
        if (cursor.moveToFirst()) {
            final byte[] thumbnailBytes = cursor.getBlob(0);
            if (thumbnailBytes != null) {
                thumbnail = BitmapFactory.decodeByteArray(thumbnailBytes, 0, thumbnailBytes.length);
            }
        }
        return thumbnail;
    }
    finally {
        cursor.close();
    }

}

}

Et voici un cas d'utilisation typique à l'intérieur d'une activité:

String phoneNumber = "...";
QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.friend);
new QuickContactHelper(this, badge, phoneNumber).addThumbnail();

Dans un fragment, il sera légèrement différente:

String phoneNumber = "...";
QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.friend);
new QuickContactHelper(getActivity(), badge, phoneNumber).addThumbnail();

Maintenant, il existe des moyens pour être plus efficace - par exemple, si vous êtes de l'affichage d'un message de montage que vous voulez ré-utiliser le même objet bitmap pour chaque badge exemple pour un numéro de téléphone au lieu de constamment créer un nouveau helper instances de classe et re-récupération de l'image bitmap - mais mon but ici est de poster une solution qui est réduite à un minimum absolu, pour plus de clarté, tandis que dans le même temps offrir une gamme complète et utilisable solution hors de la boîte. Cette solution a été construit et testé sur Andriod 4.0, et testé sur 4.1 ainsi.

16voto

assaf passal Points 151

Après de nombreuses nuits de débogage, je découvre que la meilleure approche consiste à utiliser les contact id et si elle ne parvient pas à utiliser les photo id .

 public static Bitmap loadContactPhoto(ContentResolver cr, long  id,long photo_id) 
{

    Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
    InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
    if (input != null) 
    {
        return BitmapFactory.decodeStream(input);
    }
    else
    {
        Log.d("PHOTO","first try failed to load photo");

    }

    byte[] photoBytes = null;

    Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, photo_id);

    Cursor c = cr.query(photoUri, new String[] {ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);

    try 
    {
        if (c.moveToFirst()) 
            photoBytes = c.getBlob(0);

    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();

    } finally {

        c.close();
    }           

    if (photoBytes != null)
        return BitmapFactory.decodeByteArray(photoBytes,0,photoBytes.length);
    else
        Log.d("PHOTO","second try also failed");
    return null;
}
 

le code testé sur l'émulateur et le périphérique Nexus S et semble fonctionner.

16voto

ROFLwTIME Points 2223

Les gars, j'ai passé de nombreuses heures à essayer de comprendre cela. Voici une méthode que j'ai créée et qui vous permettra d'obtenir votre photo sur facebook par numéro de téléphone (sans tirets). Vous pouvez bien sûr le modifier en conséquence:

     public Bitmap getFacebookPhoto(String phoneNumber) {
    Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
    Uri photoUri = null;
    ContentResolver cr = this.getContentResolver();
    Cursor contact = cr.query(phoneUri,
            new String[] { ContactsContract.Contacts._ID }, null, null, null);

    if (contact.moveToFirst()) {
        long userId = contact.getLong(contact.getColumnIndex(ContactsContract.Contacts._ID));
        photoUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, userId);

    }
    else {
        Bitmap defaultPhoto = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_report_image);
        return defaultPhoto;
    }
    if (photoUri != null) {
        InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(
                cr, photoUri);
        if (input != null) {
            return BitmapFactory.decodeStream(input);
        }
    } else {
        Bitmap defaultPhoto = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_report_image);
        return defaultPhoto;
    }
    Bitmap defaultPhoto = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_report_image);
    return defaultPhoto;
}
 

5voto

kellogs Points 1220

Aucune de ces approches n'a fonctionné pour moi. Quel était le travail était:

 String[] projection = new String[] {
                ContactsContract.Contacts.PHOTO_ID,                 ///< the correct ID for photo retrieval in loadLocalContactPhotoBytes()
//              ContactsContract.Contacts._ID,
                ContactsContract.Contacts.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER,
//              ContactsContract.CommonDataKinds.Photo.PHOTO
        };

        ContentResolver cr = ctx.getContentResolver();

        Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                //      Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,
                //              new String[] {RawContacts._ID, RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_NAME},
                //              new String[] {Contacts._ID},
                projection, null, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");

....
 

// le 'curseur' ci-dessus est passé comme argument ci-dessous

     private byte[] loadLocalContactPhotoBytes(ContentResolver cr, Cursor cursor, byte[] defaultPhotoBytes)
    {
        byte[] photoBytes = null;// = cursor.getBlob(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.PHOTO));

//      int id = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));
        int id = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID));
//      Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
//      Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
        Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, id);

        Cursor c = cr.query(photoUri, new String[] {ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);

        try 
        {
            if (c.moveToFirst()) 
                photoBytes = c.getBlob(0);

        } catch (Exception e) {
            // TODO: handle exception
            Log.w(_TAG, e.toString());

        } finally {

            c.close();
        }           

        photoBytes = photoBytes == null ? defaultPhotoBytes : photoBytes;
        return photoBytes;
    }
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X