0

I have an image processing app. In my code, I pass my service an ArrayList and the service does the rest. Now I want to extend the functionality of my app and let users be able to go to the gallery, pick one picture and, using the share button, send it to my app to be processed. I want to reuse the most code as possible, so I decided that a good way to go would be converting those URIs returned by the send action to actual file paths. My solution works as expected with QuickPic, but not with Google Photos. My code is as follows:

//MainFragment.onCreateView()
Intent intent = getActivity().getIntent();
if(Intent.ACTION_SEND.equals(intent.getAction()) {
    handleSingleImage(intent);
}

private void handleSingleImage(Intent intent) {
    Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);

    Log.d("MYURISTRING", uri.toString());
    ArrayList<String> selectedPaths = new ArrayList<String>();

    String path = Utils.getRealPathFromURI(getActivity(), uri);

    selectedPaths.add(path);

    Utils.startProcessPhotosService(getActivity(), MainFragment.this, selectedPaths);
}

//Utils
public static String getRealPathFromURI(Context context, Uri contentUri) {
    /*String[] proj = {MediaStore.Images.Media.DATA};

    CursorLoader cursorLoader = new CursorLoader(context, contentUri, proj, null, null, null);
    Cursor cursor = cursorLoader.loadInBackground();

    int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();

    return cursor.getString(columnIndex);*/

    ContentResolver contentResolver = context.getContentResolver();
    Cursor cursor = contentResolver.query(contentUri, null, null, null, null);
    cursor.moveToFirst();

    String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));

    cursor.close();

    return path;
}

If I test this with a photo from QuickPic app, everything works as expected, and the URI on the log is as follows:

content://media/external/images/media/135695

But if I test this with Google Photos, my app crashes, and the URI is as follows:

content://com.google.android.apps.photos.contentprovider/-1/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F135669/ACTUAL

How can I do to support both styles of URI (and, possibly, more than these)? Thank you

Ernestina Juan
  • 957
  • 1
  • 9
  • 24

1 Answers1

1

so I decided that a good way to go would be converting those URIs returned by the send action to actual file paths

That is so not a good way to go.

As I have already pointed out a couple of times today, and dozens upon dozens of times in the past months, a Uri is not a file. You cannot reliably get a local file path for a Uri. There may not even be a local path, let alone one that you can access.

If you wish to use the content represented by the Uri, use getContentResolver().openInputStream(), or things that in turn use it (e.g., Picasso for image loading).

Community
  • 1
  • 1
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • The point is that for my app I need to access EXIF data from the photo, but the ExifInterface class only has a filename constructor – Ernestina Juan Jun 04 '15 at 20:09
  • @ErnestinaJuan: So, use other EXIF-reading code. Heck, Google themselves have no fewer than *three* implementations of EXIF code in Android, with `ExifInterface` being only one. My camera library uses [EXIF code culled from the Mms app](https://github.com/commonsguy/cwac-camera/tree/master/camera/src/com/android/mms/exif). And specifically for the orientation header, the camera app has [yet another EXIF implementation](http://stackoverflow.com/questions/5468098/reading-exif-data-from-byte-array-in-android/13581324#13581324). – CommonsWare Jun 04 '15 at 20:44
  • @CommonsWare i have almost same problem. Im trying to get the actual file path from the Uri so i can put it into a file and upload it. I used `uri.getLastPathSegment()` but no luck. any ideas? – kevoroid Jun 05 '15 at 08:16
  • @omid8bimo: Find code that can upload from an `InputStream`. – CommonsWare Jun 05 '15 at 11:05
  • What EXIF reading code could I use to get EXIF data from a Uri or InputStream? – Ernestina Juan Jun 05 '15 at 15:25
  • @ErnestinaJuan: My camera library uses [EXIF code culled from the Mms app](https://github.com/commonsguy/cwac-camera/tree/master/camera/src/com/android/mms/exif). That EXIF code supports `InputStream` directly, via [the `readExif()` method on `ExifInterface`](https://github.com/commonsguy/cwac-camera/blob/master/camera/src/com/android/mms/exif/ExifInterface.java#L735-L746) (the library's `ExifInterface`, not the Android SDK's `ExifInterface`). – CommonsWare Jun 05 '15 at 15:35
  • I'm going to try it. Thank you! – Ernestina Juan Jun 05 '15 at 16:08