1

Loading images with Picasso is seemingly so easy, until I hit this roadblock. Not sure why! I can load photos from contacts via PHOTO_URI if the contacts only have a thumbnail, or, if I instead ask for PHOTO_THUMBNAIL_URI specifically.

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        ImageView icon = (ImageView)view.findViewById(R.id.ContactImage);
        String photoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI));

        if (photoUri == null) {
            icon.setImageDrawable(null);
        } else {
            Picasso.with(context).load(photoUri).into(icon);
        }
    }

For what it's worth: if I use Picasso.with(context).load(photoUri).placeholder(R.drawable.placeholder).error(R.drawable.error).into(icon); then I see the placeholder image in the place of every contact who has a high res image. I never see an "error" picture. If I revert back to just using icon.setImageURI(Uri.parse(photoUri)); then I see the high res contact images again just fine. (But then I don't have a snazzy async caching picture loader!)

UPDATE: Thanks to @copolii and his answers below, the following now works flawlessly with Picasso 2.1.1:

@Override
public void bindView(View view, Context context, Cursor cursor) {

    Long id = cursor.getLong(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
    Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
    String photoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI));

    ImageView icon = (ImageView)view.findViewById(R.id.ContactImage);

    if (photoUri == null) {
        icon.setImageDrawable(null);
    } else {
        Picasso
            .with(context)
            .load(contactUri)
            .into(icon);
    }

}

This loads the higher-res photo, if there is one, and if not, shows the low-res photo, and if there is no photo set for a contact, it's set to a blank / null.

courtlandj
  • 435
  • 9
  • 19

1 Answers1

4

Have you tried using a contact uri?

That last boolean parameter in openContactPhotoInputStream promises to get you the high res photo if one is available.

Instead of using a photo uri use a contact uri or a contact lookup uri.

UPDATE Since the question has been answered, I though I'd post the relevant details here: A small test app is posted here (You need Android Studio): https://github.com/copolii/PicassoContactsTest

If you set both a placeholder and an error icon, the error icon is displayed for contacts who do not have a picture. I'd recommend setting the social face guy as your place-holder and no error icon. That way, your place-holder stays on if the contact has no picture.

If you do want to differentiate between the two, choose your error icon with the above in mind (i.e. don't use a big red OMFG error indicator).

--- Previous Content ---

Let me know if that helps.

I did the work for the contacts photo loading and unless I'm missing something, you should get the high resolution picture (API 14+) automatically:

if (SDK_INT < ICE_CREAM_SANDWICH) {
  return openContactPhotoInputStream(contentResolver, uri);
} else {
  return openContactPhotoInputStream(contentResolver, uri, true);
}

It seems that the openContactPhotoInputStream doesn't like the PHOTO_URI.

Android Docs: openContactPhotoInputStream

If the URIs are distinguishable I can easily add support for PHOTO_URI as well (I have to find out how to load it first though). I'm already determining if the given uri is a contact photo uri or a contact lookup uri (older android versions do not like lookup uris being fed into openContactPhotoInputStream so I have to dereference the lookup uri into a contact uri before passing it to openContactPhotoInputStream).

I hope this helps.

copolii
  • 14,208
  • 10
  • 51
  • 80
  • When I use PHOTO_URI, but a contact doesn't have a high res photo, it returns URIs like `content://com.android.contacts/contacts/38/photo` and it works and displays just fine. But if they have a high res photo, it returns a URI formed like `content://com.android.contacts/display_photo/5`, and this is when I get nothing, or, if set, the placeholder. – courtlandj Jan 19 '14 at 21:53
  • And to be clear, I am only getting a low-res version of their photo if I use PHOTO_THUMBNAIL_URI, even though I am running KitKat. Definitely above ICS. – courtlandj Jan 19 '14 at 22:25
  • OK, Thanks. that's useful information. It seems like `openContactPhotoInputStream` can't process uris like `content://com.android.contacts/display_photo/5` I'll give it a try in an small test app and see what's missing. – copolii Jan 20 '14 at 22:50
  • Have you tried using a `contact uri`? That last boolean parameter in `openContactPhotoInputStream` promises to get you the high res photo if one is available. Instead of using a `photo uri` use a `contact uri` or a `contact lookup uri`. Let me know if that helps. – copolii Jan 21 '14 at 03:52
  • Can you provide a sample app please so I can verify and fix for 2.2? – dnkoutso Jan 22 '14 at 17:14
  • @dnkoutso I'd do this myself and make a pull request, but I'm a bit busy for next little while. To be able to process PHOTO_URI for high res images, you'd have to get is as a BLOB (byte[]) from the Photo table, then feed the byte[] to BitmapFactory. Found an example here: http://stackoverflow.com/a/13362698/675750 – copolii Jan 22 '14 at 23:13
  • @copolii - I may need correction on using a "contact URI": I replace the photoUri in the original example with this contactUri `Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);` and I get the error image, if set, or if I use a contact lookup URI, I get the placeholder image, if set. `contactUri` looks like: `content://com.android.contacts/contacts/1491` or `content://com.android.contacts/contacts/255` – courtlandj Jan 23 '14 at 08:34
  • Well, the above was clearly, clearly using the wrong 'id' - silly me. I was using the `ContactsContract.CommonDataKinds.Contacts._ID` instead of `ContactsContract.CommonDataKinds.Phone.CONTACT_ID`. This now works, with full size images no less! I'll update my above example code with the working code block. Thanks for steering me towards this! – courtlandj Jan 23 '14 at 08:59
  • Any time :) I put a small test app here: https://github.com/copolii/PicassoContactsTest I'm gonna make the fix quickly and put in a pull request. It shouldn't be hard. If the `openContactPhotoInputStream` returns null it means the guy doesn't have a picture ... it's not really an error :) – copolii Jan 23 '14 at 09:45
  • Having looked at the code, I don't think it's really a bug ... or undesired behaviour. It should probably just be documented (and maybe it is) that if a contact has no display picture (low or high res) it is treated as an error. – copolii Jan 23 '14 at 09:59
  • I'll be able to review your pull. Thanks. – dnkoutso Jan 24 '14 at 06:57
  • @dnkoutso Pull request submitted. I've improved the overall handling and detection of the uris as well (no more string comparisons). https://github.com/square/picasso/pull/368 – copolii Jan 26 '14 at 04:24
  • I have also updated the test app (https://github.com/copolii/PicassoContactsTest) to use all 4 uris for testing (wasn't sure how you wanted to handle unit tests). – copolii Jan 26 '14 at 05:08
  • lookupuri does not work for thumbnail images on lower android versions (tested on API level 15). Thankyou for mentioning that! – Abraham Philip Mar 31 '15 at 17:57