This topic has been discussed in lots of questions here, with mostly different results and, due to API changes and different types of URIs, no definitive answer
To expand on alex.dorokhov's answer with some sample code. The support library is a great way to go.
build.gradle
dependencies {
...
compile "com.android.support:exifinterface:25.0.1"
...
}
Example code:
import android.support.media.ExifInterface;
...
try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) {
ExifInterface exif = new ExifInterface(inputStream);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
} catch (IOException e) {
e.printStackTrace();
}
The reason I had to do it this way once we started targeting api 25 (maybe a problem on 24+ also) but still supporting back to api 19, on android 7 our app would crash if I passed in a URI to the camera that was just referencing a file. Hence I had to create a URI to pass to the camera intent like this.
FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileprovider", tempFile);
The issue there is that file its not possible to turn the URI into a real file path (other than holding on to the temp file path).
Getting EXIF from a content URI (an InputStream actually) is now available in the support library. See: https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html
Don't use EXIF. You can get orientation of image from Uri like this:
private static int getOrientation(Context context, Uri photoUri) {
Cursor cursor = context.getContentResolver().query(photoUri,
new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
if (cursor.getCount() != 1) {
cursor.close();
return -1;
}
cursor.moveToFirst();
int orientation = cursor.getInt(0);
cursor.close();
cursor = null;
//orientation here can be 90, 180, 270!
}
The following works with all apps I have tested, in any case:
That will only work if the Uri
happens to be something coming from the MediaStore
. It will fail if the Uri
happens to come from anything else.
The immediate answer is You don’t, you don’t find file paths from content uris in newer version of the OS. It could be said that not all content uris point to pictures or even files.
Correct. I have pointed this out on many occasions, such as here.
How are we supposed to use the ExifInterface class if we should not use paths?
You don't. Use other code to get the EXIF headers.
There might be external libraries that read Exif stuff from a stream, but I’m wondering about the common/platform way to solve this.
Use external libraries.
I have searched for similar code in google’s open source apps, but found nothing.
You will find some in the Mms app.
UPDATE: 2020-01-10: Use ExifInterface
from the AndroidX libraries. It supports using InputStream
to read in the EXIF data, and you can get an InputStream
for content identified by a Uri
by means of a ContentResolver
.