Filtre d'intention Android pour une extension de fichier particulière?

je veux être en mesure de télécharger un fichier avec une extension particulière à partir du 'net, et avoir passé à mon application pour traiter avec elle, mais je n'ai pas été en mesure de comprendre le filtre d'intention. Le filetype n'est pas inclus dans les mimetypes, et j'ai essayé d'utiliser

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

mais ça n'a pas marché.

83
demandé sur Curyous 2009-11-14 06:55:26

13 réponses

Voici comment j'ai défini mon activité dans mon AndroidManifest.xml pour obtenir que cela fonctionne.

<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>

le scheme de file indique que cela doit se produire lorsqu'un fichier local est ouvert (plutôt qu'un protocole comme HTTP).

mimeType peut être défini à \*/\* pour correspondre à n'importe quel type mime.

pathPattern est l'endroit où vous spécifiez quelle extension vous voulez associer (dans cet exemple .kdb ). Le .* au début correspond à n'importe quel squence de caractères. Ces chaînes nécessitent une double évasion, donc \\. correspond à une période littérale. Ensuite, vous terminez avec votre extension de fichier. Une mise en garde avec pathPattern est que .* n'est pas un match gourmand comme vous vous y attendriez si c'était une expression régulière. Ce modèle ne correspondra pas aux chemins qui contiennent un . avant le .kdb . Pour une discussion plus détaillée de cette question et une solution, voir ici

enfin, selon la documentation Android, à la fois host et scheme attributs sont nécessaires pour l'attribut pathPattern à travailler, donc il suffit de définir à la joker pour correspondre à quoi que ce soit.

maintenant, si vous sélectionnez un fichier .kdb dans une application comme Linda File Manager, mon application apparaît comme une option. Je dois noter que cela seul ne vous permet pas de télécharger ce type de fichier dans un navigateur, puisque ce seul s'enregistre avec le schéma de fichier. Avoir une application comme Linda File Manager sur votre téléphone résiste lui-même généreusement vous permettant de télécharger n'importe quel type de fichier.

112
répondu Brian Pellin 2017-05-23 12:18:07

je dois admettre que la simple tâche d'ouvrir les pièces jointes à partir des e-mails et des fichiers du système de fichiers sur Android a été l'une des expériences les plus exaspérantes jamais. Il est facile de gérer trop de fichiers ou trop peu. Mais le faire juste à droite est dur. La plupart des solutions postées sur stackoverflow ne fonctionnaient pas correctement pour moi.

mes exigences étaient:

  • faites partager les pièces jointes de mon application
  • avoir mon application Gérer les fichiers sur filestorage qui ont été générés par mon application et ont une extension particulière

probablement la meilleure façon d'effectuer cette tâche est de spécifier un type MIME personnalisé pour vos pièces jointes. Et vous choisirez probablement aussi d'avoir une extension de fichier personnalisée. Alors disons que notre application s'appelle "Cool App" et que nous générons des pièces jointes qui ont ".cool" à la fin.

objectif et il fonctionne... satisfaisant.

<!-- 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>

Notes:

  • le pathPattern semble plus ou moins ignoré pour les pièces jointes (en utilisant android:scheme="content" ). Si quelqu'un obtient le patchpattern pour répondre seulement à certains modèles, je serais ravi de voir comment.
  • L'application Gmail a refusé d'inscrire mon application dans le chooser si j'ai ajouté l'attribut android:host="*" .
  • il fonctionne probablement encore si ces blocs intent-filter sont fusionnés mais je n'ai pas vérifié cela.
  • pour traiter les requêtes d'un navigateur lors du téléchargement d'un fichier le android:scheme="http" peut être utilisé. Notez que certains navigateurs peuvent gâcher le android:mimeType alors expérimentez avec android:mimeType="*/*" et vérifiez dans le débogueur ce qui est effectivement passé à travers et ensuite resserrer le filtrage pour ne pas finir par être cette application ennuyeuse qui gère tout .
  • Certains Fichier Les explorateurs détruiront aussi les types MIME pour vos fichiers. Le intent-filter ci-dessus a été testé avec L'application "My Files" de Samsung sur un Galaxy S3. L'Explorateur FX refuse toujours d'ouvrir correctement le fichier et j'ai aussi remarqué que l'icône app n'est pas utilisée pour les fichiers. Encore une fois, si quelqu'un obtient que pour travailler s'il vous plaît commenter ci-dessous.

j'espère que vous trouverez cela utile et que vous n'aurez pas à gaspiller des jours à travers toutes les combinaisons possibles. Il ya de la place pour amélioration afin que les commentaires soient les bienvenus.

21
répondu omahena 2014-10-15 22:12:03

il y a beaucoup de fausses informations sur ce sujet, notamment à partir de la propre documentation de Google. Le meilleur, et étant donné l'étrange logique, probablement la seule vraie documentation est le code source.

le application du filtre d'intention a une logique qui défie presque la description. Le parser code est l'autre pièce pertinente du puzzle.

les filtres suivants sont assez proches de sensible comportement. Les patterns de chemin s'appliquent, pour les intentions du schéma "file".

la correspondance de type mime globale correspondra à tous les types tant que l'extension du fichier correspond. Ce n'est pas parfait, mais c'est la seule façon de faire correspondre le comportement des gestionnaires de fichiers comme ES File Explorer, et c'est limité aux intentions où l'extension URI/file correspond.

Je n'ai pas inclus d'autres schémas comme" http " ici, mais ils fonctionneront probablement très bien sur tous ces filtres.

L'étrange régime est "contenu", pour laquelle l'extension n'est pas disponible pour le filtre. Mais aussi longtemps que le fournisseur indique votre type MIME (par ex. Gmail transmettra le type MIME pour la pièce jointe), le filtre correspondra.

Pièges à connaître:

  1. soyez conscient que rien ne se comporte de manière cohérente dans les filtres, c'est un labyrinthe de cas spécials, et traite la violation du principe de moindre surprise comme un objectif de conception. Aucun motif algorithmes d'appariement de suivre la même syntaxe ou de comportement. Absence d'un champ parfois est un joker et parfois ne l'est pas. Les attributs d'un élément de données doivent parfois aller de pair et parfois ignorer le groupement. Il ne pouvait vraiment pu faire mieux.
  2. le schéma et l'hôte doivent être spécifiés pour que les règles de chemin correspondent (contrairement à L'API guide de Google, actuellement).
  3. au moins ES File Explorer génère les intentions avec un type MIME de "", qui est filtré très différemment à null, est impossible de correspondre explicitement, et ne peut être apparié que par le filtre risqué"*/*".
  4. le filtre "* / * " ne correspond pas aux intentions avec un type MIME nul - qui nécessite un filtre séparé pour ce cas spécifique sans type MIME du tout.
  5. le schéma" content " ne peut être comparé que par type MIME, car le nom du fichier original n'est pas disponible dans l'intention (au moins avec Gmail.)
  6. Le regroupement des attributs distincts "données" éléments est (presque) pas pertinent pour l'interprétation, à l'exception spécifique de l'hôte et de port - qui n'paire ensemble. Tout le reste n'a pas d'association spécifique à l'intérieur d'un élément "données" ou entre des éléments "données".

avec tout cela à l'esprit, voici un exemple avec des commentaires:

<!--
     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>
16
répondu David Sainty 2015-06-24 13:52:02

la réponse de Brian ci-dessus m'a obtenu 90% du chemin. Pour finir, pour mime type I utilisé

android:mimeType="*/*"

je soupçonne que les affiches précédentes ont tenté de poster le même détail, mais le withough qotting de l'étoile slash star comme code, stackoverflow diplays it as just a slash.

10
répondu Dawson 2015-06-01 12:33:43

plutôt que android:path , essayez android:mimeType , avec une valeur du type MIME de ce morceau particulier de contenu. De plus, android:path n'accepte pas les caractères génériques -- utilisez android:pathPattern pour cela.

8
répondu CommonsWare 2009-11-14 11:58:05

la réponse de Brian est très proche, mais voici un moyen propre et sans erreur pour avoir votre application invoquée lorsque vous essayez d'ouvrir un fichier avec votre propre extension personnalisée (pas besoin de scheme ou 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>
3
répondu Kon 2011-07-22 22:25:12

sur Android 4, les règles sont devenues plus strictes qu'avant. Use:

    <data
      android:host=""
      android:mimeType="*/*"
      android:pathPattern=".*\.ext"
      android:scheme="file"
    ></data>
3
répondu Martin 2013-12-18 17:30:48

j'ai été aux prises avec ce assez peu pour une extension de fichier personnalisé, moi-même. Après beaucoup de recherche, j'ai trouvé cette page web où l'affiche a découvert que la classe patternMatcher D'Android (qui est utilisé pour le pathPattern matching dans intention-Filtres) a un comportement inattendu lorsque votre chemin contient le premier caractère de votre modèle de match ailleurs dans le chemin (comme si vous essayez de match "*.xyz", la classe patternMatcher s'arrête s'il y a un " x" plus tôt dans votre chemin). Voici ce qu'il a trouvé pour une solution de contournement, et a travaillé pour moi, bien qu'il soit un peu d'un piratage:

PatternMatcher est utilisé pour pathPattern à IntentFilter mais, L'algorithme de PatternMatcher est assez étrange pour moi. Voici l'algorithme de D'Androïde PatternMatcher.

S'il y a 'next character' of '.* modèle " dans le milieu de la chaîne, PatternMatcher arrête boucle à ce point. (Voir PatternMatcher.java de Android Framework.)

ex. chaîne : "c'est mon attachement" modèle : ". att. ". Android PatternMatcher entre boucle pour correspondre. ' modèle jusqu'à la prochaine rencontre caractère du modèle (dans cet exemple, 'a')'. ' boucle de correspondance s'arrête à l'indice 8 - " a "entre" est " et "mon". Donc pour la suite de cette match retourne 'false'.

Assez étrange, n'est-ce pas. Pour contourner cela-réduire réellement possibilité-développeur devrait utiliser fâcheux pathPattern stupide.

ex. But: correspondance du chemin uri qui inclut 'message'.

<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>

Ceci est spécialement publié lors de la correspondance avec l'extension de fichier personnalisé.

3
répondu benjamin davis 2014-04-25 20:32:31

aucune des actions ci-dessus ne fonctionne correctement, pour affichage ou envoi d'actions, si le suffixe n'est pas enregistré avec un type MIME dans la base de données système=wide MIME D'Android. Les seuls réglages que j'ai trouvé que le feu pour le suffixe spécifié inclut android:mimeType="*/*" , mais ensuite l'action se déclenche pour tous les fichiers. Clairement PAS ce que vous voulez!

Je ne peux trouver aucune solution appropriée sans ajouter le mime et le suffixe à la base de données mime Android, jusqu'à présent, je n'ai pas trouvé un moyen de le faire. Si quelqu'un sait, un pointeur serait formidable.

3
répondu Glenn Widener 2016-09-01 19:17:34

j'ai essayé de faire en sorte que cela fonctionne depuis des lustres et j'ai essayé basicly toutes les solutions suggérées et je ne peux toujours pas obtenir Android pour reconnaître des extensions de fichiers spécifiques. J'ai une intention-filtre avec un "*/*" mimetype qui est la seule chose qui semble fonctionner et les navigateurs fichier-Liste maintenant mon application comme une option pour l'ouverture des fichiers, mais mon application est maintenant montrée comme une option pour l'ouverture de tout type de fichier, même si j'ai spécifié des extensions de fichier spécifiques en utilisant la balise pathPattern. Ce va si loin que même lorsque j'essaie de voir/éditer un contact dans ma liste de contacts Android me demande si je veux utiliser mon application pour voir le contact, et c'est juste l'une des nombreuses situations où cela se produit, très très ennuyeux.

éventuellement, j'ai trouvé ce poste google groups avec une question similaire à laquelle un ingénieur Cadre Android réelle répondu. Elle explique que android ne sait tout simplement rien sur les extensions de fichiers, seulement les types MIME ( https://groups.google.com/forum/#!topic/android-développeurs/a7qsSl3vQq0 ).

donc d'après ce que j'ai vu, essayé et lu, Android ne peut tout simplement pas distinguer entre les extensions de fichier et la balise patchpattern est basicly une gigantesque perte de temps et d'énergie. Si vous avez la chance de n'avoir besoin que de fichiers d'un certain type mime (texte, vidéo ou audio, par exemple), vous pouvez utiliser un filtre intent avec un type mime. Si vous avez besoin d'une extension de fichier spécifique ou d'un type mime non connu par Androïde cependant alors vous n'avez pas de chance.

si je me trompe à propos de tout cela s'il Vous Plaît me dire, jusqu'à présent, j'ai lu tous les billets et essayé toutes les solutions proposées que je pouvais trouver mais aucune n'a fonctionné.

je pourrais écrire une autre page ou deux sur la façon dont commun ce genre de choses semblent être dans Android et comment foutu l'expérience de développeur est, mais je vais vous sauver mes fanfaronnades en colère ;). L'espoir que j'ai sauvé une certaine difficulté.

2
répondu PeeGee85 2017-10-18 19:08:03

si vous voulez que les fichiers soient ouverts directement à partir de Gmail, dropbox ou de l'un des outils de fichier android, puis utiliser le code suivant (supprimer 'android:host="*"' qui a rendu le fichier inaccessible pour 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>

le filtre de données doit être écrit dans une déclaration selon Android version 4.x

1
répondu AndreasReiff 2014-03-18 07:58:27

en utilisant le filtre comme ci-dessous pour ouvrir à partir du navigateur, gmail & le navigateur de fichier (testé). NOTE: S'il vous plaît ne pas fusionner deux filtres, qui feront navigateur ignoré votre application(testé).

        <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>
1
répondu Tran Hieu 2014-05-23 09:59:46

Lorsqu'une intention répond à un intent-filter , ce sont les exigences intent-filter : (imaginez une liste de vérification).

  • toute correspondance <action>
  • Aucune correspondance <category>
  • Aucune correspondance <data mimeType> (easy fix: " / ")
  • facultatif:

    • Aucune correspondance <data scheme> (easy fix: <data android:scheme="file" /> <data android:scheme="content" /> )

    • Aucune correspondance <data host> (easy fix: "*")

    • toute correspondance <data pathPattern/etc.> (par exemple .*\.0cc )

de la Définition des <data $type=""> éléments vérifie la valeur de $type de boîte de iff tout <data $type=> correspond à la Intent .

Omitting mimeType casse votre intent-filter , même si c'est apparemment redondant. Si vous omettez <data scheme/host/pathPattern> , votre filtre correspond à tout.

https://f-droid.org/en/packages/de.k3b.android.intentintercept / est une application conçue pour recevoir tous intentions, et vous permet d'inspecter l'intention. J'ai appris que les extensions de fichiers non reconnues ouvertes via Simple File Manager sont livrées avec le type MIME application/octet-stream .

https://stackoverflow.com/a/4621284/2683842 rapporte que <data pathPattern=> .*xyz avorte à la première x qu'il voit, et échouera immédiatement si elle n'est pas suivie de yz . Donc /sdcard/.hidden/foo.0cc ne passera pas .*\.0cc à moins que vous essayiez .*\..*\.0cc à la place.

  • Je n'ai pas vérifié si cette solution de contournement était nécessaire.

résultat final:

<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>
0
répondu jimbo1qaz 2018-09-18 10:18:56