I'm trying to get a photo from known placeID location ("ChIJqaUj8fBLzEwRZ5UY3sHGz90").
I'm using the code below (from the google guide)
PlacePhotoMetadataResult result = Places.GeoDataApi.getPlacePhotos(mGoogleApiClient, placeId).await();
if (result.getStatus().isSuccess()) {
PlacePhotoMetadataBuffer photoMetadataBuffer = result.getPhotoMetadata();
if (photoMetadataBuffer.getCount() > 0 && !isCancelled()) {
// Get the first bitmap and its attributions.
PlacePhotoMetadata photo = photoMetadataBuffer.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();
}
the result.getStatus returns a success, but PhotoMetadataBuffer is returned empty (photoMetadataBuffer.getCount = 0).
Has anyone successfully got an image using this method?
It looks like there aren't any photos associated with this place at the moment. If you try another place id that has associated photos, you should get some results. For example, try this place id:
ChIJN1t_tDeuEmsRUsoyG83frY4
Related
I can't seem to get the url, from the PlacePhotoMetadata object. Debugger shows that there is an URL there but I can't seem to access it.
How do you access the URL in the object?
val placeId = "ChIJa147K9HX3IAR-lwiGIQv9i4"
val photoMetadataResponse = mGeoDataClient.getPlacePhotos(placeId)
photoMetadataResponse.addOnCompleteListener { task ->
// Get the list of photos
val photos = task.result
// Get the PlacePhotoMetadataBuffer (metadata for all of the photos)
val photoMetadataBuffer = photos.photoMetadata
// Get the first photo in the list
for (photo in photoMetadataBuffer) {
// Get the attribution text
val attribution = photo.attributions
}
}
You can't. Take a look at the documentation for PlacePhotoMetadata. There are methods to download a bitmap of the image, but no methods that return the URL.
To get the photo you should do something like this:
// this is your for-loop:
photoMetadataBuffer.forEach { photo ->
photo.getPhoto(client).setResultCallback({ result ->
// do whatever you want here:
showPhotoWithAttribution(photo.attributions, result.getBitmap())
})
}
Note that replacing a for-loop with a forEach call has no real advantage, it just makes your code look cleaner.
I am referring Google Places photo android api.
I am using below code in onBindViewHolder of RecyclerView Adapter.
Half the time it throws Illegal State exception. Please help.
final Task<PlacePhotoMetadataResponse> photoMetadataResponse = mGeoDataClient.getPlacePhotos(placeId);
photoMetadataResponse.addOnCompleteListener(new OnCompleteListener<PlacePhotoMetadataResponse>() {
#Override
public void onComplete(#NonNull Task<PlacePhotoMetadataResponse> task) {
// Get the list of photos.
PlacePhotoMetadataResponse photos = task.getResult();
// Get the PlacePhotoMetadataBuffer (metadata for all of the photos).
PlacePhotoMetadataBuffer photoMetadataBuffer = photos.getPhotoMetadata();
// Get the first photo in the list.
PlacePhotoMetadata photoMetadata = photoMetadataBuffer.get(0);
// Get the attribution text.
CharSequence attribution = photoMetadata.getAttributions();
// Get a full-size bitmap for the photo.
Task<PlacePhotoResponse> photoResponse = mGeoDataClient.getPhoto(photoMetadata);
photoResponse.addOnCompleteListener(new OnCompleteListener<PlacePhotoResponse>() {
#Override
public void onComplete(#NonNull Task<PlacePhotoResponse> task) {
PlacePhotoResponse photo = task.getResult();
Bitmap bitmap = photo.getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
Glide.with(mContext)
.load(stream.toByteArray())
.asBitmap()
.error(R.drawable.cast_album_art_placeholder)
.centerCrop()
.thumbnail(.2f)
.into(holder.placeImage);
}
});
}
});
StackTrace :
E/UncaughtException: java.lang.IllegalStateException
at com.google.android.gms.common.internal.zzbp.zzbg(Unknown Source)
at com.google.android.gms.common.data.zzc.zzbu(Unknown Source)
at com.google.android.gms.common.data.zzc.<init>(Unknown Source)
at com.google.android.gms.location.places.internal.zzav.<init>(Unknown Source)
at com.google.android.gms.location.places.internal.zzar.<init>(Unknown Source)
at com.google.android.gms.location.places.PlacePhotoMetadataBuffer.get(Unknown Source)
Even if thi issues is almost one year old and since the given answer didn't solve my error, I'll share my solution:
// Get the first photo in the list.
if (photoMetadataBuffer.getCount() > 0) {
PlacePhotoMetadata photoMetadata = photoMetadataBuffer.get(0);
// continue with your code
}
This, because the photoMetadataBuffer isn't null.
But yes, the error happens only for places without pictures.
I am fairly certain that the issue is that your application is crashing due to the fact that you are attempting to retrieve a photo from a location that does not have a photo to display. You must do a null check before attempting to retrieve the first photo in your photoMetadataBuffer.get(0). This is a good example of how Google's documentation is somewhat incomplete from the example code that is provided. You should have something like the following:
// Get the first photo in the list.
if (photoMetadataBuffer != null) {
PlacePhotoMetadata photoMetadata = photoMetadataBuffer.get(0);
// continue with your code
}
If the photoMetadataBuffer is null, then there isn't a photo to be displayed and you can handle your application logic appropriately, such as loading a default image, giving feedback to the user, or not displaying the ImageView.
I am learning Android dev. and am developping a Hearthstone app using a Hearthstone API for fun.
My users can search for specific cards and now I wish to implement a Card Displayer that displays cards by their type, and lets the user swipe right or left to display the next one in my JSONArray. My API request gives me one and each JSONObject has an img attribute with the cards image URL.
Therefore, when the user swipes I am doing the following:
// Swipe right -> number - 1 (Previous page)
// Swipe left -> number + 1 (Next page)
public void displayCardNumber(int number) {
APIRequests apiRequests = new APIRequests();
try {
// Gets the JSONObject at 'number' and retrieves its img URL.
JSONObject card = (JSONObject) cardsArray.get(number);
String currentImageURL = (String) card.get("img");
// Here is where my problem is.
Bitmap bitmap = apiRequests.getImageBitmap(currentImageURL);
if (bitmap != null) {
setNewImage(bitmap);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
But apiRequest.getImageBitmap(URL) is where I have a problem.
I must download the image in order to display it, but not only does the following block of code not work when I download more than one image, I must also find an efficient way of displaying my cards (that requires background download perhaps?).
// Returns the image's bitmap using the URL
protected Bitmap getImageBitmap(String currentImageURL) {
try {
Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(currentImageURL).getContent());
return bitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
Why can't I download more than 1 image? Is my way of getting my Bitmap false?
Thank you.
Use Glide https://github.com/bumptech/glide .This is faster.
Bitmap theBitmap = Glide.
with(this).
load(imgUrl). //image url as string
asBitmap().
into(100, 100). // Width and height
get();
You can also use it with another way like this:
Glide.with(context).load(url) // image url
.thumbnail(0.5f)
.crossFade()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(imgId) // If no image found the imgId is the default image id for the imageView
.into(imageView); // imageView to show the image
I have found a solution,
In order to load my image and display it I now use a library called Android Universal Image Loader that lets me do the following:
// Load image, decode it to Bitmap and display Bitmap in ImageView
ImageLoader imageLoader = ImageLoader.getInstance();
ImageView i = (ImageView)view.findViewById(R.id.cardDisplay);
imageLoader.displayImage(currentImageURL, i);
I retrieve the correct URL in my AsyncTask's doInBackground and display it with the library's method.
I've been following the tutorial to create an open graph story here. Everything works nicely, but I'd like the uploaded image to be large i.e. "user generated".
My problem is in actually implementing that. Here's the code that gets the image from the SD card:
// If uploading an image, set up the first batch request
// to do this.
// Set up image upload request parameters
Bundle imageParams = new Bundle();
Bitmap image = BitmapFactory.decodeFile(getActivity().getIntent().getStringExtra("image_for_facebook"));
// Set up the image upload request callback
Request.Callback imageCallback = new Request.Callback() {
#Override
public void onCompleted(Response response) {
// Log any response error
FacebookRequestError error = response.getError();
if (error != null) {
dismissProgressDialog();
Log.i(TAG, error.getErrorMessage());
}
}
};
// Create the request for the image upload
Request imageRequest = Request.newUploadStagingResourceWithImageRequest(Session.getActiveSession(),
image, imageCallback);
// Set the batch name so you can refer to the result
// in the follow-on object creation request
imageRequest.setBatchEntryName("imageUpload");
// Add the request to the batch
requestBatch.add(imageRequest);
And here's the bit which subsequently gives the graph object its properties:
// Set up the OpenGraphObject representing the book.
OpenGraphObject book = OpenGraphObject.Factory.createForPost("books.book");
// Set up the book image; if we uploaded the image, it is the "uri" result from the previous
// batch request, otherwise it is just a URL.
String imageUrl = "{result=imageUpload:$.uri}";
book.setImageUrls(Arrays.asList(imageUrl));
book.setTitle("A Game of Thrones");
book.setUrl("https://facemash.biz/books/a_game_of_thrones/");
book.setDescription("In the frozen wastes to the north of Winterfell, sinister and supernatural forces are mustering.");
// books.book-specific properties go under "data"
book.getData().setProperty("isbn", "0-553-57340-3");
What do I have to do to set the "user_generated" parameter of the image shown here to be true? (Assuming of course that I'm right in thinking that that's all I have to do to get a large image rather than a thumbnail).
Thanks!
Have a look at the Scrumptious sample, in SelectionFragment.java, the getImageObject method. Basically, you need to create a graph object with the "url" and the "user_generated" properties:
GraphObject imageObject = GraphObject.Factory.create();
imageObject.setProperty("url", "{result=imageUpload:$.uri}");
imageObject.setProperty("user_generated", "true");
GraphObjectList<GraphObject> images = GraphObject.Factory.createList(GraphObject.class);
images.add(imageObject);
book.setImage(images);
Ming's answer came very close for me. In order to attach an image to an OpenGraphAction, I had to do the following:
GraphObject imageObject = GraphObject.Factory.create();
imageObject.setProperty("url", imageUrl);
imageObject.setProperty("user_generated", true);
List<JSONObject> images = new ArrayList<JSONObject>();
images.add(imageObject.getInnerJSONObject());
action.setImage(images);
Open Graph Actions have the method setImage(List<JSONObject> images), but I couldn't find a setImage(GraphObjectList<GraphObject>) method. I'm using Facebook SDK v3.6, so that may have changed.
I'm trying to get the profile images of my followers for use within a ListView as thumbnails.
These thumbnails are around 125x125, but the standard twitter4j call of User.getProfileImageURL(); returns much smaller size of 48x48 and is also recommended to not be used as the image source.
I've tried creating a ProfileImage object and supplying it as a parameter, User.getProfileImageURL(profile image object.Original),
But this code takes some time to simply retrieve the url, which when loading a list of thumbnails, is inefficient.
Any suggestions on how to go about this?
Edit
Twitter API v1 has been disabled, so my old answer is no longer valid. Refer to API v1.1, which I believe requires authentication.
If you know the screen name, the twitter api allows for you to fetch the profile image at 4 different resolutions;
https://api.twitter.com/1/users/profile_image?screen_name=Krylez&size=mini
https://api.twitter.com/1/users/profile_image?screen_name=Krylez&size=normal
https://api.twitter.com/1/users/profile_image?screen_name=Krylez&size=bigger
https://api.twitter.com/1/users/profile_image?screen_name=Krylez&size=original
The "bigger" image is 73x73, which is going to interpolate in your 125x125 container. If you're not okay with this, you can try to fetch the "original" photo, but this photo could be very large (slow) and it's not necessarily a square.
Whatever method you choose, make sure you're not fetching and/or decoding Bitmaps on the UI thread. The Android API documentation has excellent guidelines for the correct way to do this.
Also we can make use of the Twitter4j using:
mTwitter.getUserProfileImage();
From the official doc:
You can obtain a user’s most recent profile image from GET users/show. Within the user object, you’ll find the profile_image_url
and profile_image_url_https fields. These fields will contain the
resized “normal” variant of the user’s uploaded image. This “normal”
variant is typically 48x48px.
By modifying the URL, you can retrieve other variant sizings such as
“bigger”, “mini”, and “original”.
Following the code:
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient();
twitterApiClient.getAccountService().verifyCredentials(false, false, new Callback<User>() {
#Override
public void success(Result<User> userResult) {
String name = userResult.data.name;
String email = userResult.data.email;
// _normal (48x48px) | _bigger (73x73px) | _mini (24x24px)
String photoUrlNormalSize = userResult.data.profileImageUrl;
String photoUrlBiggerSize = userResult.data.profileImageUrl.replace("_normal", "_bigger");
String photoUrlMiniSize = userResult.data.profileImageUrl.replace("_normal", "_mini");
String photoUrlOriginalSize = userResult.data.profileImageUrl.replace("_normal", "");
}
#Override
public void failure(TwitterException exc) {
Log.d("TwitterKit", "Verify Credentials Failure", exc);
}
});
For further information refer to Twitter API Documentation | Profile Images and Banners
To create a custom size pic, for example 90x90 you can use the createScaledBitmap() method.
private final int PROFILE_PIC_SIZE = 90;
Bitmap originalPic = null;
Bitmap resizedPic = null;
try {
InputStream in = new java.net.URL(photoUrlOriginalSize).openStream();
originalPic = BitmapFactory.decodeStream(in);
resizedPic = Bitmap.createScaledBitmap(originalPic, PROFILE_PIC_SIZE, PROFILE_PIC_SIZE, false);
} catch (Exception exc) {
Log.e("Error", exc.getMessage());
exc.printStackTrace();
}
You can use getOriginalProfileImageURL() for example. This is as large as it gets.
Smaller ones are getBiggerProfileImageURL() and getProfileImageURL().
These are the urls you retrieve:
http://pbs.twimg.com/profile_images/NUMBER/c62p-cAD_normal.jpeg
http://pbs.twimg.com/profile_images/NUMBER/c62p-cAD_bigger.jpeg
http://pbs.twimg.com/profile_images/NUMBER/c62p-cAD.jpeg