My application (using SDK less than 24) can take photos and video using the camera. The photos and videos can be viewed in the gallery outside the app. SDK 24 and above requires FileProvider to create the uri for saving the photo or video to the gallery.
Prior to SDK 24 I would use a uri and an intent to take a photo:
private void openCameraForResult(int requestCode){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
picturesDirectoryPhotoFileName = nextFileName();
File photoFile = makePicturesPhotoFile();
Uri uri = Uri.fromFile(photoFile);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, requestCode);
}
private File makePicturesPhotoFile() {
File photoGallery = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File media = new File(photoGallery, picturesDirectoryPhotoFileName);
return media;
}
Using SDK 24 and higher an exception occurs:
Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/126cfd69-59c6-4534-9b2e-4af9753d3643.jpg exposed beyond app through ClipData.Item.getUri()
I want to achieve the same (without the exception) using FileProvider. The implementation below can take a photo but the it does not appear in the gallery. I want to know what I am doing wrong.
AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="Pictures" path="Pictures"/>
<external-path name="Movies" path="Movies"/>
</paths>
Take a photo:
private void openCameraForResult(int requestCode){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
picturesDirectoryPhotoFileName = nextFileName();
File photoFile = makePicturesPhotoFile();
getDependencyService().getLogger().debug(photoFile.getAbsolutePath());
Uri uri = fileProviderUri.makeUriUsingSdkVersion(photoFile);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, requestCode);
}
Make Uri
private static final String AUTHORITY_FORMAT = "%s.fileprovider";
public Uri makeUriUsingSdkVersion(File file) {
Uri uri;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
uri = Uri.fromFile(file);
} else {
String packageName = getApplicationContext().getPackageName();
String authority = String.format(Locale.getDefault(), AUTHORITY_FORMAT, packageName);
uri = getUriForFile(getApplicationContext(), authority, file);
}
return uri;
}