You can use the Google Places API for Android to request place photos to display in your application. Photos returned by the photos service come from a variety of sources, including business owners and Google+ user-contributed photos. To retrieve images for a place, you must take the following steps:
- Call
GeoDataApi.getPlacePhotos(), passing a string with a place ID. This returns aPlacePhotoMetadataResultinstance. - Call
getPhotoMetadata()on thePlacePhotoMetadataResultinstance to get aPlacePhotoMetadataBufferholding a list ofPlacePhotoMetadatainstances (one for each photo). Call
get()on thePlacePhotoMetadataBufferinstance, passing an integer to retrieve thePlacePhotoMetadatainstance at the given index.- To return a bitmap image, call either
PlacePhotoMetadata.getPhoto(), orPlacePhotoMetadata.getScaledPhoto()on aPlacePhotoMetadatainstance. - To return attribution text, call
PlacePhotoMetadata.getAttributions()on aPlacePhotoMetadatainstance.
- To return a bitmap image, call either
The Google Places API for Android requires network access, therefore all calls must be made in the background, off the main UI thread. For this reason, we recommend retrieving photos in the background asynchronously. For examples of how to do this, see Get photos in the background using AsyncTask, and Get photos in the background using ResultCallback.
The following simplified code snippet demonstrates getting a list of photos for a place.
// Get a PlacePhotoMetadataResult containing metadata for the first 10 photos.
PlacePhotoMetadataResult result = Places.GeoDataApi
.getPlacePhotos(mGoogleApiClient, placeId).await();
// Get a PhotoMetadataBuffer instance containing a list of photos (PhotoMetadata).
if (result != null && result.getStatus().isSuccess()) {
PlacePhotoMetadataBuffer photoMetadataBuffer = result.getPhotoMetadata();
}
The following simplified code snippet demonstrates getting a
PlacePhotoMetadata instance, then using that instance to get a
full-size bitmap image and attribution text:
// Get the first photo in the list.
PlacePhotoMetadata photo = photoMetadataBuffer.get(0);
// Get a full-size bitmap for the photo.
Bitmap image = photo.getPhoto(mGoogleApiClient).await()
.getBitmap();
// Get the attribution text.
CharSequence attribution = photo.getAttributions();
Get photos in the background using AsyncTask
We recommend using AsyncTask to implement place photos in your app. Here is a summary of the steps required to do this:
- Connect to the Places API.
- Create a task class that extends AsyncTask to encapsulate the calls to retrieve PlacePhotoMetadata and request the image.
- Create a method instantiating that class to handle image requests.
Create a photo task class
The following example class takes a place ID and gets the first photo in the returned list. You can use this class as a template for the class you will create in your own app.
abstract class PhotoTask extends AsyncTask<String, Void, PhotoTask.AttributedPhoto> {
private int mHeight;
private int mWidth;
public PhotoTask(int width, int height) {
mHeight = height;
mWidth = width;
}
/**
* Loads the first photo for a place id from the Geo Data API.
* The place id must be the first (and only) parameter.
*/
@Override
protected AttributedPhoto doInBackground(String... params) {
if (params.length != 1) {
return null;
}
final String placeId = params[0];
AttributedPhoto attributedPhoto = null;
PlacePhotoMetadataResult result = Places.GeoDataApi
.getPlacePhotos(mGoogleApiClient, placeId).await();
if (result.getStatus().isSuccess()) {
PlacePhotoMetadataBuffer photoMetadataBuffer = result.getPhotoMetadata();
if (photoMetadata.getCount() > 0 && !isCancelled()) {
// Get the first bitmap and its attributions.
PlacePhotoMetadata photo = photoMetadata.get(0);
CharSequence attribution = photo.getAttributions();
// Load a scaled bitmap for this photo.
Bitmap image = photo.getScaledPhoto(mGoogleApiClient, mWidth, mHeight).await()
.getBitmap();
attributedPhoto = new AttributedPhoto(attribution, image);
}
// Release the PlacePhotoMetadataBuffer.
photoMetadataBuffer.release();
}
return attributedPhoto;
}
/**
* Holder for an image and its attribution.
*/
class AttributedPhoto {
public final CharSequence attribution;
public final Bitmap bitmap;
public AttributedPhoto(CharSequence attribution, Bitmap bitmap) {
this.attribution = attribution;
this.bitmap = bitmap;
}
}
}
Handle photo requests
The following example demonstrates creating a method that instantiates the
example class (PhotoTask), to request images for a place.
private void placePhotosTask() {
final String placeId = "ChIJrTLr-GyuEmsRBfy61i59si0"; // Australian Cruise Group
// Create a new AsyncTask that displays the bitmap and attribution once loaded.
new PhotoTask(mImageView.getWidth(), mImageView.getHeight()) {
@Override
protected void onPreExecute() {
// Display a temporary image to show while bitmap is loading.
mImageView.setImageResource(R.drawable.empty_photo);
}
@Override
protected void onPostExecute(AttributedPhoto attributedPhoto) {
if (attributedPhoto != null) {
// Photo has been loaded, display it.
mImageView.setImageBitmap(attributedPhoto.bitmap);
// Display the attribution as HTML content if set.
if (attributedPhoto.attribution == null) {
mText.setVisibility(View.GONE);
} else {
mText.setVisibility(View.VISIBLE);
mText.setText(Html.fromHtml(attributedPhoto.attribution.toString()));
}
}
}
}.execute(placeId);
}
Get photos in the background using ResultCallback
As an alternative to AsyncTask, you can make photo requests asynchronously by using ResultCallback. The following code example demonstrates how to do this.
private ResultCallback<PlacePhotoResult> mDisplayPhotoResultCallback
= new ResultCallback<PlacePhotoResult>() {
@Override
public void onResult(PlacePhotoResult placePhotoResult) {
if (!placePhotoResult.getStatus().isSuccess()) {
return;
}
mImageView.setImageBitmap(placePhotoResult.getBitmap());
}
};
/**
* Load a bitmap from the photos API asynchronously
* by using buffers and result callbacks.
*/
private void placePhotosAsync() {
final String placeId = "ChIJrTLr-GyuEmsRBfy61i59si0"; // Australian Cruise Group
Places.GeoDataApi.getPlacePhotos(mGoogleApiClient, placeId)
.setResultCallback(new ResultCallback<PlacePhotoMetadataResult>() {
@Override
public void onResult(PlacePhotoMetadataResult photos) {
if (!photos.getStatus().isSuccess()) {
return;
}
PlacePhotoMetadataBuffer photoMetadataBuffer = photos.getPhotoMetadata();
if (photoMetadataBuffer.getCount() > 0) {
// Display the first bitmap in an ImageView in the size of the view
photoMetadataBuffer.get(0)
.getScaledPhoto(mGoogleApiClient, mImageView.getWidth(),
mImageView.getHeight())
.setResultCallback(mDisplayPhotoResultCallback);
}
photoMetadataBuffer.release();
}
});
}
Attributions
In most cases, place photos can be used without attribution, or will have
the required attribution included as part of the image. However, if the
returned
PlacePhotoMetadata instance includes an attribution, you must
include the additional attribution in your application wherever you display the
image. For more information, see
Displaying Attributions.
Usage limits
Retrieving an image costs one unit of quota; there are no usage limits for retrieving photo metadata. See the documentation on usage limits.