Retrieving image from gallery from Picasa // Google + synced folders not working

I'm trying to get an image from the gallery app from one of the folders from Google+ synced photos. After selecting the image, Uri returns back correctly. But when I try to get the actual path of this image on the storage device so that I can use it, it crashes. The problem appears to be with the picasa content provider .

Tested on Nexus S and Nexus 7, as well as on other devices.

 E / AndroidRuntime (14572): java.lang.RuntimeException: Failure delivering result ResultInfo {who = null, request = 1, result = -1, data = Intent {dat = content: //com.google.android.gallery3d.provider / picasa / item / 5427003652908228690}}

Here, the data field seems to pass Uri correctly, but when I try to find the location of the image, it crashes with the following error.

 W / GalleryProvider (14381): unsupported column: _data

The content provider for Picasa albums does not seem to have a _data field.

Code to get location:

 // imageUri is the Uri from above.
 String [] proj = {MediaStore.Images.Media.DATA};
 Cursor cursor = context.getContentResolver (). Query (imageUri, proj, null, null, null);
 int column_index = cursor.getColumnIndexOrThrow (MediaStore.Images.Media.DATA);
 cursor.moveToFirst ();

 String filePath = cursor.getString (column_index);
 cursor.close ();

The only columns that appear to be supported for this image are: [user_account, picasa_id, _display_name, _size, mime_type, datetaken, latitude, longitude, orientation]

How do we get the actual location of this image. And if we should not work with this image, these images should not be displayed to the user in the first place.

Purpose to launch the gallery application:

 Intent intent = new Intent ();
 intent.setType ("image / *");
 intent.setAction (Intent.ACTION_GET_CONTENT);
+58
android android-intent android-contentprovider
Aug 01 2018-12-12T00:
source share
7 answers

After much research, I felt that there were too many workarounds to do something that seemed pretty simple. So, I went ahead, wrote a small library that handles all complex ones if elses and works for all possible scripts that I can think of. Try it and see if that helps.

http://techdroid.kbeanie.com/2013/03/easy-image-chooser-library-for-android.html

This is the initial implementation. Although it handles almost every situation, there may be a few errors. If you use this library, please tell me your feedback and, if at all, can be improved.

+7
Mar 30 '13 at 18:45
source share

I spent many hours and now I have found a solution that works in all cases without any magic loading in special threads or something like that. The following method returns a stream from the content that the user has selected, and this works with everything in the wild.

FileInputStream getSourceStream(Uri u) throws FileNotFoundException { FileInputStream out = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { ParcelFileDescriptor parcelFileDescriptor = mContext.getContentResolver().openFileDescriptor(u, "r"); FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); out = new FileInputStream(fileDescriptor); } else { out = (FileInputStream) mContext.getContentResolver().openInputStream(u); } return out; } 
+14
Jan 13 '14 at 19:34
source share

I ran into the same problem about a year ago. I will show you my solution (the code is rather dirty, please reorganize it). So, you have the URI of the image that was returned from the gallery:

  ImageInfo getImage(URI imageUri) { ImageInfo result = null; final String[] cursorColumns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.ORIENTATION}; // some devices (OS versions return an URI of com.android instead of com.google.android if (imageUri.toString().startsWith("content://com.android.gallery3d.provider")) { // use the com.google provider, not the com.android provider. imageUri = Uri.parse(imageUri.toString().replace("com.android.gallery3d","com.google.android.gallery3d")); } Cursor cursor = App.getContext().getContentResolver().query(imageUri, cursorColumns, null, null, null); if (cursor != null) { int dataColumnIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); int orientationColumnIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION); cursor.moveToFirst(); // if it is a picasa image on newer devices with OS 3.0 and up if (imageUri.toString().startsWith("content://com.google.android.gallery3d")) { result = new ImageInfo(downloadImage(imageUri), "0"); } else { // it is a regular local image file result = new ImageInfo(cursor.getString(dataColumnIndex), cursor.getString(orientationColumnIndex)); } cursor.close(); } else { result = new ImageInfo(downloadImage(imageUri), "0"); } return result; } 

And now we need a function to load the image:

 private String downloadImage(URI imageUri) { File cacheDir; // if the device has an SD card if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),".OCFL311"); } else { // it does not have an SD card cacheDir = App.getContext().getCacheDir(); } if(!cacheDir.exists()) cacheDir.mkdirs(); File f = new File(cacheDir, PUT_HERE_FILE_NAME_TO_STORE_IMAGE); try { InputStream is = null; if (imageUri.toString().startsWith("content://com.google.android.gallery3d")) { is = App.getContext().getContentResolver().openInputStream(imageUri); } else { is = new URL(imageUri.toString()).openStream(); } OutputStream os = new FileOutputStream(f); Utils.InputToOutputStream(is, os); return f.getAbsolutePath(); } catch (Exception ex) { Log.d(this.getClass().getName(), "Exception: " + ex.getMessage()); // something went wrong ex.printStackTrace(); return null; } } 

ImageInfo is my class for storing the path to the image and its orientation.

 public static class ImageInfo { public final String filePath; public final String imageOrientation; public ImageInfo(String filePath, String imageOrientation) { this.filePath = filePath; if (imageOrientation == null) imageOrientation = "0"; this.imageOrientation = imageOrientation; } } 
+5
Dec 30 '12 at 17:17
source share

Based on @drindt's answer below, the codes give the downloaded temporary File path from a Google Photo file that is synchronized but not included in the device.

 @SuppressLint("NewApi") public static String getFilePath(final Context context, final Uri uri) { // Google photo uri example // content://com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2FAF1QipMObgoK_wDY66gu0QkMAi/ORIGINAL/NONE/114919 if ("content".equalsIgnoreCase(uri.getScheme())) { String result = getDataColumn(context, uri, null, null); // if (TextUtils.isEmpty(result)) if (uri.getAuthority().contains("com.google.android")) { try { File localFile = createImageFile(context, null); FileInputStream remoteFile = getSourceStream(context, uri); if(copyToFile(remoteFile, localFile)) result = localFile.getAbsolutePath(); remoteFile.close(); } catch (IOException e) { e.printStackTrace(); } } return result; } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @param selection (Optional) Filter used in the query. * @param selectionArgs (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */ static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = { column }; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { final int column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_index); } } finally { if (cursor != null) cursor.close(); } return null; } /** * Copy data from a source stream to destFile. * Return true if succeed, return false if failed. */ private static boolean copyToFile(InputStream inputStream, File destFile) { if (inputStream == null || destFile == null) return false; try { OutputStream out = new FileOutputStream(destFile); try { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) >= 0) { out.write(buffer, 0, bytesRead); } } finally { out.close(); } return true; } catch (IOException e) { return false; } } public static String getTimestamp() { try { return new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ROOT).format(new Date()); } catch (RuntimeException e) { return new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); } } public static File createImageFile(Context context, String imageFileName) throws IOException { if (TextUtils.isEmpty(imageFileName)) imageFileName = getTimestamp(); // make random filename if you want. final File root; imageFileName = imageFileName; root = context.getExternalCacheDir(); if (root != null && !root.exists()) root.mkdirs(); return new File(root, imageFileName); } public static FileInputStream getSourceStream(Context context, Uri u) throws FileNotFoundException { FileInputStream out = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(u, "r"); FileDescriptor fileDescriptor = null; if (parcelFileDescriptor != null) { fileDescriptor = parcelFileDescriptor.getFileDescriptor(); out = new FileInputStream(fileDescriptor); } } else { out = (FileInputStream) context.getContentResolver().openInputStream(u); } return out; } 
+2
Jun 12 '16 at 3:50
source share

The below trick worked for me, what am I doing here, if there is any authority URL in the URI, then I create a temporary image using the code below and return the URI of the contents of the same.

I also answered a similar question .

 public static String getImageUrlWithAuthority(Context context, Uri uri) { InputStream is = null; if (uri.getAuthority() != null) { try { is = context.getContentResolver().openInputStream(uri); Bitmap bmp = BitmapFactory.decodeStream(is); return writeToTempImageAndGetPathUri(context, bmp).toString(); } catch (FileNotFoundException e) { e.printStackTrace(); }finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } public static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes); String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null); return Uri.parse(path); } 
+1
Sep 30 '15 at 17:17
source share

I used this approach, works great for me, hope this helps you ....

ACTIVITYRESULT_CHOOSEPICTURE is the int that 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(); final InputStream ist = ontext.getContentResolver().openInputStream(intent.getData()); final Bitmap bitmap = BitmapFactory.decodeStream(ist, null, options); ist.close(); } } 

if the above code doesn’t work, than just linking to this link ... this will depressingly show a way

http://dimitar.me/how-to-get-picasa-images-using-the-image-picker-on-android-devices-running-any-os-version/

0
May 14 '14 at 10:47
source share

Finally, the classic solution ended ... Using Document.util, which covers all the permissions: -1-Inside your onActivityResult (): -

 case GALLERY_CAPTURE_IMAGE_REQUEST_CODE: String filePath = DocumentUtils.getPath(MainContainerActivity.this,data.getData(); break; 

2- Create a DocumentUtils class: -

 public class DocumentUtils { @TargetApi(Build.VERSION_CODES.KITKAT) public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } // TODO handle non-primary volumes } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } final String selection = "_id=?"; final String[] selectionArgs = new String[]{split[1]}; return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { // Return the remote address String url; if (isGooglePhotosUri(uri)) { url = getDataColumnWithAuthority(context, uri, null, null); return getDataColumn(context, Uri.parse(url), null, null); } return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @param selection (Optional) Filter used in the query. * @param selectionArgs (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */ public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = {column}; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { final int column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_index); } } finally { if (cursor != null) cursor.close(); } return null; } /** * Function for fixing synced folder image picking bug * * **/ public static String getDataColumnWithAuthority(Context context, Uri uri, String selection, String[] selectionArgs) { Bitmap bitmap = null; InputStream is = null; if (uri.getAuthority()!=null){ try { is = context.getContentResolver().openInputStream(uri); } catch (FileNotFoundException e) { e.printStackTrace(); } Bitmap bmp = BitmapFactory.decodeStream(is); return ImageLoader.getImageUri(context,bmp).toString(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */ public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is Google Photos. */ public static boolean isGooglePhotosUri(Uri uri) { if(uri.getAuthority()!=null) return true; return false; } 

}

3- You will also need the following function in ImageLoader.java: -

 public static Uri getImageUri(Context inContext, Bitmap inImage) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes); String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null); return Uri.parse(path); } 
0
May 26 '15 at 8:41
source share



All Articles