2010-10-02 21 views
7

Estoy tratando de mostrar imágenes de contacto en mi aplicación, pero estoy obteniendo imágenes de aquellas que se agregaron manualmente y no las que están sincronizadas con Facebook. ¿Cómo solucionar esto? Aquí está mi código a continuación:Obtener fotos de contactos que están sincronizadas con Facebook para Android

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

Estoy experimentando el mismo problema. Parece que el problema ocurre con los contactos que solo están sincronizados con FB. Para los contactos que se sincronizan desde múltiples fuentes, es decir, Twitter y FB, está bien. –

Respuesta

0

El código que ha proporcionado solo debe acceder a la fotografía predeterminada. Además, debe agregar la ID de contacto a esa URI, no la ID de la foto (suponiendo que esté usando la identificación de la foto de la tabla de datos).

Si hay varias fotos, puede intentar acceder a ellas directamente desde la tabla de datos. Tendrá que analizar un cursor de base de datos y convertir los datos de bytes sin procesar en un mapa de bits de forma manual como se muestra a continuación:

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

le gustaría que mContactId para que se corresponda con el contacto que desea para fotos.

Si desea limitar solo las fotos de Facebook, necesitará usar ContactsContract.Data.RAW_CONTACT_ID en su lugar, que debe obtener de la tabla RawContacts con su ID de contacto y un filtro basado en la cuenta de Facebook (asumiendo que Cuenta sabe lo que está buscando ... que puede variar según la implementación del proveedor de sincronización ...)

+0

Este método todavía resulta en un byte nulo para las imágenes de Facebook para Android. Supongo que es porque la API de Facebook para Android tiene un sistema de lista blanca que permite que los datos se compartan solo con las aplicaciones predeterminadas de Android. – Yash

+0

Aún gracias por su respuesta – Yash

+0

Podría haber jurado que he cargado fotos de Facebook antes de usar un método similar ... sin embargo, puede depender de su proveedor de sincronización. Creo que hay varios diferentes por ahí. ¿Has intentado cambiar a una aplicación de cliente de Facebook diferente? –

0

tengo la imagen para todos los contactos, incluso algunos que se sincronizan desde facebook con este código:

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

Tal vez revise nuevamente el código que crea su photoId. No use la Id de una foto en la tabla de datos para crear el Uri. También probé y recuperar la foto funcionó solo si uso un uri que enlaza directamente con el usuario fusionado. A continuación, obtendrá la imagen predeterminada para esta persona independientemente de donde se haya sincronizado.

+0

¿Funciona esto también para contactos solo sincronizados con FB? Intenté pero falla con la entrada siendo nula después de tratar de recuperar la secuencia de entrada de fotos. –

+0

Lo he visto y parece que solo funciona para algunas fotos de Facebook. Parece que algunas de las fotos de Facebook se copiaron en el contacto de Google para la persona y solo entonces puedo cargar estas imágenes. – Janusz

4

No funciona para los contactos que se sincronizan solo desde el FB. Tendrá que usar la API de gráficos de FB y buscar la foto desde allí; y necesitas saber el nombre de facebook de contactos.

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

¿Por qué siempre es un error? PERMISO DENEGADO cuando me conecto a esa URL? – user430926

+1

¿Olvidaste agregar el permiso de INTERNET a tu AndroidManifest.xml? –

2

He intentado todas las soluciones se encuentran en desbordamiento de pila en el momento de escribir esto y nada va a recuperar correctamente una foto que venía de Facebook a través del adaptador de sincronización de la cuenta oficial de Facebook aplicación.

Para ser claros, las personas que publican soluciones que "piensan" que trabajan probablemente utilicen teléfonos HTC sense que vienen con un adaptador de sincronización de Facebook escrito por HTC que no tiene los mismos requisitos de seguridad que la aplicación oficial de Facebook.

Es una cuestión de seguridad y uno de los métodos logró tratar de acceder a los bytes de la foto de Facebook y terminará con una SqliteException diciendo que el contenido solicitado está restringido.

El mismo código ejecutado como un proceso de sistema extraerá la foto bien. Simplemente no es posible a partir de ahora.

0

Definitivamente no hay forma de hacerlo de forma estándar. Entonces, debemos usar una Inyección SQL para poder piratear la base de datos de contactos y obtener los avatares de Facebook. El siguiente código funciona en la mayoría de Motorola, que utilizan Motoblur, en Android 2.2 o superior:

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

Para otros terminales debe obtener la base de datos de contactos y analizarla para determinar cómo aplicar la inyección de SQL, lo que requiere un teléfono rooteado

+0

Parece que esto no funciona en dispositivos con Android 4.0.x. El SQL generado se escapó para evitar la inyección. :( –

Cuestiones relacionadas