Filtro intento Android per una particolare estensione di file?


92

Voglio essere in grado di scaricare un file con una particolare estensione dalla rete e farlo passare alla mia applicazione per gestirlo, ma non sono stato in grado di capire il filtro di intenti. Il tipo di file non è incluso nei mimetypes e ho provato a utilizzare

<data android:path="*.ext" />

ma non sono riuscito a farlo funzionare.

Risposte:


119

Ecco come ho definito la mia attività nel mio AndroidManifest.xml per farlo funzionare.

<activity android:name="com.keepassdroid.PasswordActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="file" />
        <data android:mimeType="*/*" />
        <data android:pathPattern=".*\\.kdb" />
        <data android:host="*" />
    </intent-filter>
</activity>

Il schemeof fileindica che ciò dovrebbe accadere quando viene aperto un file locale (piuttosto che un protocollo come HTTP).

mimeTypepuò essere impostato per \*/\*corrispondere a qualsiasi tipo MIME.

pathPatternè dove specifichi quale estensione vuoi abbinare (in questo esempio .kdb). L' .*inizio corrisponde a qualsiasi quadrato di caratteri. Queste stringhe richiedono un doppio escape, quindi \\\\.corrisponde a un punto letterale. Quindi, si finisce con l'estensione del file. Un avvertimento con pathPattern è che .*non è una corrispondenza avida come ci si aspetterebbe se fosse un'espressione regolare. Questo modello non riuscirà a trovare la corrispondenza dei percorsi che contengono una .prima di .kdb. Per una discussione più dettagliata di questo problema e una soluzione alternativa, vedere qui

Infine, secondo la documentazione di Android, entrambi gli attributi hoste schemesono necessari affinché l' pathPatternattributo funzioni, quindi impostalo sul carattere jolly per far corrispondere qualsiasi cosa.

Ora, se selezioni un .kdbfile in un'app come Linda File Manager, la mia app viene visualizzata come opzione. Dovrei notare che questo da solo non ti consente di scaricare questo tipo di file in un browser, poiché si registra solo con lo schema di file. Avere un'app come Linda File Manager sul tuo telefono si oppone genericamente permettendoti di scaricare qualsiasi tipo di file.


3
Questo non funziona qui. Prima con mimeType = " ", il pacchetto non si installa su Android 2.1, ottengo un'eccezione MalformedMimeTypeException. L'uso di "* / " risolve questo problema, ma poi questo filtro non ha effetto. Attualmente sto testando con il browser Skyfire, che non conserva il tipo di download MIME, come fa il browser Android standard. E quando si fa clic su un file nell'elenco dei download di Skyfire, viene trasmesso un intento VIEW semplicistico con i dati del file. E questo filtro per intenti non corrisponde.
olivierg

@Brian Pellin: stavo effettivamente cercando un modo per associare un tipo MIME .kdbxall'estensione per consentire a ES File Explorer di aprire i file kdbx quando sono stato indirizzato a questo post. Apparentemente se l'intento ha un tipo MIME vuoto, questo filtro dell'intento non funzionerà !! Inoltre, è possibile avere un intento con una stringa EMPTY come azione e solo un URI. Google Docs ha risposto a quell'intento, quindi deve essere valido.
billc.cn

2
Giusto per essere chiari, mimeType dovrebbe essere "* / *" Penso che alcune persone si siano dimenticate di sfuggire ai loro * s
Brian Pellin

1
Non funzionerà con Android 4. Dovresti usare un <data>tag con quattro attributi. Avere 4 tag è logico OPPURE - Che ha funzionato con Android 2 - ma Android 4 è più rigoroso. Vedi stackoverflow.com/questions/20650378/…
Martin

3
se \\\\.corrisponde a un punto letterale, perché non lo usi per formare .kdbun'estensione in questo modo \\\\.kdb:?
Lealo

34

C'è molta disinformazione su questo argomento, non da ultimo dalla documentazione di Google. La migliore, e data la strana logica, forse l'unica vera documentazione è il codice sorgente.

L' implementazione del filtro di intenti ha una logica che sfida quasi la descrizione. Il codice del parser è l'altro pezzo rilevante del puzzle.

I seguenti filtri si avvicinano molto al comportamento ragionevole. I modelli di percorso si applicano agli intenti dello schema "file".

La corrispondenza del modello di tipo MIME globale corrisponderà a tutti i tipi purché l'estensione del file corrisponda. Questo non è perfetto, ma è l'unico modo per abbinare il comportamento di gestori di file come ES File Explorer, ed è limitato agli intenti in cui l'URI / estensione del file corrisponde.

Non ho incluso altri schemi come "http" qui, ma probabilmente funzioneranno bene con tutti questi filtri.

Lo schema strano è "contenuto", per il quale l'estensione non è disponibile per il filtro. Ma fintanto che il provider dichiara il tuo tipo MIME (ad esempio Gmail trasmetterà il tipo MIME per l'allegato senza impedimenti), il filtro corrisponderà.

Trucchi di cui essere a conoscenza:

  1. Tieni presente che nulla si comporta in modo coerente nei filtri, è un labirinto di casi speciali e considera la violazione del principio della minima sorpresa come un obiettivo di progettazione. Nessuno degli algoritmi di pattern matching segue la stessa sintassi o comportamento. L'assenza di un campo a volte è un carattere jolly ea volte no. Gli attributi all'interno di un elemento di dati a volte devono andare insieme e talvolta ignorare il raggruppamento. Avrebbe potuto davvero essere fatto meglio.
  2. Lo schema E l'host devono essere specificati affinché le regole del percorso corrispondano (contrariamente alla guida API di Google, attualmente).
  3. Almeno ES File Explorer genera intenti con un tipo MIME di "", che è filtrato in modo molto diverso da null, è impossibile far corrispondere esplicitamente e può essere trovato solo dal filtro rischioso "* / *".
  4. Il filtro "* / *" NON corrisponderà a Intents con un tipo MIME nullo, che richiede un filtro separato per questo caso specifico senza alcun tipo MIME.
  5. Lo schema "contenuto" può essere trovato solo in base al tipo MIME, perché il nome del file originale non è disponibile nell'intento (almeno con Gmail).
  6. Il raggruppamento di attributi in elementi "dati" separati è (quasi) irrilevante per l'interpretazione, con l'eccezione specifica di host e porta, che si accoppiano insieme. Tutto il resto non ha alcuna associazione specifica all'interno di un elemento "data" o tra elementi "data".

Con tutto questo in mente, ecco un esempio con i commenti:

<!--
     Capture content by MIME type, which is how Gmail broadcasts
     attachment open requests.  pathPattern and file extensions
     are ignored, so the MIME type *MUST* be explicit, otherwise
     we will match absolutely every file opened.
-->
<intent-filter
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:priority="50" >
    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT" />

    <data android:scheme="file" />
    <data android:scheme="content" />
    <data android:mimeType="application/vnd.my-type" />
</intent-filter>

<!--
     Capture file open requests (pathPattern is honoured) where no
     MIME type is provided in the Intent.  An Intent with a null
     MIME type will never be matched by a filter with a set MIME
     type, so we need a second intent-filter if we wish to also
     match files with this extension and a non-null MIME type
     (even if it is non-null but zero length).
-->
<intent-filter
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:priority="50" >
    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT" />

    <data android:scheme="file" />
    <data android:host="*" />

    <!--
         Work around Android's ugly primitive PatternMatcher
         implementation that can't cope with finding a . early in
         the path unless it's explicitly matched.
    -->
    <data android:pathPattern=".*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
</intent-filter>

<!--
     Capture file open requests (pathPattern is honoured) where a
     (possibly blank) MIME type is provided in the Intent.  This
     filter may only be necessary for supporting ES File Explorer,
     which has the probably buggy behaviour of using an Intent
     with a MIME type that is set but zero-length.  It's
     impossible to match such a type except by using a global
     wildcard.
-->
<intent-filter
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:priority="50" >
    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT" />

    <data android:scheme="file" />
    <data android:host="*" />
    <data android:mimeType="*/*" />

    <!--
         Work around Android's ugly primitive PatternMatcher
         implementation that can't cope with finding a . early in
         the path unless it's explicitly matched.
    -->
    <data android:pathPattern=".*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
    <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.my-ext" />
</intent-filter>

È fantastico che tu resisti alle molte evidenti necessità di \\ .. più e più volte e altre stranezze. Google avrebbe dovuto risolverlo entro la 4.2, che diavolo. Ahimè, ho ancora casi che il tuo esempio non sembra risolvere. C'è qualche problema con 6 estensioni cha come ".gblorb" che il mio codice funziona bene con 3 lettere o meno?
RoundSparrow hilltx

La migliore risposta a questa domanda e domande simili secondo me! Purtroppo, fintanto che non è possibile abbinare gli intenti del contenuto in base all'estensione del file (come sottolineato in 5.), non è possibile filtrare in modo affidabile TUTTI gli intenti corretti senza corrispondere anche a quelli sbagliati. Questo è per il caso in cui non è possibile utilizzare un tipo MIME personalizzato. Quindi, finché Android non fornisce una soluzione per questo, per me sarà un selezionatore di file all'interno dell'app ... Non voglio confondere l'utente con un comportamento incoerente.
Benjamin Bisinger,

1
Grazie mille .. Hai appena reso la mia giornata .. Nel mio caso ho dovuto cambiare MimeType come <data android:mimeType="*/*" /> in tutte e tre le opzioni e ha funzionato a meraviglia per tutte le app tra cui Google Drive e Gmail.
Rishabh Wadhwa,

1
Vorrei ringraziarti così tanto, @David Sainty. Hai posto fine alla mia agonia di 24 ore per cercare di capire come gestirla. Ho provato stackoverflow.com/q/18577860/6110285 , stackoverflow.com/a/8599921/6110285 e molti altri simili. Questo è l'unico che ha funzionato.
pittix

24

Devo ammettere che il semplice compito di aprire allegati da e-mail e file dal filesystem su Android è stata una delle esperienze più esasperanti di sempre. È facile gestire troppi file o troppo pochi. Ma farlo bene è difficile. La maggior parte delle soluzioni pubblicate su stackoverflow non ha funzionato correttamente per me.

Le mie esigenze erano:

  • fare in modo che la mia app gestisca gli allegati condivisi dalla mia app
  • fare in modo che la mia app gestisca i file sul file archivio che sono stati generati dalla mia app e hanno un'estensione particolare

Probabilmente il modo migliore per svolgere questa attività è specificare un tipo MIME personalizzato per i tuoi allegati. E probabilmente sceglierai anche di avere un'estensione di file personalizzata. Quindi diciamo che la nostra app si chiama "Cool App" e generiamo file allegati che hanno ".cool" alla fine.

Questo è il massimo che ho ottenuto per il mio obiettivo e funziona ... soddisfacente.

<!-- Register to handle email attachments -->
<!-- WARNING: Do NOT use android:host="*" for these as they will not work properly -->
<intent-filter>
    <!-- needed for properly formatted email messages -->
    <data
        android:scheme="content"
        android:mimeType="application/vnd.coolapp"
        android:pathPattern=".*\\.cool" />
    <!-- needed for mangled email messages -->
    <data
        android:scheme="content"
        android:mimeType="application/coolapp"
        android:pathPattern=".*\\.cool" />
    <!-- needed for mangled email messages -->
    <data
        android:scheme="content"
        android:mimeType="application/octet-stream"
        android:pathPattern=".*\\.cool" />

    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
</intent-filter>

<!-- Register to handle file opening -->
<intent-filter>
    <data android:scheme="file"
          android:mimeType="*/*"
          android:pathPattern=".*\\.cool"
          android:host="*"/>

    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
</intent-filter>

Appunti:

  • L' pathPatternsembra essere più o meno ignorato per gli allegati (quando si utilizza android:scheme="content"). Se qualcuno fa in modo che pathPattern risponda solo a determinati schemi, sarei entusiasta di vedere come.
  • L'app Gmail ha rifiutato di elencare la mia app nel selettore se ho aggiunto l' android:host="*"attributo.
  • Probabilmente funziona ancora se questi intent-filterblocchi vengono uniti, ma non l'ho verificato.
  • Per gestire le richieste da un browser durante il download di un file android:scheme="http"può essere utilizzato. Nota che alcuni browser potrebbero rovinare il sistema, android:mimeTypequindi sperimenta android:mimeType="*/*"e controlla nel debugger ciò che è effettivamente passato e quindi stringi il filtro per non finire per essere quella fastidiosa app che gestisce tutto .
  • Alcuni esploratori di file rovineranno anche i tipi MIME per i tuoi file. Quanto sopra è intent-filterstato testato con l'app "My Files" di Samsung su un Galaxy S3. FX Explorer si rifiuta ancora di aprire correttamente il file e ho anche notato che l'icona dell'app non viene utilizzata per i file. Ancora una volta, se qualcuno riesce a farlo funzionare, commenta di seguito.

Spero che lo troverai utile e che non dovrai sprecare giorni a passare attraverso tutte le combinazioni possibili. C'è spazio per miglioramenti, quindi i commenti sono i benvenuti.


Questa è una soluzione funzionante per me. La registrazione di un <intent-filter> separato per Content-Scheme e File-Scheme ha funzionato! Grazie!
Mehlyfication

Grazie! Ha funzionato per me. Sia l'app Gmail che l'app Samsung My Files su Galaxy S6 sono state in grado di aprire file con la mia app utilizzando la tua soluzione!
Haris

Che cos'è esattamente il "nome dell'app?" (Nel mio caso, il nome dell'app leggibile dall'uomo contiene spazi.)
William Jockusch

@WilliamJockusch sembra che @DavidSainty stia semplicemente memorizzando il nome dell'applicazione nel file di risorse della stringa. Gli spazi dovrebbero andare bene. La stringa utilizzata per il android:labelfiltro per l'intento è la stringa che l'utente vedrà nel menu di scelta. Per impostazione predefinita, viene utilizzato il nome dell'applicazione.
omahena

Cosa devo usare per l'app "Google Drive"?
sviluppatore Android

9

La risposta di Brian sopra mi ha portato al 90% del percorso. Per finire, per il tipo MIME ho usato

android:mimeType="*/*"

Sospetto che i poster precedenti abbiano tentato di pubblicare lo stesso dettaglio, ma senza aver inserito la stella come codice, stackoverflow lo riproduce solo come una barra.


2
Con questo gestirai TUTTI i tipi di file, e questo è davvero fastidioso (beh, a meno che la tua app gestisca davvero tutto) ...
Tim Autin

Questo non va bene. Per favore, non farlo all'interno delle tue app.
Marte

8

Piuttosto che android:pathprovare android:mimeTypecon un valore del tipo MIME di questo particolare contenuto. Inoltre, android:pathnon accetta i caratteri jolly: utilizzare android:pathPatternper quello.


"Il tipo di file non è incluso nei mimetypes"? Dovrebbe esserci ancora un tipo MIME per il tipo di contenuto che stai scaricando, anche se non usa la stessa parola.
Eric Mill,

Esiste un tipo MIME per il tipo di contenuto, ma il file è prodotto da un'applicazione di terze parti che inserisce un'estensione diversa su di esso, quindi non credo che verrà riconosciuto come quel tipo MIME.
Curyous

7

Ho provato a farlo funzionare per anni e ho provato praticamente tutte le soluzioni suggerite e ancora non riesco a far riconoscere ad Android estensioni di file specifiche. Ho un filtro di intenti con un tipo "*/*"MIME che è l'unica cosa che sembra funzionare e i browser di file ora elencano la mia app come un'opzione per l'apertura dei file, tuttavia la mia app viene ora mostrata come un'opzione per aprire QUALSIASI TIPO di file anche se Ho specificato estensioni di file specifiche utilizzando il tag pathPattern. Questo va così lontano che anche quando provo a visualizzare / modificare un contatto nel mio elenco di contatti, Android mi chiede se voglio usare la mia app per visualizzare il contatto, e questa è solo una delle tante situazioni in cui ciò si verifica, MOLTO MOLTO fastidioso.

Alla fine ho trovato questo post di Google Gruppi con una domanda simile a cui ha risposto un vero ingegnere del framework Android. Spiega che Android semplicemente non sa nulla di estensioni di file, solo i tipi MIME ( https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0 ).

Quindi da quello che ho visto, provato e letto, Android semplicemente non riesce a distinguere tra estensioni di file e il tag pathPattern è fondamentalmente una gigantesca perdita di tempo ed energia. Se sei abbastanza fortunato da aver bisogno solo di file di un certo tipo MIME (diciamo testo, video o audio), puoi usare un filtro di intenti con un tipo MIME. Se hai bisogno di un'estensione di file specifica o di un tipo MIME non conosciuto da Android, allora sei sfortunato.

Se mi sbaglio su qualcosa di questo, dimmelo, finora ho letto tutti i post e ho provato tutte le soluzioni proposte che sono riuscito a trovare ma nessuna ha funzionato.

Potrei scrivere un'altra o due pagine su quanto sembrano essere comuni questo tipo di cose in Android e su quanto sia incasinata l'esperienza degli sviluppatori, ma ti risparmierò le mie rabbiose invettive;). Spero di aver salvato qualcuno dei guai.


1
Ti ho votato positivamente perché la tua risposta fornisce un link utile e il downvoter non ha lasciato un commento. Mi dispiace SO può essere ostile in questo modo a volte, ma non smettere.
John Hatton

3

La risposta di Brian è molto vicina, ma ecco un modo pulito e privo di errori per richiamare la tua app quando provi ad aprire un file con la tua estensione personalizzata (senza bisogno di schema o host):

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:mimeType="*/*" />
    <data android:pathPattern="*.*\\.kdb" />
</intent-filter>

2
La documentazione di Android afferma che l'attributo pathPattern è significativo solo se vengono specificati uno schema e un host, e ho verificato questo: developer.android.com/guide/topics/manifest/data-element.html
Brian Pellin,

4
-1; questo corrisponderà a qualsiasi file; Il commento di Brian è corretto e con la piccola modifica di mimeType = " / " il suo esempio originale è perfetto.
Nick

Questo post è di molto tempo fa, ma non "/" non si installa. Hai bisogno di "* / *", che corrisponderà a qualsiasi tipo di file (non sono sicuro, se volevi dire questo). Quindi al tuo programma potrebbe essere chiesto di aprire video o mp3. Non ho ancora trovato una soluzione a questo.
Rene

Dovresti usare un <data>tag con quattro attributi. La tua soluzione potrebbe funzionare con Android 2, ma le regole sono diventate più rigide: stackoverflow.com/questions/20650378/…
Martin

Che succede con lo strano pathPattern ? E hoste schemesono obbligatori!
IgorGanapolsky

3

Su Android 4 le regole sono diventate più rigide di un tempo. Uso:

    <data
      android:host=""
      android:mimeType="*/*"
      android:pathPattern=".*\\.ext"
      android:scheme="file"
    ></data>

3

Ho lottato un po 'con questo per un'estensione di file personalizzata, io stesso. Dopo molte ricerche, ho trovato questa pagina Web in cui il poster ha scoperto che la classe patternMatcher di Android (che viene utilizzata per la corrispondenza pathPattern in Intent-Filters) ha un comportamento inaspettato quando il tuo percorso contiene il primo carattere del tuo modello di corrispondenza altrove nel percorso (come se stai cercando di trovare la corrispondenza con "* .xyz", la classe patternMatcher si interrompe se c'è una "x" all'inizio del percorso). Ecco cosa ha trovato per una soluzione alternativa e ha funzionato per me, anche se è un po 'un trucco:

PatternMatcher viene utilizzato per pathPattern in IntentFilter Ma l'algoritmo di PatternMatcher è piuttosto strano per me. Ecco l'algoritmo di Android PatternMatcher.

Se c'è il "carattere successivo" del pattern ". *" Nel mezzo della stringa, PatternMatcher interrompe il ciclo in quel punto. (Vedi PatternMatcher.java del framework Android.)

Ex. stringa: "questo è un mio allegato" pattern: ". att. ". PatternMatcher Android entra in loop per abbinare '. 'pattern fino a incontrare il carattere successivo del pattern (in questo esempio,' a ') Quindi,'. "il ciclo di corrispondenza si ferma all'indice 8 -" a "tra" è "e" mio ". Pertanto il risultato di questa corrispondenza restituisce "falso".

Piuttosto strano, non è vero. Per ovviare a questo problema - ridurre effettivamente le possibilità - lo sviluppatore dovrebbe utilizzare un fastidioso e stupido pathPattern.

Ex. Obiettivo: percorso uri corrispondente che include "messaggio".

<intent-filter>
...
<data android:pathPattern=".*message.*" />
<data android:pathPattern=".*m.*message.*" />
<data android:pathPattern=".*m.*m.*message.*" />
<data android:pathPattern=".*m.*m.*m.*message.*" />
<data android:pathPattern=".*m.*m.*m.*m.*message.*" />
...
</intent-filter>

Ciò viene emesso in particolare quando si abbina l'estensione di file personalizzata.


Per chiunque sia interessato, un problema è stato registrato su code.google.com
benjamin davis

3

Nessuno dei precedenti funziona correttamente, per le azioni VISUALIZZA o INVIA, se il suffisso non è registrato con un tipo MIME nel sistema di Android = database MIME ampio. Le uniche impostazioni che ho trovato che si attivano per il suffisso specificato includono android:mimeType="*/*", ma poi l'azione si attiva per TUTTI i file. Chiaramente NON quello che vuoi!

Non riesco a trovare alcuna soluzione adeguata senza aggiungere il mime e il suffisso al database mime di Android, finora non ho trovato un modo per farlo. Se qualcuno lo sa, un puntatore sarebbe fantastico.


2

Quando un intento soddisfa un intent-filter, questi sono i intent-filterrequisiti: (immagina una lista di controllo).

  • Qualsiasi corrispondenza <action>
  • Qualsiasi corrispondenza <category>
  • Qualsiasi corrispondenza <data mimeType>(soluzione semplice: " / ")
  • Facoltativamente:

    • Qualsiasi corrispondenza <data scheme>(soluzione semplice: <data android:scheme="file" /> <data android:scheme="content" />)

    • Qualsiasi corrispondenza <data host>(soluzione semplice: "*")

    • Qualsiasi corrispondenza <data pathPattern/etc.>(ad esempio .*\\.0cc)

La definizione di più <data $type="">elementi controlla la casella $ type se ce ne sono <data $type=>corrispondenze Intent.

L'omissione di mimeType interrompe il tuo intent-filter, anche se apparentemente è ridondante. L'omissione <data scheme/host/pathPattern>fa sì che il filtro corrisponda a tutto.

https://f-droid.org/en/packages/de.k3b.android.intentintercept/ è un'app progettata per ricevere tutti gli intenti e ti consente di ispezionare l'intento. Ho appreso che le estensioni di file non riconosciute aperte tramite Simple File Manager vengono fornite con il tipo MIME application/octet-stream.

https://stackoverflow.com/a/4621284/2683842 segnala che si <data pathPattern=> .*xyzinterrompe alla prima visualizzazione xe fallirà immediatamente se non seguito da yz. Quindi /sdcard/.hidden/foo.0ccnon passerà a .*\\.0ccmeno che non provi .*\\..*\\.0ccinvece.

  • Non ho verificato se questa soluzione alternativa è necessaria.

Risultato finale:

<activity android:name=".Ft2NsfActivity">

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="file" />
        <data android:scheme="content" />
        <data android:host="*" />
        <data android:pathPattern=".*\\.ftm"/>
        <data android:pathPattern=".*\\..*\\.ftm"/>
        <data android:pathPattern=".*\\..*\\..*\\.ftm"/>
        <data android:pathPattern=".*\\..*\\..*\\..*\\.ftm"/>
        <data android:pathPattern=".*\\.0cc"/>
        <data android:pathPattern=".*\\..*\\.0cc"/>
        <data android:pathPattern=".*\\..*\\..*\\.0cc"/>
        <data android:pathPattern=".*\\..*\\..*\\..*\\.0cc"/>
        <data android:mimeType="*/*" />
    </intent-filter>

</activity>

1

Se desideri che i file vengano aperti direttamente da Gmail, Dropbox o uno qualsiasi degli strumenti per i file Android incorporati, utilizza il codice seguente (elimina "android: host =" * "" che ha reso il file non raggiungibile per Gmail):

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:scheme="content" android:pathPattern=".*\\.kdb" 
          android:mimeType="application/octet-stream"/>


</intent-filter>

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:scheme="file" android:mimeType="*/*"     
          android:pathPattern=".*\\.kdb"/>
</intent-filter>

Il filtro dati deve essere scritto in un'istruzione come per la versione 4.x di Android


Ho provato di tutto cercando di far funzionare correttamente il download e l'apertura del browser Android. La tua soluzione funziona bene per il browser nativo Android e Chrome Android, tuttavia Firefox sembra ancora aprire il mio file in una finestra di testo. È un tipo MIME personalizzato e un'estensione personalizzata. In precedenza con solo l'estensione, funzionava solo in Firefox. Ora funziona ovunque tranne Firefox (incluso Gmail). Lo sto ancora provando, ma volevo solo segnalare il fatto che qui è presente una nuova serie di problemi con il browser incrociato.
Damon Smith

1

Utilizzando il filtro come di seguito per aprire da browser, gmail e browser di file (testato). NOTA: non unire due filtri, altrimenti il ​​browser ignorerà la tua app (testato).

        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>

            <data android:scheme="file" android:pathPattern=".*\\.ext" android:mimeType="application/*"/>
            <data android:scheme="content" android:pathPattern=".*\\.ext" android:mimeType="application/*"/>
        </intent-filter>

        <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
            <data android:scheme="http"
                  android:host="*"
                  android:pathPattern=".*\\.ext" />
            <data android:scheme="https"
                  android:host="*"
                  android:pathPattern=".*\\.ext" />
            <data android:scheme="ftp"
                  android:host="*"
                  android:pathPattern=".*\\.ext" />

        </intent-filter>

Hai testato questa risposta con gli allegati di Gmail?
IgorGanapolsky

1

Aggiorna 2020

Android è passato agli URI di contenuto e ai tipi MIME per i filtri di intent.

Il problema

Un URI di contenuto non deve necessariamente contenere l'estensione o il nome del file e sarà diverso tra le diverse applicazioni che forniscono il contenuto / file.

Di seguito sono riportati alcuni esempi di URI di contenuto da diverse applicazioni di posta elettronica per lo stesso allegato di posta elettronica:

Gmail -> content://com.google.android.gm.sapi/some_email@gmail.com/message_attachment_external/%23thread-a%3Ar332738858767305663/%23msg-a%3Ar-5439466788231005876/0.1?account_type=com.google&mimeType=application%2Foctet-stream&rendition=1

Outlook -> content://com.microsoft.office.outlook.fileprovider/outlookfile/data/data/com.microsoft.office.outlook/cache/file-download/file--2146063402/filename.customextention

Samsung Email App -> content://com.samsung.android.email.attachmentprovider/1/1/RAW

Come puoi vedere, sono tutti diversi e non è garantito che contengano nulla relativo al tuo file effettivo. Quindi, non puoi usare quello android:pathPatternche molti hanno suggerito.

Una soluzione per aggirare gli allegati di posta elettronica

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>

    <category android:name="android.intent.category.BROWSABLE"/>
    <category android:name="android.intent.category.DEFAULT"/>

    <data android:scheme="content"/>
    <data android:host="*"/>

    <!--  Required for Gmail and Samsung Email App  -->
    <data android:mimeType="application/octet-stream"/>

    <!--  Required for Outlook  -->
    <data android:mimeType="application/my-custom-extension"/>
</intent-filter>

Attraverso i test ho trovato i tipi MIME utilizzati da Gmail, Outlook e Samsung Email e li ho aggiunti al mio filtro di intenti.

Avvertimenti / trucchi

  • Ho scoperto che con la mia soluzione di cui sopra, se avessi aperto un file di tipo binario, avrebbe avviato automaticamente la mia app. L'ho gestito nella mia attività visualizzando uno stato non riuscito se non potevamo analizzare il file. Ho pensato che fosse un evento piuttosto raro, quindi sarebbe stato accettabile.

  • Non sono riuscito a trovare alcun modo per avviare la mia app tramite il browser di file senza aggiungere <data android:mimeType="*/*"/>al mio filtro di intenti. Non potevo usarlo perché avrebbe quindi avviato la mia app ogni volta che l'utente faceva clic su qualsiasi file sul proprio telefono (non solo quelli con estensione file personalizzata). Non consiglierei di aggiungerlo al tuo filtro di intenti.

Pensieri finali

  • Al momento non esiste una soluzione elegante per associare la tua app a un tipo di estensione specifico in Android. Questo è stato il meglio che potevo fare nella mia situazione.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.