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


92

Je veux pouvoir télécharger un fichier avec une extension particulière à partir du 'net, et le faire passer à mon application pour le traiter, mais je n'ai pas été en mesure de comprendre le filtre d'intention. Le type de fichier n'est pas inclus dans les types MIME, et j'ai essayé d'utiliser

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

mais je ne pouvais pas faire fonctionner ça.

Réponses:


119

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 schemeof fileindique que cela devrait se produire lorsqu'un fichier local est ouvert (plutôt qu'un protocole comme HTTP).

mimeTypepeut être défini sur \*/\*pour correspondre à n'importe quel type de mime.

pathPatternest l'endroit où vous spécifiez l'extension à associer (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 à un point littéral. Ensuite, vous terminez avec votre extension de fichier. Une mise en garde avec pathPattern est qu'il .*ne s'agit pas d'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 contenant un .avant le .kdb. Pour une discussion plus détaillée de ce problème et une solution de contournement, cliquez ici

Enfin, selon la documentation Android, les attributs hostet les deux schemesont nécessaires pour que l' pathPatternattribut fonctionne, il suffit donc de le définir sur le caractère générique pour qu'il corresponde à tout.

Maintenant, si vous sélectionnez un .kdbfichier dans une application telle que 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, car cela ne s'enregistre qu'avec le schéma de fichier. 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.


3
Cela ne fonctionne pas ici. D'abord avec mimeType = " ", le package ne s'installe pas sur Android 2.1, j'obtiens une MalformedMimeTypeException. L'utilisation de "* / " corrige ce problème, mais alors, ce filtre n'a aucun effet. Je teste actuellement avec le navigateur Skyfire, qui ne conserve pas le type de téléchargement mime, comme le fait le navigateur Android standard. Et lorsque vous cliquez sur un fichier dans la liste des téléchargements Skyfire, une intention VIEW simpliste est diffusée avec les données du fichier. Et ce filtre d'intention ne correspond pas.
olivierg

@Brian Pellin: Je cherchais en fait un moyen de lier un type mime à l' .kdbxextension pour permettre à l'explorateur de fichiers ES d'ouvrir les fichiers kdbx lorsque j'ai été pointé vers ce message. Apparemment, si l'intention a un type MIME vide, ce filtre d'intention ne fonctionnera pas !! De plus, il est possible d'avoir une intention avec une chaîne VIDE comme action et juste un URI. Google Docs a répondu à cette intention, il doit donc être valide.
billc.cn

2
Juste pour être clair, mimeType devrait être "* / *" Je pense que certaines personnes ont oublié d'échapper à leurs * s
Brian Pellin

1
Cela ne fonctionnera pas avec Android 4. Vous devez utiliser une <data>balise avec quatre attributs. Avoir 4 balises est logique OU - qui fonctionnait avec Android 2 - mais Android 4 est plus strict. Voir stackoverflow.com/questions/20650378/…
Martin

3
si \\\\.correspond à un point littéral, pourquoi ne l'utilisez-vous pas pour former une .kdbextension comme celle-ci \\\\.kdb:?
Lealo

34

Il y a beaucoup de désinformation sur ce sujet, notamment de la propre documentation de Google. Le meilleur, et étant donné la logique étrange, la seule vraie documentation est peut-être le code source.

L' 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 sont assez proches du comportement raisonnable. 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 est "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.

Il faut être conscient de:

  1. Sachez que rien ne se comporte de manière cohérente dans les filtres, c'est un labyrinthe de cas particuliers et traite la violation du principe de moindre surprise comme un objectif de conception. Aucun des algorithmes de correspondance de modèles ne suit la même syntaxe ou le même comportement. L'absence d'un champ est parfois un joker et parfois non. Les attributs d'un élément de données doivent parfois aller ensemble et parfois ignorer le regroupement. Cela aurait vraiment pu être mieux fait.
  2. Le schéma ET l'hôte doivent être spécifiés pour que les règles de chemin correspondent (contrairement au guide API de Google, actuellement).
  3. Au moins ES File Explorer génère des intentions avec un type MIME de "", qui est filtré très différemment à null, il est impossible de faire correspondre explicitement et ne peut être mis en correspondance que par le filtre risqué "* / *".
  4. Le filtre «* / *» ne correspondra PAS aux intentions avec un type MIME nul - qui nécessite un filtre séparé pour ce cas spécifique sans aucun type MIME.
  5. Le schéma "contenu" ne peut être mis en correspondance que par type MIME, car le nom de fichier d'origine n'est pas disponible dans l'intention (au moins avec Gmail).
  6. Le regroupement des attributs dans des éléments de "données" séparés est (presque) sans rapport avec l'interprétation, à l'exception spécifique de l'hôte et du port - qui se couplent. Tout le reste n'a pas d'association spécifique dans un élément "data" ou entre des éléments "data".

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>

C'est formidable que vous résistiez aux nombreux besoins manifestés pour \\ .. maintes et maintes fois et autres bizarreries. Google aurait dû corriger cela par 4.2, qu'est-ce que c'est. Hélas, j'ai encore des cas que votre exemple ne semble pas résoudre. Y a-t-il un problème avec 6 extensions cha comme ".gblorb" que mon code fonctionne correctement avec 3 lettres ou moins?
RoundSparrow hilltx

Meilleure réponse à cette question et questions similaires à mon avis! Malheureusement, tant qu'il n'est pas possible de faire correspondre les intentions de contenu par extension de fichier (comme vous le faites remarquer au point 5.), il n'est pas possible de filtrer de manière fiable TOUTES les intentions correctes sans également faire correspondre les mauvaises. C'est dans le cas où vous ne pouvez pas utiliser un type mime personnalisé. Donc, tant qu'Android ne fournit pas de solution pour cela, ce sera pour moi un sélecteur de fichiers dans l'application ... Je ne veux pas confondre l'utilisateur avec un comportement incohérent.
Benjamin Bisinger

1
Merci beaucoup .. Vous venez de faire ma journée .. Dans mon cas, j'ai dû changer MimeType comme <data android:mimeType="*/*" /> dans les trois options et cela a fonctionné comme un charme pour toutes les applications, y compris Google Drive et Gmail.
Rishabh Wadhwa

1
J'aimerais beaucoup vous remercier, @David Sainty. Vous avez mis fin à mon agonie de 24h d'essayer de comprendre comment y faire face. J'ai essayé stackoverflow.com/q/18577860/6110285 , stackoverflow.com/a/8599921/6110285 et bien d'autres similaires. Celui-ci est le seul qui a fonctionné.
pittix le

24

Je dois admettre que la simple tâche d'ouvrir les pièces jointes 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 vues. Il est facile de gérer trop ou trop peu de fichiers. Mais il est difficile de bien faire les choses. La plupart des solutions publiées sur stackoverflow ne fonctionnaient pas correctement pour moi.

Mes exigences étaient:

  • faire en sorte que mon application gère les pièces jointes partagées par mon application
  • faire en sorte que mon application gère les fichiers sur le stockage de fichiers qui ont été générés par mon application et qui ont une extension particulière

La meilleure façon d'accomplir cette tâche est probablement de spécifier un type MIME personnalisé pour vos pièces jointes. Et vous choisirez probablement également 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.

C'est le plus proche de mon objectif et cela 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>

Remarques:

  • Le pathPatternsemble être plus ou moins ignoré pour les pièces jointes (lors de l'utilisation android:scheme="content"). Si quelqu'un obtient le pathPattern pour ne répondre qu'à certains modèles, je serais ravi de voir comment.
  • L'application Gmail a refusé de répertorier mon application dans le sélecteur si j'ai ajouté l' android:host="*"attribut.
  • Cela fonctionne probablement toujours si ces intent-filterblocs sont fusionnés mais je ne l'ai pas vérifié.
  • Pour gérer les demandes 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 l' android:mimeTypeexpérience android:mimeType="*/*"et vérifier dans le débogueur ce qui est réellement passé, puis resserrer le filtrage pour ne pas devenir cette application ennuyeuse qui gère tout .
  • Certains explorateurs de fichiers vont également gâcher les types MIME pour vos fichiers. Ce qui précède a intent-filterété testé avec l'application "Mes fichiers" 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 obtient que cela fonctionne, 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 à l'amélioration, donc les commentaires sont les bienvenus.


C'est une solution de travail pour moi. L'enregistrement d'un <intent-filter> séparé pour Content-Scheme et File-Scheme a fait l'affaire! Merci!
Mehlyfication

Merci! A travaillé pour moi. L'application Gmail et l'application Samsung My Files sur Galaxy S6 ont pu ouvrir le fichier avec mon application en utilisant votre solution!
Haris

Quel est exactement le "nom de l'application"? (Dans mon cas, le nom de l'application lisible par l'homme contient des espaces.)
William Jockusch

@WilliamJockusch il semble que @DavidSainty stocke simplement le nom de l'application dans le fichier de ressources de chaîne. Les espaces devraient être bien. La chaîne utilisée pour le android:labelfiltre d'intention est la chaîne que l'utilisateur verra dans le menu de sélection. Par défaut, le nom de l'application est utilisé.
omahena

Que dois-je utiliser pour l'application "Google Drive"?
développeur android

9

La réponse de Brian ci-dessus m'a conduit à 90% du chemin. Pour finir, pour le type de mime que j'ai utilisé

android:mimeType="*/*"

Je soupçonne que les affiches précédentes ont tenté de publier le même détail, mais sans trop noter l'étoile de la barre oblique en tant que code, stackoverflow l'affiche comme une simple barre oblique.


2
Avec cela, vous gérerez TOUS les types de fichiers, et c'est vraiment ennuyeux (enfin, sauf si votre application gère vraiment tout) ...
Tim Autin

C'est mauvais. Veuillez ne pas faire cela dans vos applications.
Mars

8

Plutôt que d' android:pathessayer android:mimeType, avec une valeur du type MIME de ce contenu particulier. De plus, android:pathn'accepte pas les caractères génériques - utilisez android:pathPatternpour cela.


"Le type de fichier n'est pas inclus dans les types MIME"? Il devrait toujours y avoir un type MIME pour le type de contenu que vous téléchargez, même s'il n'utilise pas le même mot.
Eric Mill

Il existe un type MIME pour le type de contenu, mais le fichier est produit par une application tierce qui y met une extension différente, donc je ne pense pas qu'il sera reconnu comme ce type MIME.
Curyous

7

J'essaie de faire fonctionner cela depuis des lustres et j'ai essayé fondamentalement toutes les solutions suggérées et je n'arrive toujours pas à faire reconnaître à Android des extensions de fichiers spécifiques. J'ai un filtre d'intention avec un "*/*"type MIME 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 TOUT TYPE de fichier même si J'ai spécifié des extensions de fichier spécifiques à l'aide de la balise pathPattern. Cela va si loin que même lorsque j'essaie d'afficher / de 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 qu'une des nombreuses situations où cela se produit, TRÈS TRÈS ennuyeux.

Finalement, j'ai trouvé ce post de groupes Google avec une question similaire à laquelle un véritable ingénieur du framework Android a répondu. Elle explique qu'Android ne sait tout simplement rien sur les extensions de fichiers, seulement les types MIME ( https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0 ).

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 énorme perte de temps et d'énergie. Si vous avez la chance de n'avoir besoin que 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 non connu par Android, vous n'avez pas de chance.

Si je me trompe à propos de tout cela, veuillez me le dire, jusqu'à présent, j'ai lu tous les articles 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 fréquence à laquelle ce genre de choses semble être dans Android et à quel point l'expérience des développeurs est foirée, mais je vais vous épargner mes élucubrations furieuses;). J'espère que j'ai sauvé des ennuis à quelqu'un.


1
Vous avez voté pour parce que votre réponse donne un lien utile et que le contrevenant n'a pas laissé de commentaire. Désolé, SO peut parfois être hostile de cette façon, mais n'y arrêtez pas.
John Hatton

3

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>

2
La documentation Android indique que l'attribut pathPattern n'a de sens que si un schéma et un hôte sont spécifiés, et j'ai vérifié ceci: developer.android.com/guide/topics/manifest/data-element.html
Brian Pellin

4
-1; cela correspondra à n'importe quel fichier; Le commentaire de Brian est correct et avec la modification mineure de mimeType = " / " son exemple original est parfait.
Nick

Ce message est d'il y a longtemps, mais pas de "/" ne s'installe pas. Vous avez besoin de "* / *", qui correspondra à n'importe quel type de fichier (pas sûr, si vous vouliez dire cela). Ainsi, votre programme peut être invité à ouvrir des vidéos ou des mp3. Je n'ai pas encore trouvé de solution à cela.
René

Vous devez utiliser une <data>balise avec quatre attributs. Votre solution pourrait fonctionner avec Android 2 - mais les règles sont devenues plus strictes: stackoverflow.com/questions/20650378/...
Martin

Qu'est-ce qui se passe avec l'étrange pathPattern ? Et hostet schemesont obligatoires!
IgorGanapolsky

3

Sur Android 4, les règles sont devenues plus strictes qu'autrefois. Utilisation:

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

3

J'ai eu beaucoup de mal avec cela pour une extension de fichier personnalisée, moi-même. Après de nombreuses 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 travaillé pour moi, bien que ce soit un peu un hack:

PatternMatcher est utilisé pour pathPattern chez IntentFilter Mais, l'algorithme de PatternMatcher me semble assez étrange. Voici l'algorithme d'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 du framework Android.)

Ex. string: "ceci est un modèle de mon attachement": ". att. ". Android PatternMatcher entre en boucle pour correspondre à '. 'motif jusqu'à rencontrer le caractère suivant du motif (dans cet exemple,' a ') Donc,'. 'la boucle correspondante s'arrête à l'index 8 -' a 'entre' is 'et' my '. Par conséquent, le résultat de cette correspondance renvoie «faux».

Assez étrange, n'est-ce pas. Pour contourner cela - en fait réduire la possibilité - le développeur doit utiliser pathPattern stupide et ennuyeux.

Ex. Objectif: faire correspondre le chemin d'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 particulièrement émis lors de la correspondance avec une extension de fichier personnalisée.


Pour toute personne intéressée, un problème a été enregistré sur code.google.com
benjamin davis

3

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 se déclenchent pour le suffixe spécifié incluent 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 mime d'Android, jusqu'à présent, je n'ai pas trouvé de moyen de le faire. Si quelqu'un sait, un pointeur serait formidable.


2

Lorsqu'une intention répond à un intent-filter, voici les intent-filterexigences: (imaginez une liste de contrôle).

  • Toute correspondance <action>
  • Toute correspondance <category>
  • Toute correspondance <data mimeType>(solution simple: " / ")
  • En option:

    • Toute correspondance <data scheme>(fixe facile: <data android:scheme="file" /> <data android:scheme="content" />)

    • Toute correspondance <data host>(solution simple: "*")

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

La définition de plusieurs <data $type="">éléments vérifie la case $ type ssi l'un <data $type=>correspond à la Intent.

Omettre mimeType casse votre intent-filter, même si cela semble redondant. L'omission <data scheme/host/pathPattern>fait que votre filtre correspond à tout.

https://f-droid.org/en/packages/de.k3b.android.intentintercept/ est une application conçue pour recevoir toutes les 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 signale <data pathPattern=> .*xyzqu'interrompt dès xqu'il voit, et échouera immédiatement s'il n'est pas suivi de yz. Donc /sdcard/.hidden/foo.0ccne passera pas à .*\\.0ccmoins que vous n'essayiez à la .*\\..*\\.0ccplace.

  • Je n'ai pas vérifié si cette solution de contournement est 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>

1

Si vous souhaitez que les fichiers soient ouverts directement depuis Gmail, Dropbox ou l'un des outils de fichiers Android intégrés, 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 dans une seule instruction selon la version Android 4.x


J'ai tout essayé pour que le téléchargement et l'ouverture du navigateur Android fonctionnent correctement. Votre solution fonctionne bien pour le navigateur natif Android et Chrome Android, mais Firefox Firefox semble toujours ouvrir mon fichier dans une fenêtre de texte. C'est un type mime personnalisé et une extension personnalisée. Auparavant, avec juste l'extension, cela ne fonctionnait que dans Firefox. Maintenant, cela fonctionne partout sauf Firefox (y compris Gmail). Je suis toujours en train de le tester, mais je voulais juste signaler le fait qu'il existe un nouvel ensemble de problèmes entre navigateurs.
Damon Smith

1

Utilisation du filtre comme ci-dessous pour ouvrir à partir du navigateur, de gmail et du navigateur de fichiers (testé). REMARQUE: veuillez ne pas fusionner deux filtres, car 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>

Avez-vous testé cette réponse avec les pièces jointes Gmail?
IgorGanapolsky

1

Mise à jour 2020

Android est passé aux URI de contenu et aux types MIME pour les filtres d'intention.

Le problème

Un URI de contenu ne doit pas nécessairement contenir l'extension ou le nom du fichier et il sera différent entre les différentes applications qui fournissent le contenu / fichier.

Voici quelques exemples d'URI de contenu provenant de différentes applications de messagerie pour la même pièce jointe:

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

Application de messagerie Samsung -> content://com.samsung.android.email.attachmentprovider/1/1/RAW

Comme vous pouvez le voir, ils sont tous différents et ne sont pas garantis de contenir quoi que ce soit lié à votre fichier réel. Ainsi, vous ne pouvez pas utiliser ce android:pathPatternque la plupart ont suggéré.

Une solution de contournement pour les pièces jointes aux e-mails

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

Grâce à des tests, j'ai trouvé les types MIME utilisés par Gmail, Outlook et Samsung Email et les ai ajoutés à mon filtre d'intention.

Mises en garde / Gotchas

  • J'ai trouvé qu'avec ma solution ci-dessus, si j'ouvrais un fichier de type binaire, cela lancerait automatiquement mon application. J'ai géré cela dans mon activité en affichant un état d'échec si nous ne pouvions pas analyser le fichier. J'ai pensé que c'était un événement assez rare, donc ce serait acceptable.

  • Je n'ai trouvé aucun moyen de lancer mon application via le navigateur de fichiers sans ajouter <data android:mimeType="*/*"/>à mon filtre d'intention. Je ne pouvais pas l'utiliser car cela lancerait ensuite mon application chaque fois que l'utilisateur cliquait sur un fichier sur son téléphone (pas seulement ceux avec l'extension de fichier personnalisé). Je ne recommanderais pas d'ajouter ceci à votre filtre d'intention.

Dernières pensées

  • Il n'existe actuellement aucune solution élégante pour associer votre application à un type d'extension spécifique sous Android. C'était le mieux que je puisse faire dans ma situation.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.