Background
Targeting API 24 or above, instead of using a simple "Uri.fromFile" command, developers need to use FileProvider (or their own ContentProvider), in order to let other apps to access the app's files.
The problem
I try to open a camera app to let it save a file into my app's private storage, using this code:
final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
final File photoFile = FileHelper.generateTempCameraFile(this);
mCameraCachedImageURI = FileProvider.getUriForFile(this, getPackageName()+ ".provider", photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraCachedImageURI);
takePictureIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(takePictureIntent, REQ_CODE_PICK_IMAGE_FROM_CAMERA);
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
manifest file
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
This starts fine, as the camera app is launched, but in the returned result, I fail to get the orientation of the image file using code that previously worked fine:
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
int orientation = getOrientation(this,mCameraCachedImageURI );
...
public static int getOrientation(final Context context, final Uri photoUri) {
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(photoUri,
new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
} catch (final Exception ignored) {
}
if (cursor == null) {
// fallback
return getOrientation(photoUri.getPath());
}
int result = 0;
if (cursor.getCount() > 0) {
cursor.moveToFirst();
result = cursor.getInt(0);
}
cursor.close();
return result;
}
public static int getOrientation(final String filePath) {
if (TextUtils.isEmpty(filePath))
return 0;
try {
final ExifInterface exifInterface = new ExifInterface(filePath);
final int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
return rotate;
} catch (final IOException ignored) {
}
return 0;
}
This will crash, because the cursor doesn't have any columns while running this code.
Not only that, but even the fallback function (when changing the code to use it) doesn't work, as it adds an additional part to the path of the file ("external" in this case).
What I've found
It seems that the contentResolver uses the FileProvider here, instead of what was used on previous versions of Android.
Thing is, I need the ContentProvider of this URI in order to grant the camera app permission to access this file...
The question
How do I get the orientation using the above code (or even a better code), using the new FileProvider Uri ? Maybe I can force the ContentResolver to use the previously ContentProvider to get the needed column's data of the cursor?
Do I really have to create my own ContentProvider here?