Comment accorder un accès temporaire à un fournisseur de contenu personnalisé à l'aide de FLAG_GRANT_READ_URI_PERMISSION

Je suis en train de requête personnalisés fournisseur de contenu(App) à partir d'une autre application(App B).

Je peux le faire quand il n'y a pas d'autorisation de la protection de fournisseur de contenu. Plus précisément, je build fournisseur de contenu sur App Un et envoyé une intention contenant l'URI d'Application B.
Ici est l'intention-en envoyant une partie en Application A.

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------------------->" + 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);
        }
}

suivie par fichier manifeste de l'Application A.

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:name=".ContentProviderTestActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <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" >
    </provider>
</application>

Puis l'Application B(classe prévue à cet effet) obtenir l'URI de requête et les données correspondantes dans le fournisseur de contenu(à l'aide de code suivant).

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());
       }
    }
}

}

Ici de l'Application du B du fichier manifest.

<uses-permission android:name="android.permission.INTERNET" />
<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:name="._GetWebResoureActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.SEND" >
            </action>
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="*/*" />
        </intent-filter>
    </activity>

    <receiver android:name="StaticReceiver11" >
        <intent-filter>
            <action android:name="android.intent.action.MYSEND" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

    <activity
        android:name="Provid"
        android:label="@string/title_activity_provid" >
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="*/*" />
        </intent-filter>

    </activity>
</application>

Cependant, lorsque j'ai une requête fournisseur de contenu à partir de l'App B, les erreurs se produisent:

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   

Il semble que l'Application B n'a pas fait usage de la temporaire de l'autorisation d'accès. En d'autres mots, comment utiliser FLAG_GRANT_READ_URI_PERMISSION à partir de l'App B?

J'ai aussi essayé d'ajouter directement des Uri de l'intention(à l'aide de setData()), au lieu d'Uri.toString()(à l'aide de putExtra()).

sendIntent.setData(uri2);

et

Uri userNameuri = getIntent().getData(); 

Mais le "userNameuri" a obtenu dans l'Application B est null.

Je suis totalement confus...

mis à jour

J'ai essayé le "grantUriPermission("com.android.getCPaccess", uri2, l'Intention.FLAG_GRANT_READ_URI_PERMISSION)", selon un précédent post

Est-ce la bonne gestion des permissions lors de l'envoi de sensibles les données de l'application en tant que pièce jointe à un courriel?

Et il fonctionne en effet. Il peut fonctionner sans l'aide de FLAG_GRANT_READ_URI_PERMISSION. Mais l'autorisation n'est pas "temporaire". Il faut être terminés manuellement par revokeUriPermission().

Donc, je me demandais si il existe un moyen d'accorder une autorisation temporaire introduite dans FLAG_GRANT_READ_URI_PERMISSION, ou c'est un bug?

Est-il un <uses-permission> pour android.la permission.permRead dans votre application qui implémente le fournisseur & sélecteur de l'activité?
Salut, Jens. J'ai également essayé. Lorsque les deux applications ont <uses-permission android:name="android.la permission.permRead" /> dans le fichier de manifeste, il fonctionne très bien. Mais c'est le genre d'autorisation permanente. Je veux de travail temporaire d'autorisation d'accès avec FLAG_GRANT_READ_URI_PERMISSION(comme décrit par google android developer). Ainsi, l'Application B de ne pas avoir de android.la permission.permRead, au lieu de cela, il reçoit l'intention avec FLAG_GRANT_READ_URI_PERMISSION drapeau "vrai" à partir de l'App A. Mais cela échoue.
Vous devriez seulement besoin d'une uses-permission, a déclaré dans l'application qui déclare que le sélecteur d'activité qui appelle #addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION). Vous devriez probablement inclure plus de votre manifeste, & code en question.
Assurez-vous. J'ai édité la question. Oui, Une Application n'a pas besoin uses-permission. Mais l'Application B ne devrait pas avoir <uses-permission android:name="android.la permission.permRead" />soit, parce que si elle a, il n'y a pas besoin de addFlags(Intention.FLAG_GRANT_READ_URI_PERMISSION).
Non - application, qui définit le fournisseur, doit également définir l'autorisation(s) que vous utilisez pour lire/écrire. aussi déclarer un utilise-l'autorisation pour le lire (& écrire, si vous souhaitez accorder l'autorisation d'écriture aussi) - vous ne pouvez pas accorder une autorisation que vous avez vous-même ne tiennent pas.

OriginalL'auteur Jin | 2012-11-17