简体   繁体   中英

Retrieve a non cached Picasa image from Gallery. 3.0 and 4.0

My app is calling the gallery with an intent that looks like this:

Intent intent = new Intent(Intent.ACTION_PICK,
        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, SELECT_IMAGE_FROM_GALLERY);

In versions < 3.0 there's no problem.

With 3.0 and greater versions, when you get a local image, the intent in the onActivityResult method contains an Uri like...

content://media/external/images/media/XXX

but when you select a picasa image the uri is something like...

content://com.google.android.gallery3d.provider/picasa/item/XXXXXXXXXXXXXXXXXXXXX

I read many about that problem and I tried many workarounds.

At the moment, I can obtain just cached images using:

getContentprovider().openInputStream(uri)

The problem is that, when the image is not cached, the openInputStream(uri) method, throws a FileNotFoundException , and i can't get the image :_(

Anyone knows how to get the file or the url to download the file or something to get the image??

Thanks!!

The correct solution is to use ACTION_GET_CONTENT . Its name may not sound as intuitive as ACTION_PICK but it's the one you should use for what you are trying to do.

The reason behind using ACTION_GET_CONTENT for picking an image in your gallery instead of using ACTION_PICK and pointing to the ImageStore's URI provider is that ACTION_GET_CONTENT is well supported , whereas ACTION_PICK is not . It's been mentioned a couple of times by Android Framework engineers.

I learned it the hard way. Before finding out about this I had to deal with various inconsistencies.


A note related to this

You should always use openInputStream to obtain the file through a ContentResolver with the URI received instead of trying to obtain the real path in which the file is being stored. It may well be the case that the ContentProvider implementation is backed by a cloud service (this is the case with Picasa) or the implementation details change over time.

Android's content providers let you abstract how the data is being accessed. Trying to find out where the file is located is a common error I see. Usually what is suggested is to find the location by querying the DATA column of the given URI . Depending on the ContentProvider used it may return different things and even change over time with new versions.

By using openInputStream you don't have to care about where the file is, you just receive the stream of bytes and do what you wish with it. This way you won't have problems supporting content providers from other apps like Google Drive, Dropbox, etc that provide a similar picker interface to select an image.

I know OP is using openInputStream , but other answers are suggesting otherwise and it's something I see too frequently.

Another way to get the bitstream for the picture is thru the picasa api....

applying some mapping to content provider uri ...

content://com.google.android.gallery3d.provider/picasa/item/5703943700733980450

one can map it to a picasa api like the following:

item=>photoid name?? albumid??

picasaweb.google.com/data/entry/api/user/$NAME/albumid/nnnn/photoid/nnnn

Above is an api request for photo entry - see picasa docs for details.

API requires

Name albumID photoID

Name i think u can get from the account on the phone. AlbumID is tricky because the /item/ node value in the content provider is not a GUID that can use a relationship to infer the album that its in. I don't think.. AFAIK in picasa , you need the user,album,photo tuple to get a reference to a photo entry and the photo entry has the URL for the large photo in the API element:

"media$group":{ "media$content":[ {"url":

You can take the textvalue of the url attribute and request it using http(s) if the visibility of the album is public. The response is the binary stream of the JPG.

php picasa api show large image

see the accepted answer in the above link for more details on getting the image that you want from the picasa api.

Using one of my own content URI's in an example...

content://com.google.android.gallery3d.provider/picasa/item/5703943700733980450

is not available in cache so how to get the image?

well the name on the account is 'rowntreerob' and i know that photoid 5703943700733980450 belongs to albumid 5703943611411433905.

So, i make an api request for the entry

https://picasaweb.google.com//data/entry/api/user/rowntreerob/albumid/5682316071017984417/photoid/5682316083381958690?fields=media%3Agroup%2Fmedia%3Athumbnail%5B%40url%5D%2Cmedia%3Agroup%2Fmedia%3Acontent%5B%40url%5D&alt=json

and check the response for the text value of

"media$group":{ "media$content":[ {"url":

value= https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/DSC01612.JPG

I make a photo image request using the value above and i have the image.


The Gallery 3D app also has the code you could fork because whereever it detects a 'touch' on one of the list of thumbnails, it delegates to the contentProvider interface to 'get' the BMP. I believe that this interface encapsulates all the gory implementation nits mentioned above. By asking the ContentProvider to produce the BMP, the developer doesnt have to worry about the flavor of implementation?? On the thumbtouch, Gallery3d may just ask the provider to return the BMP and its the provider instance that is responsible for resolving the various states of the cache and whether network calls will be required to return the BMP.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM