title: Custom chooser activity: SecurityException UID n does not have permission to content:// uri
body: <p>I'm building a Chooser app that replaces the native Android Share dialog. It works fine except when I try to share an image from Chrome via longpress image > share image. </p>
  
  <p>I found that Google+ doesn't catch the exception (it crashes) so I can have a look at it via Logcat:</p>
  
  <ul>
  <li>Do an image search on Google.</li>
  <li>Select an image (this should show the preview)</li>
  <li>Longpress the image</li>
  <li>Choose "Share image"</li>
  <li>My chooser activity pops up</li>
  <li>Select Google+</li>
  <li>Google+ crashes with this error:</li>
  </ul>
  
  <blockquote>
    <p>java.lang.SecurityException: UID 10130 does not have permission to content://com.android.chrome.FileProvider/images/screenshot/15307295588677864462883877407218.jpg [user 0]</p>
  </blockquote>
  
  <p>My code (simplified):</p>
  
  <pre><code>@Override
  public void onCreate() {
      handleIntent();
  }
  
  private void handleIntent() {
  
      // Get intent and payload
      mIntent = getIntent();
      mPayloadIntent = (Intent) mIntent.getParcelableExtra(Intent.EXTRA_INTENT);
  
      // Nullify some things for queryIntentActivities (or no results will be found)
      mPayloadIntent.setComponent(null);
      mPayloadIntent.setPackage(null);
  
      // Retrieve a list of targets we can send mPayloadIntent to..
      List&lt;ResolveInfo&gt; targets = context.getPackageManager().queryIntentActivities(mPayloadIntent, 0);
      // etc...
  
  }
  
  private void onClickTarget(ResolveInfo target) {
  
      // Prepare..
      ComponentName compName = new ComponentName(
                  target.activityInfo.applicationInfo.packageName,
                  target.activityInfo.name);
  
      // Build a 'new' shareIntent
      Intent shareIntent = new Intent(mPayloadIntent);
      shareIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
      shareIntent.setComponent(compName);
  
      // Start the targeted activity with the shareIntent
      startActivity(shareIntent);
      finish();
  
  }
  </code></pre>
  
  <p>AndroidManifest.xml:</p>
  
  <pre><code>&lt;activity
      android:name=".ActShareReplace"
      android:label="Sharedr"
      android:theme="@style/AppTheme.TransparentActivity"
      &gt;
      &lt;intent-filter&gt;
          &lt;action android:name="android.intent.action.CHOOSER" /&gt;
          &lt;category android:name="android.intent.category.DEFAULT" /&gt;
      &lt;/intent-filter&gt;
  &lt;/activity&gt;
  </code></pre>
  
  <p>If I look at the documentation for <a href="https://developer.android.com/reference/android/content/Intent.html#ACTION_CHOOSER" rel="nofollow noreferrer">Intent.ACTION_CHOOSER</a> it says:</p>
  
  <blockquote>
    <p>If you need to grant URI permissions through a chooser, you must specify the permissions to be granted on the ACTION_CHOOSER Intent in addition to the EXTRA_INTENT inside. This means using setClipData(ClipData) to specify the URIs to be granted as well as FLAG_GRANT_READ_URI_PERMISSION and/or FLAG_GRANT_WRITE_URI_PERMISSION as appropriate.</p>
  </blockquote>
  
  <p>I'm not completely sure if this is something my app has to do or if it's the responsibility of the app that invoked the chooser activity - but I would assume it's the latter. My app can't set URI permissions for intents it's receiving, can it?</p>
  
  <p>Anyway, if I inspect the extra's and flags on <code>mIntent</code> and <code>mPayloadIntent</code> I get:</p>
  
  <p>mIntent only has extras, no flags (as far as I can tell):</p>
  
  <blockquote>
    <p>android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER
    IntentSender{4fa3901: android.os.BinderProxy@3aec3a6} (android.content.IntentSender)</p>
    
    <p>android.intent.extra.INTENT 
    Intent { act=android.intent.action.SEND typ=image/jpeg flg=0x80001 clip={image/jpeg U:content://com.android.chrome.FileProvider/images/screenshot/15307316967108618905323381238187.jpg} (has extras) } (android.content.Intent)</p>
    
    <p>android.intent.extra.TITLE
    Share via (java.lang.String)</p>
  </blockquote>
  
  <p>mPayloadIntent:</p>
  
  <blockquote>
    <p>android.intent.extra.STREAM 
    content://com.android.chrome.FileProvider/images/screenshot/1530731945132897653908815339041.jpg (android.net.Uri$HierarchicalUri)</p>
  </blockquote>
  
  <ul>
  <li>FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET</li>
  <li>FLAG_ACTIVITY_NEW_DOCUMENT</li>
  <li>FLAG_GRANT_READ_URI_PERMISSION</li>
  </ul>
  
  <p>So <code>mPayloadIntent</code> <em>does</em> have the <code>FLAG_GRANT_READ_URI_PERMISSION</code> but mIntent <em>does not</em>. According to the docs it should.</p>
  
  <p>I've read that it's possible that my app consumed the URI permission so <a href="https://stackoverflow.com/questions/51174627/securityexception-permission-denial-opening-provider-org-chromium-chrome-brows">I tried caching the file myself</a> but as soon as I try to access the URI through a ContentResolver, I get a - you guessed it - permission error.</p>
  
  <p>I then realized that I probably shouldn't have to cache the file as Android's native <a href="https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/app/ChooserActivity.java" rel="nofollow noreferrer">Chooser Activity</a> doesn't seem to do that either. So that's where I'm at now. Back to square one.</p>
  
  <p>Is this a Chrome bug? An Android bug? Or am I doing something wrong?</p>
  
  <p>I'd happily blame Chrome and file a bug report but someone who's working on a similar project (and ran into the same issue) told me Whatsapp has a similar problem. It, too, shares images via a content:// uri.</p>
  
  <p>For completeness, I'm testing this on a Pixel 2016 with Android 8.1. I have no idea what the other guy (who ran into the same issue with WA) is using.</p>