title: How to grant temporary access to custom content provider using FLAG_GRANT_READ_URI_PERMISSION
body: <p>I am trying to query custom content provider(App A) from another app(App B).         </p>
  
  <p>I can do that when there is no permission protection for content provider. Specifically, I build custom content provider on App A and sent an intent containing the URI to App B.
  Here is intent-sending part in App A.        </p>
  
  <pre><code>class InsertOnClickListener implements OnClickListener{        
          public void onClick(View v) {
              ContentValues values = new ContentValues();
              values.put(DataBaseConfiguation.TableConfiguation.USER_NAME, "Jack");
              Uri uri = getContentResolver().insert(DataBaseConfiguation.TableConfiguation.CONTENT_URI, values);
              System.out.println("uri-------------------&gt;" + uri);
              // the uri above should be like "content://com.catking.contentprovider.MyContentProvider/user"
              Uri uri2 = Uri.parse("content://com.catking.contentprovider.MyContentProvider/user");
                Cursor c = managedQuery(uri2, null, null, null, null);
                String sendvalue = null;
                 if (c.moveToFirst()) {
                    do{
                       System.out.println("User name:"+c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString());               
                       sendvalue = c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString();
                    } while (c.moveToNext());
                 }
              Intent sendIntent = new Intent();
              sendIntent.setClassName("com.android.web", "com.android.web.Provid");
              sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
              sendIntent.putExtra("name", uri2.toString());
              sendIntent.setType("text/plain");
              startActivity(sendIntent);
          }
  }
  </code></pre>
  
  <p>followed by manifest file of App A.        </p>
  
  <pre><code>&lt;application
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name" &gt;
      &lt;activity
          android:name=".ContentProviderTestActivity"
          android:label="@string/app_name" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.MAIN" /&gt;
              &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
      &lt;provider android:authorities="com.catking.contentprovider.MyContentProvider"
          android:exported="true"
          android:grantUriPermissions="true"
          android:name="com.catking.contentprovider.MyContentProvider" 
          android:readPermission="android.permission.permRead"
          android:writePermission="android.permission.permWrite" &gt;
      &lt;/provider&gt;
  &lt;/application&gt;
  </code></pre>
  
  <p>Then App B(class Provid) get the URI and query the corresponding data in content provider(using following code).        </p>
  
  <pre><code>public class Provid extends Activity {
  
  public void onCreate(Bundle savedInstanceState) {
      Bundle extras = getIntent().getExtras(); 
      String userNameuri;
      if (extras != null) {
          userNameuri = extras.getString("name");
        Uri allTitles = Uri.parse(userNameuri);
        Cursor c = managedQuery(allTitles, null, null, null, null);
         if (c.moveToFirst()) {
            do{
               System.out.println("Name is"+c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString());               
            } while (c.moveToNext());
         }
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <p>Here's App B's manifest file.</p>
  
  <pre><code>&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
  &lt;application
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name" &gt;
      &lt;activity
          android:name="._GetWebResoureActivity"
          android:label="@string/app_name" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.MAIN" /&gt;
              &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
          &lt;/intent-filter&gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.SEND" &gt;
              &lt;/action&gt;
              &lt;category android:name="android.intent.category.DEFAULT" /&gt;
              &lt;data android:mimeType="*/*" /&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
  
      &lt;receiver android:name="StaticReceiver11" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.MYSEND" /&gt;
              &lt;category android:name="android.intent.category.DEFAULT" /&gt;
          &lt;/intent-filter&gt;
      &lt;/receiver&gt;
  
      &lt;activity
          android:name="Provid"
          android:label="@string/title_activity_provid" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.VIEW" /&gt;
              &lt;category android:name="android.intent.category.DEFAULT" /&gt;
              &lt;data android:mimeType="*/*" /&gt;
          &lt;/intent-filter&gt;
  
      &lt;/activity&gt;
  &lt;/application&gt;
  </code></pre>
  
  <p>However, when I query content provider from App B, errors occur:        </p>
  
  <pre><code>java.lang.RuntimeException: Unable to start activity ComponentInfo {com.android.web/com.android.web.Provid}: java.lang.SecurityException: Permission Denial: opening     provider com.ck.contentprovider.MyContentProvider from ProcessRecord{426c6ea8 17032:com.android.web/u0a95} (pid=17032, uid=10095) requires android.permission.permRead or android.permission.permWrite   
  </code></pre>
  
  <p>It seems that App B did not make use of the temporary permission to access. In other word, how to utilize FLAG_GRANT_READ_URI_PERMISSION from App B?</p>
  
  <p>I have also tried directly adding Uri to intent(using setData()), instead of Uri.toString()(using putExtra()).        </p>
  
  <pre><code>sendIntent.setData(uri2);
  </code></pre>
  
  <p>and        </p>
  
  <pre><code>Uri userNameuri = getIntent().getData(); 
  </code></pre>
  
  <p>But the "userNameuri" got in App B is null.</p>
  
  <p>I am totally confused...</p>
  
  <p><strong>updated</strong>        </p>
  
  <p>I tried "grantUriPermission("com.android.getCPaccess", uri2, Intent.FLAG_GRANT_READ_URI_PERMISSION)" according to a previous post<br>
  <a href="https://stackoverflow.com/questions/4179594/what-is-the-correct-permission-handling-when-sending-sensitive-app-data-as-email">What is the correct permission handling when sending sensitive app data as email attachment?</a>        </p>
  
  <p>And it works indeed. It can work without using FLAG_GRANT_READ_URI_PERMISSION. But the permission is not "temporary". It have to be ended manually by revokeUriPermission().</p>
  
  <p>So, I am wondering if there is a way to grant temporary permission as introduced in FLAG_GRANT_READ_URI_PERMISSION, or it's a bug at all?</p>