My app is providing the functionality to share files between users. For image files there is a custom gallery, and by long clicking, it opens images in local Image Viewer via ACTION_VIEW intent. Here is the code:
public static boolean openFile(Context context, File file)
{
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
String extension = FilenameUtils.getExtension(file.getPath());
String mimeType = mimeTypeMap.getMimeTypeFromExtension(extension.toLowerCase());
Intent openFile = new Intent(Intent.ACTION_VIEW);
openFile.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|Intent.FLAG_ACTIVITY_NO_HISTORY
|Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri fileUri;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
String authority = context.getApplicationContext().getPackageName() + ".provider";
try {
fileUri = FileProvider.getUriForFile(context, authority, file);
} catch (IllegalArgumentException e) {
if (Fabric.isInitialized()) Crashlytics.logException(e);
else e.printStackTrace();
return false;
}
}
else fileUri = Uri.fromFile(file);
openFile.setDataAndType(fileUri, mimeType != null ? mimeType : "*/*");
if (openFile.resolveActivity(context.getPackageManager()) != null)
{
context.startActivity(openFile);
return true;
}
return false;
}
All works fine on API < 24, but on 24+ I've faced an issue trying to open image on sdcard. The exception is:
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/89F3-1B06/Pictures/DSC_0004.JPG
W/System.err: at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:719)
W/System.err: at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:404)
Apparently, this is due to the fact that <external-path name="other" path="."/>
doesn't provide access on the level of sdcard in the file tree. So I've added this path:
<external-path name="external_files" path="../../"/>
. That helped, but something tells me, that it's not the best solution.
I've found another solution, which works too:
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
fileUri = Uri.fromFile(file);
But disabling StrictMode restrictions looks even worse. So it's not on option.
Any suggestion on how to solve this issue the right way?