当前位置:  开发笔记 > 编程语言 > 正文

如何加载联系人照片?

如何解决《如何加载联系人照片?》经验,为你挑选了5个好方法。

我在Android中为联系人加载照片时遇到问题.我已经google了一个答案,但到目前为止已经空了.有没有人有查询联系人,然后加载照片的例子?

因此,给定一个来自一个名为using的Activity结果的contactUri

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

是:

内容://com.android.contacts/data/1557

loadContact(..)工作正常.但是,当我调用getPhoto(...)方法时,我得到了照片InputStream的空值.它也令人困惑,因为URI值不同.contactPhotoUri评估为:

内容://com.android.contacts/contacts/1557

请参阅下面代码中的内联注释.

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

    }
}

显然,我在这里做错了,但我似乎无法弄清问题是什么.谢谢.



1> 小智..:

这对我有用:

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


嘿..这里的功能你通过id ..是照片ID还是联系ID?
这个方法在返回之前应该调用`input.close()`.
对于仅使用FB同步的联系人,对我不起作用.
人们一直在说替代方法有效.但我还没有看到一个库存设备上的工作(我认为HTC的同步适配器工作方式不同).任何人都可以确认同时拥有Google联系人和Facebook联系人(但只有Facebook联系人有照片)的用户可以将照片显示在只有Facebook应用同步适配器的手机上吗?

2> Phil..:

在扫描了显示缩略图问题的许多问题和答案之后,我想我会将我的解决方案发布到这个特定的难题,因为我只能找到一对完全没有工作且没有为懒惰的开发人员提供良好的固定解决方案.

下面的类采用Context,QuickContactBadge和电话号码,并且如果有可用于指定电话号码的图像,则将本地存储的图像附加到徽章.

这是班级:

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

}

}

这是活动中的典型用例:

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

在片段中它会略有不同:

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

现在有一些方法可以提高效率 - 例如,如果要渲染消息时间轴,则需要为给定电话号码的每个徽章实例重复使用相同的位图对象,而不是不断创建新的帮助程序类实例并重新检索位图 - 但我的目的是发布一个解决方案,为了清晰起见,该解决方案被剥离到绝对最小值,同时提供开箱即用的完整和可用的解决方案.此解决方案已在Andriod 4.0上构建和测试,并在4.1上进行了测试.


@DídacPérez我的回答看起来有些奇怪,因为你已经删除了你的评论(说我没有解决原来的问题).

3> ROFLwTIME..:

伙计们,我花了很多时间试图解决这个问题.这是我创建的一种方法,可以通过电话号码(无破折号)获取您的Facebook照片.当然,您可以相应地修改它:

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


我尝试了你的代码,但它不适用于我的HTC Sensation(Sense 3.0).恕我直言,我认为你的代码也只是做了contactId,然后将它提供给openContactPhotoInputStream - 它与@ wrongmissle的代码没有区别.事实上,2个解决方案的结果在我的手机上是一样的

4> 小智..:

在经过大量的调试之后,我发现最好的方法是使用它contact id,如果它没有使用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;
}

在模拟器和Nexus S设备上测试的代码似乎有效.



5> kellogs..:

这些方法都不适合我.工作是什么:

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

....

//上面的'游标'作为参数在下面传递

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

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有