title: How to access a file shared by a file manager if my app does not have READ_EXTERNAL_STORAGE
body: <p>I write an Android app that exports some data to a file.</p>
  
  <p>The file is published to the other apps via <code>ACTION_SEND</code> <code>Intent</code> and my custom <code>ContentProvider</code>. It works fine. A file can be attached to an e-mail or sent via <code>Bluetooth</code>.</p>
  
  <p>Now, the other side of the same story is that the app should be able to receive a file to import it. My intention is to let the user select a file in a file manager and select the "Share" option. Now my <code>intent-filter</code> should be activated and my app should access the file.</p>
  
  <p>My app does not have <code>READ_EXTERNAL_STORAGE</code> permission, because generally it does not need to access files in external storage. I do not want to add this permission, I do not to want to frighten users that my app can potentially access their photos and so on.</p>
  
  <p>According to the documentation of the <code>Intent</code> class, if the calling app adds <code>FLAG_GRANT_READ_URI_PERMISSION</code>, it should be enough to let my app read the shared file anyway.</p>
  
  <p>My <code>intent-filter</code>:</p>
  
  <pre><code>&lt;intent-filter&gt;
      &lt;action android:name="android.intent.action.SEND"/&gt;
      &lt;action android:name="android.intent.action.SENDTO"/&gt;
      &lt;action android:name="android.intent.action.SEND_MULTIPLE"/&gt;
      &lt;category android:name="android.intent.category.DEFAULT"/&gt;
      &lt;category android:name="android.intent.category.BROWSABLE"/&gt;
      &lt;data android:mimeType="*/*"/&gt;
  &lt;/intent-filter&gt;
  </code></pre>
  
  <p>My code to process the Intent received through the intent-filter:</p>
  
  <pre><code>Uri uri = null;
  if (uri == null)
  {
      uri = intent.getData();
  }
  if (uri == null)
  {
      if (Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction()))
      {
          uri = (Uri) intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM).get(0);
      }
      else
      {
          uri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
      }
  }
  if (uri != null)
  {
      try
      {
          InputStream stream = getContentResolver().openInputStream(uri);
          stream.read();
          stream.close();
          Toast.makeText(this, "Success " + intent.getAction() + " " + uri.toString(), Toast.LENGTH_LONG).show();
      }
      catch (IOException e)
      {
          Toast.makeText(this, "Error " + intent.getAction() + " " + uri.toString() + " " + e.getMessage(), Toast.LENGTH_LONG).show();
      }
  }
  </code></pre>
  
  <p>This is just a "test" code, so I just try to read anything from the start of the file to check if it works.</p>
  
  <p>The result is:</p>
  
  <ul>
  <li><p>I tried using ES File Explorer and Amaze to "share" files to my app. Usually the received <code>Uri</code> is a file <code>Uri ("file://" scheme)</code> and trying to open this file fails on <code>openInputStream</code> with the information that my app does not have access to the file.</p></li>
  <li><p>When I share the file which is a media file from ES File Explorer for some reason the behavior changes. I receive a <code>"content://" Uri</code> and my app can access the file. Amaze still seems to send <code>"file://" Uri</code> and opening the file fails.</p></li>
  <li><p>I tried to modify the code to get the Uris from <code>ClipData</code> (if available) but it did not change anything.</p></li>
  <li><p>When I try to open an attachment from the built-in <code>MIUI</code> email client, I also receive <code>file:// Uris</code> and the file is not accessible. (to test this I had to use <code>ACTION_VIEW</code> action instead of <code>ACTION_SEND</code>)</p></li>
  </ul>
  
  <p>I also tried the other way. I invoked a file picker from my app using <code>ACTION_GET_CONTENT</code> <code>Intent</code> and wanted to use the returned <code>Uri</code> from my app. The result was even worse, because even <code>"content://" Uris</code> do not work.</p>
  
  <p><strong>So the question is</strong> - is there any way to access the files shared from the popular file managers in a way that allows my app to access the shared file without adding <code>READ_EXTERNAL_STORAGE permission</code>?</p>
  
  <p>I can read in Android docs about <code>FLAG_GRANT_READ_URI_PERMISSION</code> and that <code>file:// Uris</code> are forbidden starting from Android <strong>7.0</strong>, so everything is theoretically prepared to make it working, but in the real world I hit the wall...</p>
  
  <p>I know I can always add <code>READ_EXTERNAL_STORAGE</code> permission to my app or ask the user to manually copy files to my app's external storage directory (path returned by <code>getExternalFilesDir</code>) and then access files there, but both these actions have serious drawbacks (security impact resulting from unnecessary permission or poor user experience).</p>
  
  <p>Is there any other option that I can use to make it working?</p>