2010-10-02 3 views
7

Sto cercando di mostrare le immagini dei contatti nella mia applicazione, ma sto ottenendo le immagini di coloro che sono stati aggiunti solo manualmente e non quelli che sono sincronizzati con Facebook. Come aggirare questo? Ecco il mio codice qui sotto:Ottenere foto dei contatti sincronizzati con facebook per 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

Sto riscontrando lo stesso problema. Sembra che il problema si verifichi con i contatti che sono sincronizzati solo con FB. Per i contatti sincronizzati da più fonti, ad esempio Twitter e FB, va bene. –

risposta

0

Il codice che hai fornito dovrebbe solo accedere alla foto predefinita. Inoltre, dovresti aggiungere l'ID contatto a quell'URI, non l'ID foto (presumendo che tu stia utilizzando l'id della foto dalla tabella dati).

Se ci sono più foto si potrebbe voler provare ad accedervi direttamente dalla tabella Dati. Avrai bisogno di analizzare un cursore di database e convertire i dati di byte grezzi in una bitmap manualmente come illustrato di seguito:

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

si vorrebbe mContactId per corrispondere con il contatto che si desidera fotografie.

Se si desidera limitare solo alle foto di Facebook, è necessario utilizzare ContactsContract.Data.RAW_CONTACT_ID invece, che si dovrebbe ottenere dalla tabella RawContacts utilizzando l'ID di contatto e un filtro basato sull'account Facebook (assumendo che sai cosa conto che stai cercando ... che può variare a seconda del fornitore di implementazione sync ...)

+0

Questo metodo genera ancora un byte null per le immagini da Facebook per Android. Immagino sia perché l'API di facebook per Android ha un sistema di whitelist che consente di condividere i dati con le sole applicazioni Android predefinite. – Yash

+0

Ancora grazie per la tua risposta – Yash

+0

Potrei giurare che ho caricato le foto di Facebook prima di usare un metodo simile ... potrebbe dipendere dal tuo provider di sincronizzazione. Credo che ce ne siano molti diversi là fuori. Hai provato a passare a un'altra app client di Facebook? –

0

ottengo l'immagine per tutti i contatti, anche alcuni che sono sincronizzati da facebook con questo codice:

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

Forse dare ancora un'occhiata al codice che crea il tuo ID di foto. Non utilizzare l'ID di una foto nella tabella dati per creare l'Uri. L'ho provato anche io e il recupero della foto ha funzionato per me solo se utilizzo un uri che si collega direttamente all'utente unificato. Otterrai quindi l'immagine predefinita per questa persona indipendentemente da dove è stata sincronizzata.

+0

Funziona anche per i contatti con sincronizzazione FB? Ho provato ma non riesce con input null dopo aver provato a recuperare il flusso di input fotografico. –

+0

Ho dato un'occhiata a questo e sembra che funzioni solo per alcune foto di Facebook. Sembra che alcune delle immagini di Facebook siano state copiate nel contatto Google per la persona e solo dopo sono riuscito a caricare queste immagini. – Janusz

4

Non funziona per i contatti sincronizzati solo da FB. Dovrai utilizzare l'API del grafico FB e recuperare la foto da lì; e devi conoscere il nome di facebook di contatti.

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

Perché è sempre un errore? PERMESSO NEGATO quando mi collego a quell'URL? – user430926

+1

Hai dimenticato di aggiungere l'autorizzazione INTERNET al tuo AndroidManifest.xml? –

2

Ho provato ogni soluzione trovata su Stack Overflow, al momento della stesura di questo e nulla sarà correttamente recuperare una foto che è venuto da Facebook tramite l'adattatore conto sincronizzazione ufficiale di Facebook app.

Per essere chiari, le persone che pubblicano soluzioni che "pensano" che stiano lavorando probabilmente utilizzano i telefoni HTC sense forniti con un adattatore di sincronizzazione Facebook scritto da HTC che non ha gli stessi requisiti di sicurezza dell'app Facebook ufficiale.

È una cosa di sicurezza e uno dei metodi è riuscito a provare ad accedere ai byte della foto di Facebook e si finirà con una SqliteException che dice che il contenuto richiesto è limitato.

Lo stesso codice eseguito come un processo di sistema eliminerà la foto. Non è possibile al momento.

0

Non c'è sicuramente modo di farlo in un modo standard. Quindi, dobbiamo usare un'iniezione SQL per poter hackerare il database dei contatti e ottenere gli avatar di Facebook. Il seguente codice funziona sulla maggior parte Motorolas, che utilizzano Motoblur, su Android 2.2 o superiore:

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

Per altri portatili è necessario ottenere il database dei contatti e analizzarli al fine di determinare come applicare la SQL Injection, che richiede un telefono con le radici.

+0

Questo non sembra funzionare su dispositivi Android 4.0.x più. L'SQL generato è sottoposto a escape per impedire l'iniezione. :( –