0

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?

Nickolay M.
  • 140
  • 3
  • 9
  • See https://stackoverflow.com/questions/40386491/android-geturiforfile-illegalargumentexception – ADM Mar 13 '18 at 15:20
  • `. So I've added this path: . That helped, ` ?? Are you stating that that would let you serve from sd card? From the mentioned path? – greenapps Mar 13 '18 at 15:37
  • I tried this approach without any hope of success, but yes, it does work on Samsung S6 Edge and Nexus 6P. – Nickolay M. Mar 14 '18 at 06:21

1 Answers1

1

FileProvider cannot serve files from removable SD card.

Only from getFilesDir(), getExternalFilesDir() and getExternalStorageDirectory().

You should make your own file provider if you wanna serve files from sd card.

greenapps
  • 11,154
  • 2
  • 16
  • 19