Autore Topic: Intent Filter  (Letto 366 volte)

Offline Ohmnibus

  • Utente senior
  • ****
  • Post: 763
  • Respect: +159
    • Github
    • Google+
    • @ohmnibus
    • Mostra profilo
    • Lords of Knowledge GdR
  • Dispositivo Android:
    Huawei P9 Lite
  • Play Store ID:
    Ohmnibus
  • Sistema operativo:
    Windows 7 x64
Intent Filter
« il: 16 Maggio 2015, 16:39:41 CEST »
0
Salve a tutti,

in una mia app ho intenzione di permettere l'esportazione di dati tramite Intent tramite android.intent.action.SEND.

Dato che un dispositivo può essere sprovvisto di applicazioni in grado di gestire l'intent, ho deciso che la stessa applicazione deve poterlo fare, in modo che nel peggiore dei casi ci sarà l'activity preposta ad esportare i dati - ma nel caso esistano più app l'utente può comunque scegliere.

Vorrei, però, che la mia app gestisca solo le richieste provenienti da essa stessa. In fondo non voglio che la mia app appaia tra i possibili destinatari di un "send" fatto altrove.

Grazie agli attributi "scheme" ed "host" degli intent-filter non dovrebbe essere troppo difficile, ma evidentemente sto sbagliando qualcosa perché l'activity preposta non viene invocata, mentre se fornisco un generico android:mimeType="*/*" funziona - quindi credo sia un problema di configurazione del manifest.

Nel manifest ho questo:
Codice (XML): [Seleziona]
                <activity
                        android:name="ohm.test.IntentReceiver"
                        android:label="@string/intent_receiver_name"
                        android:icon="@drawable/ic_folder" >
                        <intent-filter>
                                <action android:name="android.intent.action.SEND" />
                                <category android:name="android.intent.category.DEFAULT" />
                                <data
                                        android:scheme="content"
                                        android:host="com.example.test"
                                        android:pathPattern=".*"
                                        android:mimeType="*/*" />
                        </intent-filter>
                </activity>

                <!-- Questo è per il FileProvider --> 
                <provider
                        android:name="android.support.v4.content.FileProvider"
                        android:authorities="com.example.test"
                        android:grantUriPermissions="true"
                        android:exported="false">
                        <meta-data
                                android:name="android.support.FILE_PROVIDER_PATHS"
                                android:resource="@xml/filepaths" />
                </provider>

L'intent viene invocato così:
Codice (Java): [Seleziona]
                        File myFile = ...

                        Uri contentUri = FileProvider.getUriForFile(this, "com.example.test", myFile);

                        //contentUri punta a "content://com.example.test/export/testFile.qdr.json"
                       
                        Intent sendIntent = new Intent();
                        sendIntent.setAction(Intent.ACTION_SEND);
                        sendIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
                        sendIntent.setType("application/octet-stream");
                        sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        startActivityForResult(
                                        Intent.createChooser(sendIntent, "Invia file"), SEND);

ma la mia app non appare tra i destinatari.

L'unico modo che ad ora fa apparire la mia app tra i destinatari è specificando solo l'attributo android:mimeType, ma ovviamente in questo modo appare anche nelle send fatte dalle altre app.

Come posso configurare l'intent-filter affinché la mia app accetti solo le richieste "content://com.example.test/*"?

Grazie in anticipo.
Ohmnibus
Le mie app su Play Store

È stata trovata una soluzione al tuo problema? Evidenzia il post più utile premendo . È un ottimo modo per ringraziare chi ti ha aiutato.

Offline Ohmnibus

  • Utente senior
  • ****
  • Post: 763
  • Respect: +159
    • Github
    • Google+
    • @ohmnibus
    • Mostra profilo
    • Lords of Knowledge GdR
  • Dispositivo Android:
    Huawei P9 Lite
  • Play Store ID:
    Ohmnibus
  • Sistema operativo:
    Windows 7 x64
Re:Intent Filter
« Risposta #1 il: 21 Maggio 2015, 10:24:00 CEST »
+1
Ho capito dov'era il problema: gli intent filter non si basano sull'extra Intent.EXTRA_STREAM, ma sull'uri definito in setData(). Per far funzionare il tutto basta cambiare:
Codice (Java): [Seleziona]
sendIntent.setType("application/octet-stream");in
Codice (Java): [Seleziona]
sendIntent.setDataAndType(contentUri, "application/octet-stream");
Tuttavia per risolvere il problema di base (ossia Activity avviata solo se il chiamante è l'app che la contiene) la soluzione migliore consiste nel rimuovere l'intent-filter creare un chooser personalizzato:

Codice (Java): [Seleziona]
        void startChooserForResult(Intent sendIntent, int requestCode) {
                //Ottengo la lista dei pacchetti in grado di gestire l'intent
                List<ResolveInfo> resInfo = this.getPackageManager().queryIntentActivities(sendIntent, 0);
                List<Intent> targetedShareIntents = new ArrayList<Intent>();
                for (ResolveInfo resolveInfo : resInfo) {
                        String packageName = resolveInfo.activityInfo.packageName;

                        //Creo un nuovo intent in base a quello specificato
                        //e specifico ogni singolo pacchetto alla sua risoluzione
                        Intent targetedShareIntent = new Intent(sendIntent);
                        targetedShareIntent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
                       
                        targetedShareIntents.add(targetedShareIntent);

                        //Questa chiamata è necessaria perché
                        //"sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);"
                        //non sempre funziona come deve
                        grantUriPermission(packageName,
                                        (Uri)targetedShareIntent.getParcelableExtra(Intent.EXTRA_STREAM),
                                        Intent.FLAG_GRANT_READ_URI_PERMISSION);
                }
               
                //Aggiungo la mia activity tra quelle che appariranno nel codice
                Intent i = new Intent(this, IntentReceiverActivity.class);
                i.putExtra(Intent.EXTRA_STREAM, sendIntent.getParcelableExtra(Intent.EXTRA_STREAM));
               
                targetedShareIntents.add(i);
               
                //Creo il mio chooser
                Intent chooser = Intent.createChooser(targetedShareIntents.remove(0), "Invia file");

                //Specifico le varie opzioni del chooser
                //(Intent.EXTRA_INITIAL_INTENTS richiede API 5)
                chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
               
                startActivityForResult(chooser, requestCode);
        }
(Fonte: http://stackoverflow.com/a/8550043/466938 )
Ohmnibus
Le mie app su Play Store

È stata trovata una soluzione al tuo problema? Evidenzia il post più utile premendo . È un ottimo modo per ringraziare chi ti ha aiutato.