Display contact avatars using Picasso loading

Picasso comes with support for loading and displaying contact avatars, as long as the URL of the contact avatar is passed in, for example
"photo:content://com.android.contacts/contacts/1005/photo", then call Picasso.load(Uri).into(ImageView), The display of the avatar of the contact can be completed.

But this usage has a limitation: when we don’t know the avatar URL of a contact, we must first obtain the URL of the contact’s avatar by name (or other, such as phone number), which is usually a time-consuming operation ( Querying the database) needs to be done asynchronously; in this way, the avatar URL is first asynchronously queried, and then handed over to Picasso for asynchronous loading and display. The two-level asynchrony seems a bit tasteless. Therefore, in addition to briefly introducing

  • Picasso comes with built-in support for contact avatars

In addition, another usage will be introduced,

  • Using a custom RequestHandler

Below, we take the method of obtaining contact avatar based on the contact name as an example to explain these two usages.

1. Use Picasso’s built-in support to load

Picasso (take version 2.5.2 as an example) supports a total of 5 URL formats for contact avatars

  • photo:content://com.android.contacts/contacts/lookup/*/#
  • photo:content://com.android.contacts/contacts/lookup/*
  • photo:content://com.android.contacts/contacts/#/photo
  • photo:content://com.android.contacts/contacts/#
  • photo:content://com.android.contacts/display_photo/#

The loading process consists of the following steps:

1. Get the URL of the contact’s avatar according to the name

Uri elvisUrl = getContactPhotoUrl("Elvis");

/**
 * Get the URL of the contact's avatar by name.
 * @param contactName the name of the contact
 * @return URL of contact avatar
 */
@Nullable
public static Uri getContactPhotoUrl(Context context, String contactName) {
  Uri phoneUri = null;
  Cursor cursor = context.getContentResolver().query(
      ContactsContract.Contacts.CONTENT_URI,
      new String[]{ContactsContract.Contacts.PHOTO_URI},
      ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " = ?",
      new String[]{contactName},
      null);
  if (cursor != null) {
    try {
      if (cursor. moveToFirst()) {
        String photoUrlString = cursor. getString(0);
        if (!TextUtils. isEmpty(photoUrlString)) {
          phoneUri = Uri. parse(photoUrlString);
        }
      }
    } finally {
      cursor. close();
    }
  }
  return phoneUri;
}

2. Use Picasso.load(Uri).into(ImageView) to display

mPicasso.load(elvisUrl).into(imageView);

2. Use a custom RequestHandler to load

1. Custom RequestHandler

public static final String URL_SCHEMA_CONTACT_PHOTO = "contact.photo";

private class CustomRequestHandler extends RequestHandler {
  @Override
  public boolean canHandleRequest(Request data) {
    return URL_SCHEMA_CONTACT_PHOTO.equals(data.uri.getScheme());
  }

  /**
   * Return the thumbnail data of the contact avatar as an input stream.
   */
  @Override
  public Result load(Request request, int networkPolicy) throws IOException {
    Uri uri = request.uri;
    // Parse the contact name from the contact URL
    String contactName = uri. getAuthority();
    // Get the Contact ID of the contact by name
    long contactId = getContactId(mContext, contactName);
    if (contactId <= 0) {
      return null;
    }
    // Obtain the thumbnail data of the contact avatar according to the Contact ID of the contact
    byte[] photoData = loadPhotoData(mContext, contactId);
    if (photoData == null) {
      return null;
    }
    InputStream photoInputStream = new ByteArrayInputStream(photoData);
    return new Result(photoInputStream, Picasso. LoadedFrom. DISK);
  }
}

/**
 * Get the Contact ID of a contact by name.
 *
 * @param displayName the name of the contact
 * @return Contact ID of the contact
 */
public static long getContactId(Context context, String displayName) {
  long contactId = 0;
  ContentResolver contentResolver = context. getContentResolver();
  Uri uri = ContactsContract.Data.CONTENT_URI;
  String[] projection = new String[]{ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID};
  String selection = ContactsContract.Data.MIMETYPE + " = ? AND "
       + ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME + " = ?";
  String[] selectionArguments = {
      ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, displayName};
  Cursor cursor = contentResolver. query(uri, projection, selection, selectionArguments, null);
  if (cursor != null) {
    try {
      if (cursor. moveToFirst()) {
        contactId = cursor. getLong(0);
      }
    } finally {
      cursor. close();
    }
  }
  return contactId;
}

/**
 * Get the thumbnail data of the contact's avatar according to the contact's Contact ID.
 *
 * @param contactId Contact ID of the contact
 * @return thumbnail data of contact avatar
 */
public static byte[] loadPhotoData(Context context, long contactId) {
  byte[] photoData = null;
  Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
  Uri photoUri = Uri.withAppendedPath(contactUri,
      ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
  Cursor cursor = context.getContentResolver().query(photoUri,
      new String[]{ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
  if (cursor != null) {
    try {
      if (cursor. moveToFirst()) {
        photoData = cursor. getBlob(0);
      }
    } finally {
      cursor. close();
    }
  }
  return photoData;
}

2. Add a custom RequestHandler when initializing Picasso

mPicasso = new Picasso. Builder(context)
    .addRequestHandler(new CustomRequestHandler())
    ... // omit other configuration
    .build();

3. Assemble the avatar URL for the contact (“Elvis”)

/**
 * Gets the URL representing the avatar thumbnail for a specific contact
 *
 * @param contactName the display name of the specific contact
 * @return URL representing the avatar thumbnail of a specific contact
 */
public static Uri getContactPhotoLoadableUrl(String contactName) {
  return new Uri.Builder().scheme(URL_SCHEMA_CONTACT_PHOTO).authority(contactName).build();
}

Uri elvisUrl = getContactPhotoLoadableUrl("Elvis");

4. Use Picasso.load(Uri).into(ImageView) to display

mPicasso.load(elvisUrl).into(imageView);

So far, the two methods of using Picasso to add screenshots to display contact avatars have been introduced. You can choose one to use according to your needs. When the URL of the contact’s avatar is unknown, the second option is preferred, so that the loading of the avatar of the contact can be as easy as loading other network pictures.

about the author
ElvisHew’s open source project: XLog
ElvisHew’s Github homepage: https://github.com/elvishew
ElvisHew’s Sina Weibo: http://weibo.com/elvishew

Author: Elvis Hew
Link: https://www.jianshu.com/p/5488e3b7f3bc
Source: Jianshu
Copyright belongs to the author. For commercial reprint, please contact the author for authorization, for non-commercial reprint, please indicate the source.