获取与facebook同步的联系人照片

时间:2010-10-02 11:59:40

标签: android facebook contacts sync image

我正在尝试在我的应用程序中显示联系人图片,但我正在获取那些仅手动添加的图片,而不是那些与facebook同步的图片。如何解决这个问题?以下是我的代码:

Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(PhotoId));
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
return BitmapFactory.decodeStream(input);

5 个答案:

答案 0 :(得分:4)

它不适用于仅从FB同步的联系人。您需要使用FB图形API并从那里获取照片;你需要知道联系人的facebook名字。

 Bitmap contactPhoto = getImageBitmap("http://graph.facebook.com/mathiaslin/picture?type=square");

 final private static Bitmap getImageBitmap(String url) {
    Bitmap bm = null;
    try {
        URLConnection conn = new URL(url).openConnection();
        conn.connect();
        InputStream is = conn.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        bm = BitmapFactory.decodeStream(bis);
        bis.close();
        is.close();
    } catch (IOException e) {
        Log.e(TAG, "Error getting bitmap", e);
    }
    return bm;
}

答案 1 :(得分:2)

在撰写本文时,我已尝试在Stack Overflow上找到的所有解决方案,没有任何内容可以通过官方Facebook应用帐户同步适配器正确检索来自Facebook的照片。

要明确的是,发布“认为”他们工作的解决方案的人可能正在使用HTC感应手机,该手机配有由HTC编写的Facebook同步适配器,其安全要求与官方Facebook应用程序不同。

这是一个安全问题,其中一个方法确实试图访问Facebook照片的字节,你最终会得到一个SqliteException,说请求的内容是受限制的。

与系统进程运行相同的代码会将照片拉得很好。现在就不可能了。

答案 2 :(得分:0)

您提供的代码只能访问默认照片。此外,您应该将联系人ID附加到该URI,而不是照片ID(假设您正在使用数据表中的照片ID)。

如果有多张照片,您可能需要尝试直接从数据表中访问它们。您需要解析数据库游标并手动将原始字节数据转换为位图,如下所示:

String[] projection = {ContactsContract.CommonDataKinds.Photo.PHOTO};
Uri uri = Uri. ContactsContract.Data.CONTENT_URI;
String where = ContactsContract.Data.MIMETYPE 
       + "=" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + " AND " 
       + ContactsContract.Data.CONTACT_ID + " = " + mContactId;
Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);

if(cursor!=null&&cursor.moveToFirst()){
    do{
        byte[] photoData = photoCursor.getBlob(0);
        Bitmap photo = BitmapFactory.decodeByteArray(photoData, 0,
                photoData.length, null);

        //Do whatever with your photo here...
    }while(cursor.moveToNext());
}

您希望mContactId与您想要照片的联系人对应。

如果你想限制只有facebook照片,你需要使用ContactsContract.Data.RAW_CONTACT_ID,你应该使用你的联系人ID和基于facebook帐户的过滤器从RawContacts表中获取(假设你知道)您正在寻找什么帐户......可能因同步提供商实施而异...)

答案 3 :(得分:0)

我得到了所有联系人的照片,甚至还有一些通过此代码与facebook同步的联系人:

 * @param context
 *            The context used to retrieve the image.
 * @return The image of the user that is saved in the address book or null if
 *         the user does not exists or has no image.
 */
public Bitmap getContactPhoto(Context context) {
    ContentResolver contentResolver = context.getContentResolver();
    Uri photoUri = getCurrentUri(contentResolver);

    if (photoUri != null) {
        InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(
                contentResolver, photoUri);
        if (input != null) {
            return BitmapFactory.decodeStream(input);
        }
    } else {
        Log.d(getClass().getSimpleName(), "No photo Uri");
    }
    return null;
}

private Uri getCurrentUri(ContentResolver contentResolver) {
    Cursor contact = contentResolver.query(lookUpUri,
            new String[] { ContactsContract.Contacts._ID }, null, null, null);

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

或许再次查看创建photoId的代码。不要使用数据表中的照片ID来创建Uri。我也尝试过,只有当我使用直接链接到合并用户的uri时才检索照片。然后,您将获得此人的默认图像,无论其在哪里同步。

答案 4 :(得分:0)

绝对没有办法以标准的方式做到这一点。因此,我们必须使用SQL注入,以便能够破解联系人数据库并获取Facebook头像。以下代码适用于在Android 2.2或更高版本上使用Motoblur的大多数Motorolas:

public static Bitmap loadFacebookAvatar(Context context, long personId) {
    String[] rawProjection = {ContactsContract.RawContacts._ID};
    String contactIdAssertion = ContactsContract.RawContacts.CONTACT_ID + " = " + personId;
    String rawWhere = new StringBuilder()
            .append(contactIdAssertion).append(") UNION ALL SELECT ")
            .append(ContactsContract.RawContacts._ID).append(" FROM view_raw_contacts WHERE (")
            .append(contactIdAssertion).toString();
    Cursor query = context.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI,
            rawProjection,
            rawWhere, null, null);
    if (query != null && query.moveToFirst()) {
        do {
            long id = query.getLong(query.getColumnIndex(ContactsContract.RawContacts._ID));
            String[] projection = {ContactsContract.CommonDataKinds.Photo.PHOTO};
            Uri uri = ContactsContract.Data.CONTENT_URI;

            String mimeTypeAssertion = ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
            String photoAssertion = ContactsContract.CommonDataKinds.Photo.PHOTO + " IS NOT NULL";
            String rawContactIdAssertion = ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID + " = " + id;

            String where = new StringBuilder().append(mimeTypeAssertion).append(" AND ")
                    .append(photoAssertion).append(" AND ").append(rawContactIdAssertion)
                    .append(") UNION ALL SELECT ").append(ContactsContract.CommonDataKinds.Photo.PHOTO)
                    .append(" FROM view_data WHERE (").append(photoAssertion).append(" AND ")
                    .append(rawContactIdAssertion).toString();

            Cursor photoQuery = context.getContentResolver().query(uri, projection, where, null, null);
            if (photoQuery != null && photoQuery.moveToFirst()) {
                do {
                    byte[] photoData = photoQuery.getBlob(photoQuery.getColumnIndex(ContactsContract.CommonDataKinds.Photo.PHOTO));
                    if (photoData != null) {
                        return BitmapFactory.decodeByteArray(photoData, 0, photoData.length, null);
                    }
                } while (photoQuery.moveToNext());
            }
        } while (query.moveToNext());
    }
    return null;
}

对于其他手机,您必须获取联系人数据库并对其进行分析,以确定如何应用SQL注入,这需要带有根电话。