【问题标题】:Get contacts photo which are synced with facebook for android获取与 facebook for android 同步的联系人照片
【发布时间】:2011-04-20 05:20:15
【问题描述】:

我试图在我的应用程序中显示联系人图片,但我得到的只是手动添加的图片,而不是与 facebook 同步的图片。如何解决这个问题?下面是我的代码:

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

【问题讨论】:

  • 我遇到了同样的问题。似乎仅与 FB 同步的联系人会出现此问题。对于从多个来源同步的联系人,即 twitter 和 FB,这很好。

标签: android facebook contacts sync image


【解决方案1】:

它不适用于仅从 FB 同步的联系人。您需要使用 FB graph 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;
}

【讨论】:

  • 为什么总是出错?当我连接到该 URL 时权限被拒绝?
  • 您是否忘记将 INTERNET 权限添加到您的 AndroidManifest.xml 中?
【解决方案2】:

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

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

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

作为系统进程运行的相同代码会很好地提取照片。只是目前还不可能。

【讨论】:

    【解决方案3】:

    您提供的代码只能访问默认照片。此外,您应该将联系人 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 表中获取它(假设您知道您要查找的帐户...可能因同步提供程序实施而异...)

    【讨论】:

    • 此方法仍会导致来自 facebook for android 的图片为空字节。我想这是因为 facebook for android 的 api 有一个白名单系统,它允许数据只共享给 android 默认应用程序。
    • 我可以发誓,在使用类似方法之前我已经加载了 Facebook 照片……不过,这可能取决于您的同步提供商。我相信那里有几个不同的。您是否尝试过切换到不同的 Facebook 客户端应用程序?
    • 是的,这正是问题所在。 facebook 的官方应用程序(facebook for android)似乎有一个愚蠢的政策,阻止其他应用程序使用数据。我很确定 Facebook 的另一个同步应用程序可以完成这项工作。
    【解决方案4】:

    我得到了所有联系人的图片,甚至是从 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 时,检索照片才对我有用。然后,无论从何处同步,您都将获得此人的默认图像。

    【讨论】:

    • 这是否也适用于仅 FB 同步的联系人?我尝试过,但在尝试检索照片输入流后输入为 null 失败。
    • 我看了看,它似乎只适用于一些 facebook 图片。看起来一些 Facebook 图片已复制到此人的 google 联系人中,然后我才能加载这些图片。
    【解决方案5】:

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

    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 注入,这需要有根手机。

    【讨论】:

    • 这似乎不再适用于 Android 4.0.x 设备。生成的 SQL 被转义以防止注入。 :(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 2017-07-10
    • 2014-01-19
    • 1970-01-01
    • 2014-01-14
    • 2015-11-17
    相关资源
    最近更新 更多