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é.
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.
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 utilisantandroid: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 leandroid:mimeType
alors expérimentez avecandroid: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.
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:
- 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.
- 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).
- 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é"*/*".
- 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.
- 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.)
- 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>
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.
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.
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>
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>
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é.
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.
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é.
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
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>
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>