I'm working on an application where the user is able to select files, either a new image from the camera, an image from the gallery, or a plain old file. It then shows an icon and the name for the selected item. I have this working with one exception. The gallery application integrates picasaweb pictures. If the user selects a picture from a picasa album, I'm not able to get a thumbnail for it.
I'm using the MediaStore.Images.Thumbnails.getThumbnail() method, and it works for other images in the gallery just fine, but for the picasaweb files, I get, regardless of what "kind" of thumbnail I attempt to get (although MICRO is what I'm after):
ERROR/MiniThumbFile(2051): Got exception when reading magic, id =
5634890756050069570, disk full or mount read-only? class
java.lang.IllegalArgumentException
I noticed the URI's given for the selected files are different. The local image files look like:
content://media/external/images/media/6912
and the picasaweb urls look like:
content://com.android.gallery3d.provider/picasa/item/5634890756050069570
I attempted to use a query to get at the raw THUMB_DATA, using Thumbnails.queryMiniThumbnails(), with Thumbnails.THUMB_DATA in the projection array, but I got a "no such column" error.
Is there another method for getting thumbnails that would work better? And will I have the same problem when I try and access the full image data?
What I have found is that on my Galaxy Nexus, the images for Picassa are stored in one of subdirectories under the /sdcard/Android/data/com.google.android.apps.plus/cache directory. When the content provider is com.google.android.gallery3d.provider then the number after "item" in the URL contains the name of the image (in your example above "5634890756050069570"). This data correspondes to a file in one of the subdirectories under /sdcard/Android/data/com.google.android.apps.plus/cache with the extension ".screen". If you were to copy this image from your phone (in your case 5634890756050069570.screen) using DDMS and rename it with the extension ".jpeg" you could open it and view it on your computer.
The following onActivityResult method will check for this content provider being returned, and then will recursively search for the file in the /sdcard/Android/data/com.google.android.apps.plus/cache directory. The private member variable fileSearchPathResults is filled in by the recursive search method walkDirectoryRecursivelySearchingForFile().
private String fileSearchPathResult = null;
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
String filePath = null;
// This code is required to get the image path on content providers
// on API > 10 where the image is from a picassa web album, since Google changed
// the content provider in versions with API > 10
if (selectedImage.toString().contains("com.google.android.gallery3d.provider")) {
StringBuilder contentProviderPath = new StringBuilder(selectedImage.toString());
int beginningIndex = contentProviderPath.lastIndexOf("/");
String fileNameWithoutExt = contentProviderPath.subSequence(beginningIndex + 1,
contentProviderPath.length()).toString();
Log.i(TAG, fileNameWithoutExt);
try {
File path = new File("/sdcard/Android/data/com.google.android.apps.plus/cache");
if (path.exists() && path.isDirectory()) {
fileSearchPathResult = null;
walkDirectoryRecursivelySearchingForFile(fileNameWithoutExt, path);
if (fileSearchPathResult != null) {
filePath = fileSearchPathResult;
}
}
} catch (Exception e) {
Log.i(TAG, "Picassa gallery content provider directory not found.");
}
}
}
public void walkDirectoryRecursivelySearchingForFile(String fileName, File dir) {
String pattern = fileName;
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isDirectory()) {
walkDirectoryRecursivelySearchingForFile(fileName, listFile[i]);
} else {
if (listFile[i].getName().contains(pattern)) {
fileSearchPathResult = listFile[i].getPath();
}
}
}
}
}
With the filePath, you can create a Bitmap of the image with the following code:
Bitmap sourceImageBitmap = BitmapFactory.decodeFile(filePath);
ACTIVITYRESULT_CHOOSEPICTURE is the int you use when calling startActivity(intent, requestCode);
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == ACTIVITYRESULT_CHOOSEPICTURE) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
final InputStream is = context.getContentResolver().openInputStream(intent.getData());
final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
is.close();
}
}
That code will load the whole image. You can adjust the sample size to something reasonable to get a thumbnail sized image.