Je veux pouvoir télécharger un fichier avec une extension particulière à partir du 'net, et le faire passer à mon application pour y faire face, mais je n'ai pas pu comprendre le filtre d'intention. Le type de fichier n'est pas inclus dans les mimetypes, et j'ai essayé d'utiliser
<data Android:path="*.ext" />
mais je ne pouvais pas faire fonctionner cela.
Voici comment j'ai défini mon activité dans mon AndroidManifest.xml pour 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 sur \*/\*
pour correspondre à n'importe quel type de mime.
pathPattern
est l'endroit où vous spécifiez l'extension à laquelle vous souhaitez faire correspondre (dans cet exemple .kdb
). Le .*
au début correspond à n'importe quelle séquence de caractères. Ces chaînes nécessitent un double échappement, 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 une correspondance gourmande comme on pourrait s'y attendre s'il s'agissait d'une expression régulière. Ce modèle ne correspondra pas aux chemins d'accès qui contiennent un .
avant le .kdb
. Pour une discussion plus détaillée de ce problème et une solution de contournement, voir ici
Enfin, selon la documentation Android Android, les attributs Host
et scheme
sont requis pour que l'attribut pathPattern
fonctionne, il suffit donc de définir au caractère générique pour correspondre à quoi que ce soit.
Maintenant, si vous sélectionnez un .kdb
fichier dans une application comme Linda File Manager, mon application apparaît en option. Je dois noter que cela ne permet pas à lui seul de télécharger ce type de fichier dans un navigateur, car cela ne s'inscrit qu'avec le schéma de fichiers. Le fait d'avoir une application comme Linda File Manager sur votre téléphone résiste de manière générique vous permettant de télécharger n'importe quel type de fichier.
Il y a beaucoup de désinformation sur ce sujet, notamment de la propre documentation de Google. Le meilleur, et compte tenu de la logique étrange, peut-être la seule vraie documentation est le code source.
implémentation du filtre d'intention a une logique qui défie presque toute description. Le code de l'analyseur est l'autre pièce pertinente du puzzle.
Les filtres suivants se rapprochent assez d'un comportement sensé. Les modèles de chemin s'appliquent, pour les intentions de schéma de "fichier".
La correspondance de modèle de type mime global correspondra à tous les types tant que l'extension de fichier correspond. Ce n'est pas parfait, mais c'est le seul moyen de faire correspondre le comportement des gestionnaires de fichiers comme ES File Explorer, et il est limité aux intentions où l'URI/l'extension de fichier correspond.
Je n'ai pas inclus d'autres schémas comme "http" ici, mais ils fonctionneront probablement très bien sur tous ces filtres.
Le schéma étrange en sortie est le "contenu", pour lequel l'extension n'est pas disponible pour le filtre. Mais tant que le fournisseur indique votre type MIME (par exemple, Gmail transmettra le type MIME pour la pièce jointe sans entrave), le filtre correspondra.
Gotchas à connaître:
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>
Je dois admettre que la simple tâche d'ouvrir des pièces jointes à partir d'e-mails et de fichiers du système de fichiers sur Android a été l'une des expériences les plus exaspérantes de tous les temps. Il est facile de gérer trop de fichiers ou trop peu. Mais il est difficile de le faire correctement.La plupart des solutions publiées sur stackoverflow ne fonctionnaient pas correctement pour moi.
Mes exigences étaient:
La meilleure façon de procéder consiste probablement à spécifier un type MIME personnalisé pour vos pièces jointes. Et vous choisirez probablement également d'avoir une extension de fichier personnalisée. Supposons donc que notre application s'appelle "Cool App" et que nous générons des pièces jointes contenant ".cool" à la fin.
C'est le plus près de mon objectif et ça marche ... 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>
Remarques:
pathPattern
semble être plus ou moins ignoré pour les pièces jointes (lors de l'utilisation de Android:scheme="content"
). Si quelqu'un obtient le pathPattern pour répondre uniquement à certains modèles, je serais ravi de voir comment.Android:Host="*"
attribut.intent-filter
les blocs sont fusionnés mais je n'ai pas vérifié cela.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 réellement passé, puis resserrez le filtrage pour ne pas devenir cette application ennuyeuse qui gère tout.intent-filter
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 également remarqué que l'icône de l'application n'est pas utilisée pour les fichiers. Encore une fois, si quelqu'un réussit, veuillez commenter ci-dessous.J'espère que vous trouverez cela utile et que vous n'aurez pas à perdre des jours à parcourir toutes les combinaisons possibles. Il y a place à amélioration, les commentaires sont donc les bienvenus.
La réponse de Brian ci-dessus m'a permis d'atteindre 90% du chemin. Pour finir, pour le type mime j'ai utilisé
Android:mimeType="*/*"
Je soupçonne que les affiches précédentes ont tenté de publier le même détail, mais le fait de ne pas citer l'étoile barre oblique comme code, stackoverflow la considère comme une barre oblique.
Plutôt que Android:path
, essayez Android:mimeType
, avec une valeur du type MIME de ce contenu particulier. Également, Android:path
n'accepte pas les caractères génériques - utilisez Android:pathPattern
pour cela.
J'ai essayé de faire fonctionner cela pendant des siècles et j'ai essayé fondamentalement toutes les solutions suggérées et je ne parviens toujours pas à obtenir Android pour reconnaître des extensions de fichier spécifiques. J'ai un filtre d'intention avec un "*/*"
mimetype qui est la seule chose qui semble fonctionner et les navigateurs de fichiers répertorient maintenant mon application comme une option pour ouvrir des fichiers, mais mon application est maintenant affichée comme une option pour ouvrir N'IMPORTE QUEL TYPE de fichier même si j'ai spécifié un fichier spécifique extensions utilisant la balise pathPattern. Cela va si loin que même lorsque j'essaie d'afficher/modifier un contact dans ma liste de contacts Android me demande si je veux utiliser mon application pour afficher le contact, et ce n'est que l'un des nombreux situations où cela se produit, TRÈS TRÈS ennuyeux.
Finalement, j'ai trouvé ce message sur les groupes Google avec une question similaire à laquelle un véritable ingénieur cadre Android a répondu. Elle explique que Android ne sait tout simplement rien sur le fichier- extensions, uniquement les types MIME ( https://groups.google.com/forum/#!topic/Android-developers/a7qsSl3vQq ).
Donc, d'après ce que j'ai vu, essayé et lu, Android ne peut tout simplement pas faire la distinction entre les extensions de fichier et la balise pathPattern est fondamentalement une gigantesque perte de temps et d'énergie. Si vous avez la chance de ne besoin de fichiers d'un certain type MIME (par exemple, texte, vidéo ou audio), vous pouvez utiliser un filtre d'intention avec un type MIME. Si vous avez besoin d'une extension de fichier spécifique ou d'un type MIME inconnu de Android cependant, vous n'avez pas de chance.
Si je me trompe à propos de tout cela, dites-le-moi, jusqu'à présent, j'ai lu tous les messages et essayé toutes les solutions proposées que j'ai pu trouver, mais aucune n'a fonctionné.
Je pourrais écrire une autre page ou deux sur la façon dont ce genre de choses semble être courant dans Android et à quel point l'expérience du développeur est foirée, mais je vais vous éviter mes déclamations en colère;). J'espère que j'ai sauvé quelqu'un des ennuis.
Aucun des éléments ci-dessus ne fonctionne correctement, pour les actions VIEW ou SEND, si le suffixe n'est pas enregistré avec un type MIME dans la base de données MIME system = wide d'Android. Les seuls paramètres que j'ai trouvés qui déclenchent le suffixe spécifié sont Android:mimeType="*/*"
, mais l'action se déclenche pour TOUS les fichiers. Clairement PAS ce que vous voulez!
Je ne peux pas trouver de solution appropriée sans ajouter le mime et le suffixe à la base de données Android mime, jusqu'à présent, je n'ai pas trouvé de moyen de le faire. Si quelqu'un sait, un pointeur serait être formidable.
Le Android 4 les règles sont devenues plus strictes qu'elles ne l'étaient auparavant. Utilisation:
<data
Android:Host=""
Android:mimeType="*/*"
Android:pathPattern=".*\\.ext"
Android:scheme="file"
></data>
J'ai eu beaucoup de mal avec cela pour une extension de fichier personnalisée, moi-même. Après beaucoup de recherches, j'ai trouvé cette page Web où l'affiche a découvert que la classe patternMatcher d'Android (qui est utilisée pour la correspondance pathPattern dans Intent-Filters) a un comportement inattendu lorsque votre chemin contient le premier caractère de votre modèle de correspondance ailleurs dans le chemin (comme si vous essayez de faire correspondre "* .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 fonctionné pour moi, bien que ce soit un peu un hack:
PatternMatcher est utilisé pour pathPattern à IntentFilter Mais, l'algorithme de PatternMatcher est assez étrange pour moi. Voici l'algorithme de Android PatternMatcher.
S'il y a 'caractère suivant' du motif '. *' Au milieu de la chaîne, PatternMatcher arrête la boucle à ce point. (Voir PatternMatcher.Java de Android framework.)
Ex. chaîne: "ceci est un modèle de ma pièce jointe": ". att. ". Android PatternMatcher entrez la boucle pour correspondre au motif '. ' jusqu'à rencontrer le caractère suivant du motif (dans cet exemple, 'a') Donc, '. 'la boucle de correspondance s'arrête à l'index 8 -' un 'entre' est 'et' mon '. Par conséquent, le résultat de cette correspondance renvoie' faux '.
Assez étrange, n'est-ce pas. Pour contourner ce problème - en fait, réduire les possibilités - le développeur devrait utiliser un pathPattern stupide et ennuyeux.
Ex. Objectif: faire correspondre le chemin uri qui inclut le "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 émis lors de la correspondance avec une extension de fichier personnalisée.
La réponse de Brian est très proche, mais voici un moyen propre et sans erreur d'invoquer votre application lorsque vous essayez d'ouvrir un fichier avec votre propre extension personnalisée (pas besoin de schéma ou d'hôte):
<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>
Quand une intention rencontre un intent-filter
, Voici les intent-filter
exigences: (imaginez une liste de contrôle).
<action>
<category>
<data mimeType>
(solution facile: "/")En option:
Toute correspondance <data scheme>
(solution facile: <data Android:scheme="file" /> <data Android:scheme="content" />
)
Toute correspondance <data Host>
(solution facile: "*")
<data pathPattern/etc.>
(par exemple .*\\.0cc
)Définition de plusieurs <data $type="">
elements vérifie la case $ type ssi tout <data $type=>
correspond au Intent
.
Omettre mimeType rompt votre intent-filter
, même si cela semble redondant. Omettre <data scheme/Host/pathPattern>
fait correspondre votre filtre à tout.
https://f-droid.org/en/packages/de.k3b.Android.intentintercept/ est une application conçue pour recevoir tout intentions, et vous permet d'inspecter l'intention. J'ai appris que les extensions de fichiers non reconnues ouvertes via Simple File Manager sont fournies avec le type MIME application/octet-stream
.
https://stackoverflow.com/a/4621284/2683842 signale que <data pathPattern=>
.*xyz
s'interrompt au premier x
qu'il voit et échouera immédiatement s'il n'est pas suivi de yz
. Alors /sdcard/.hidden/foo.0cc
ne passera pas .*\\.0cc
sauf si vous essayez .*\\..*\\.0cc
au lieu.
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>
Utiliser le filtre comme ci-dessous pour ouvrir à partir du navigateur, de Gmail et du navigateur de fichiers (testé). REMARQUE: veuillez ne pas fusionner deux filtres, le navigateur ignorera 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>
Si vous souhaitez que les fichiers soient ouverts directement depuis Gmail, dropbox ou l'un des outils de création de fichiers Android, utilisez le code suivant (supprimez '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 en une seule instruction selon Android version 4.x