6

First thing to mention, answers to the question here do not help.

The source code looks like the following:

Intent intent    = new Intent("com.mycompany.action.PICK_FILE");
String authority = "com.mycompany.fileprovider";
File   file      = Environment.getExternalStorageDirectory();

intent.setData(FileProvider.getUriForFile(this, authority, file));

FileProvider.getUriForFile is throwing the exception and here is the stack trace:

java.lang.StringIndexOutOfBoundsException: length=15; index=16
at java.lang.String.indexAndLength(String.java:500)
at java.lang.String.substring(String.java:1313)
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:687)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:377)

In AndroidManifest.xml inside of application tag I have added the following:

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.mycompany.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true"
            >
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" 
            />
        </provider>

Content of file_paths.xml is the following:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="input_files"  path="." />
    <external-path name="output_files" path="MyAppName/" />
</paths>

output_files path is not used in this context.

I have run debugger through FileProvider.SimplePathStrategy.getUriForFile(). Relevant code snippet is the following (lines 683-688):

            final String rootPath = mostSpecific.getValue().getPath();
            if (rootPath.endsWith("/")) {
                path = path.substring(rootPath.length());
            } else {
                path = path.substring(rootPath.length() + 1);
            }

rootPath is evaluated as /storage/sdcard which is also the exact value of path, so it's not wonder that the exception is thrown.

What am I doing wrong?

UPDATE:

As suggested bellow, passed java.io.File should not be a directory. Docs are ambiguous and never say that explicitly. The workaround would be to create uri 'manually'. Thus

intent.setData(FileProvider.getUriForFile(this, authority, file));

should be replaced with:

intent.setData(Uri.parse("content://" + file.getAbsolutePath()));
Viktor Brešan
  • 5,293
  • 5
  • 33
  • 36
  • 2
    Your `file` isn't a file. It's a directory. You need to pass a `File` object that points to a specific file. – Mike M. Jan 27 '19 at 07:24

1 Answers1

2

Third params to getUriForFile, should be your path to your file with file name. Here is an docs, read it.

Dmytro Ivanov
  • 1,260
  • 1
  • 8
  • 10
  • I have read the docs and it clearly states: "`file` - `File`: A `File` pointing to the filename for which you want a content `Uri`." `java.io.File` can be either directory or file. Docs never say that it shouldn't be a directory. However, that indeed is a problem and I will accept your answer. – Viktor Brešan Jan 29 '19 at 23:41