title: Android: FileProvider.getUriForFile reading MediaStore-generated file?
body: <h1>TL;DR</h1>
  <p>I wanna get(read/generate) file <code>Uri</code> -- with path like below -- by <code>FileProvider</code>, but don't know how:</p>
  <pre><code>val file = File(&quot;/external/file/9359&quot;) // how do I get its Uri then?
  </code></pre>
  <p>All I know was <code>FileProvider.getUriForFile</code> method, but it throws exception.</p>
  <h1>What I was doing</h1>
  <p>I was trying to mock a download progress -- create a file in <code>Download</code> folder, and then pass it to <code>ShareSheet</code> to let user do whatever it want to do.</p>
  <p>What I have done:</p>
  <ol>
  <li>Create file in <code>Download</code> by using <code>MediaStore</code> and <code>ContentResolver</code>.</li>
  <li>Have a <code>ShareSheet</code> util function.</li>
  <li>Registered <code>FileProvider</code> and <code>filepath.xml</code>.</li>
  </ol>
  <p>In my case, I want to share the file via <code>ShareSheet</code> function, which requires</p>
  <ul>
  <li>The Uri of <code>File</code></li>
  </ul>
  <p>but the usual <code>file.toUri()</code> will throw exception above SDK 29. Hence I change it into <code>FileProvider.getUriForFile()</code> as Google-official recommended.</p>
  <h1>The Direct Problem Code</h1>
  <pre><code>val fileUri: Uri = FileProvider.getUriForFile(context, &quot;my.provider&quot;, file)
  </code></pre>
  <p>Will throw exception:</p>
  <pre><code>java.lang.IllegalArgumentException: Failed to find configured root that contains /external/file/9359
  </code></pre>
  <h1>My File Creation Code</h1>
  <pre><code>val fileUri: Uri? = ContentValues().apply {
      put(MediaStore.MediaColumns.DISPLAY_NAME, &quot;test.txt&quot;)
      put(MediaStore.MediaColumns.MIME_TYPE, &quot;text/plain&quot;)
      if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.Q) {
          // create file in download directory.
          put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
      }
  }.let { values -&gt;
      context.contentResolver.insert(MediaStore.Files.getContentUri(&quot;external&quot;), values)
  }
  if (fileUri == null) return
  
  context.contentResolver.openOutputStream(fileUri)?.use { fileOut -&gt;
      fileOut.write(&quot;Hello, World!&quot;.toByteArray())
  }
  
  val file = File(fileUri.path!!) // File(&quot;/external/file/9359&quot;)
  </code></pre>
  <p>I can assure the code is correct because I can see the correct file in <code>Download</code> folder.</p>
  <h1>My FileProvider Setup</h1>
  <p>I have registered provider in AndroidManifest.xml:</p>
  <pre><code>&lt;application&gt;
      &lt;provider
          android:name=&quot;androidx.core.content.FileProvider&quot;
          android:authorities=&quot;my.provider&quot;
          android:exported=&quot;false&quot;
          android:grantUriPermissions=&quot;true&quot;&gt;
          &lt;meta-data
              android:name=&quot;android.support.FILE_PROVIDER_PATHS&quot;
              android:resource=&quot;@xml/filepath&quot; /&gt;
      &lt;/provider&gt;
  &lt;/application&gt;
  </code></pre>
  <p>with filepath.xml below:</p>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;paths&gt;
      &lt;external-path
          name=&quot;external&quot;
          path=&quot;.&quot; /&gt;
  &lt;/paths&gt;
  </code></pre>
  <p>I've also tried so many path variants, one by one:</p>
  <pre><code>&lt;external-files-path name=&quot;download&quot; path=&quot;Download/&quot; /&gt;
  &lt;external-files-path name=&quot;download&quot; path=&quot;.&quot; /&gt;
  &lt;external-path name=&quot;download&quot; path=&quot;Download/&quot; /&gt;
  &lt;external-path name=&quot;download&quot; path=&quot;.&quot; /&gt;
  &lt;external-path name=&quot;external&quot; path=&quot;.&quot; /&gt;
  &lt;external-files-path name=&quot;external_files&quot; path=&quot;.&quot; /&gt;
  </code></pre>
  <p>I also even registered external storage reading permissions:</p>
  <pre><code>&lt;uses-permission android:name=&quot;android.permission.READ_EXTERNAL_STORAGE&quot; /&gt;
  </code></pre>
  <p>which part did I do wrong?</p>
  <h1>Edit 1</h1>
  <p>After posting, I thought the <code>File</code> initialization might be the problem:</p>
  <pre><code>File(fileUri.path!!)
  </code></pre>
  <p>So I changed it to</p>
  <pre><code>File(fileUri.toString())
  </code></pre>
  <p>but still not working.</p>
  <p>Their content difference is below btw:</p>
  <pre><code>fileUri.path       -&gt; /external/file/9359
  (file.path)        -&gt; /external/file/9359
  error              -&gt; /external/file/9359
  
  fileUri.toString() -&gt; content://media/external/file/9359
  (file.path)        -&gt; content:/media/external/file/9359
  error              -&gt; /content:/media/external/file/9359
  </code></pre>
  <h1>Edit 2</h1>
  <p>What I originally wanted to achieve is <a href="https://developer.android.com/training/sharing/send#send-binary-content" rel="nofollow noreferrer">sending binary data to other app</a>. As Official-documented, it seems only accept nothing but file <code>Uri</code>.</p>
  <p>I'd be appreciate if there's any other way to achieve this, like share the <code>File</code> directly, etc.</p>
  <p>But what I'm wondering now is simple -- <strong>How do I make <code>FileProvider</code> available to get/read/generate file <code>Uri</code> like <code>/external/file/9359</code> or so on?</strong> This might comes in help not only this case, and seems like a more general/basic knowledge to me.</p>