Android – Associer son application avec des fichiers – les Intent Filter

Voici un petit article pour mon ami Laurent 😉 (et pour moi aussi car je vais certainement en avoir besoin pour Scores Keeper). Il décrit comment associer un type de fichier avec son application Android. Ainsi lorsqu’on essaiera d’ouvrir un fichier de ce type avec Gmail, un explorateur ou tout autre application, notre application pourra être utilisée pour ouvrir et lire ce dernier.

Pour ce tutorial, nous allons donc créer une application qui s’associera aux fichiers CSV (comma-separated values). En voici un petit que j’ai créé avec Excel :

La première chose à faire (comme toujours) est de créer un nouveau projet :-P. Nous allons déclarer notre activité principale comme réceptrice de fichiers CSV grâce au Manifest en lui précisant son type MIME dans un Intent Filter de la façon suivante :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="org.bbt.opencsv" android:versionCode="1" android:versionName="1.0">
	<uses-sdk android:minSdkVersion="4" />

	<application android:icon="@drawable/icon" android:label="@string/app_name">
		<activity android:name=".Main" android:label="@string/app_name">

			<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="text/csv" />
			</intent-filter>

		</activity>

	</application>
</manifest>

Il est aussi possible de filtrer sur une extension précise, un chemin précis, … pour cela rendez-vous sur le site d’Android et son chapitre sur les Intents & Intent Filters. Nous définissons ici un Intent Filter pour une activité, mais il est aussi possible d’en définir un pour un Service ou un BrodcastReceiver.

Pour filtrer suivant l’extension d’un fichier voici comment procéder pour les fichiers CSV :

<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=".*\\.csv" />
    <data android:host="*" />
</intent-filter>

Ensuite, dans la vue main.xml nous allons y placer un TextView qui servira à afficher le contenu :

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:text="Aucune données n'a été reçue"
	android:id="@+id/content" />

Enfin dans notre activité principale, nous allons tester qu’un contenu nous a été envoyé. Nous allons en extraire le contenu et l’afficher dans le TextView prévu à cet effet :

package org.bbt.opencsv;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class Main extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// TextView utilisé pour afficher le contenu du fichier
		TextView contentText = (TextView) findViewById(R.id.content);

		// test du type de contenu que l'on pourrait recevoir (en fonction de l'URI des données envoyées)
		String scheme = getIntent().getScheme();
		if (("content".equals(scheme)) || ("file".equals(scheme))) {
			try {
				// Tentative d'ouverture du flux de données
				InputStream attachment = getContentResolver().openInputStream(getIntent().getData());
				BufferedReader r = new BufferedReader(new InputStreamReader(attachment));
				// Lecture du contenu
				String line;
				StringBuffer result = new StringBuffer();
				while ((line = r.readLine()) != null) {
					result.append(line + "\n");
				}
				contentText.setText(result.toString());
				Toast.makeText(this, "success", Toast.LENGTH_SHORT).show();
			} catch (Exception e) {
				// Une erreur s'est produite lors de la lecture du flux
				Toast.makeText(this, "error while opening the file.", Toast.LENGTH_SHORT).show();
				e.printStackTrace();
			}
		}
	}
}

Ainsi, lorsque nous ouvriront un fichier CSV de Gmail par exemple :

Android nous proposera toutes les applications associées à ce type de fichier, et nous pouvons trouver Open Csv (notre application) dans la liste :

Notez que notre application n’est pas la seule associée avec les fichiers CSV. En choisissant notre application, nous pouvons voir le contenu du fichier affiché dans notre TextView :

Et voilà, c’est aussi simple que ça 🙂 Il nous est alors possible de traiter le contenu de ce fichier comme bon nous semble !

Tags:, , , , ,

25 réponses à “Android – Associer son application avec des fichiers – les Intent Filter”

  1. Duvergé Laurent dit :

    Ca marche super! Merci!
    Laurent

  2. Dalc dit :

    Hop page en favori 😀
    Exactement ce que je cherchais !

  3. Anthony dit :

    Bonjour,
    je souhaiterais adapter votre code pour une application de lecture de fichier sgf (parties de go), mais je me heurte à quelques problèmes.

    Le code donné dans le tutoriel fonctionne parfaitement chez moi avec les fichiers csv, mais lorsque je tente de changer le mimetype pour « application/x-go-sgf » (qui correspond donc aux fichiers sgf), cela ne fonctionne plus.
    Pourtant un appel à mimetypemap.getMimeTypeFromExtension(« sgf »); retourne bien « application/x-go-sgf ».

    La seule parade que j’ai trouvé est de mettre dans l’intent filter :

    Mais là encore ce n’est pas le résultat attendu, vu que l’application se retrouve associé non pas seulement avec les fichiers sgf, mais avec TOUTES les extensions…

    Auriez-vous quelques éléments de réponses à m’apporter ?

    • Benoît dit :

      Bonsoir Anthony,

      Je crois que vous avez oublié de copier votre code 🙂 Quoi qu’il en soit j’ai fait quelques tests et je ne suis pas arrivé à ouvrir ce type de fichier avec le type mime. Le type mime “application/x-go-sgf” n’est peut être pas juste car c’est un fichier de type texte. Mais il est possible de filtrer avec l’extension en procédant ainsi :

      <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=".*\\.sgf" />
      <data android:host="*" />
      </intent-filter>

      J’espère que cette solution vous convient.

  4. Anthony dit :

    Bonjour, merci pour cette réponse rapide 🙂

    Oui, en effet j’ai oublié de coller le code, mais ça n’a plus trop d’importance à présent…

    La solution présenté fonctionne pour l’ouverture depuis l’explorateur de fichier. J’ai aussi rajouté deux intent-filter sur le même modèle, un avec scheme « http » et l’autre « https » pour pouvoir ouvrir les fichiers depuis le web, mais bizarrement il a fallut enlever la ligne mimeType pour que ça fonctionne, alors qu’à l’inverse pour celui avec « file » ça ne marche que si le mimeType est remplit…

    Une dernière bizarrerie : je n’arrive pas à ouvrir les fichiers depuis l’application gmail, j’y arrivais pourtant avec le code de l’exemple pour les csv. Peut-être avez-vous une dernière suggestion ? Sinon tant pis je ferrais avec ^^

    Pour récapituler, mon code complet est :

    (J’ai aussi rajouté « content » et j’ai laissé celui avec le mimeType au cas où…)

    • Anthony dit :

      Ah il semblerait que le code ne soit pas pris en compte après validation du formulaire, peut-être à causes des espaces/tabulations devant ? (et puis je me disais bien que je n’avais pas oublié la première fois ^^)

      Nouvel essai :

    • Benoît dit :

      Apprement c’est pour ça qu’il existe ce genre d’application : https://play.google.com/store/apps/details?id=com.poofinc.gmailattach. Là je pense que tu n’y peux pas grand chose si ce n’est développer ce genre de fonctionnalité pour Gmail.

      • Anthony dit :

        Ce genre d’application va justement utiliser un intent-filter, surement avec un mimetype= »*/* » et scheme= »content » pour permettre de télécharger le contenu des pièces jointe.

        Après de nombreux essai, j’ai finalement compris le comportement de gmail vis-à-vis des pièces jointes :

        L’application gmail ignore le champ pathPattern, et n’affiche les boutons « Télécharger » et « Aperçu » qu’en fonction du mimeType de la pièce jointe. Pour les fichiers dont il ne connait pas le mimeType, il leur attribue celui de « application/octet-stream », ce qui est le cas pour les fichiers sgf, mais aussi pour une multitude d’autres fichiers.

        Le seul moyen d’afficher un bouton « Aperçu » pour les fichier sgf est donc d’utiliser un intent-filter de la forme android:mimeType= »application/octet-stream » scheme= »content », mais le problème est que cela matche aussi avec tous les fichiers ayant des extensions non-reconnu du coup…

        Bref, à priori pas de solution pour couvrir seulement les sgf depuis gmail, dommage.

      • Benoît dit :

        C’est effectivement étonnant de la part de l’application Gmail. Doit y avoir une raison mais je vois pas laquelle 😦 C’est bien dommage pour ton usage. Gmail est un moyen bien pratique pour partager des données entre smartphones.
        En tout cas merci pour toutes ces précisions j’aurai au moins appris quelque-chose et bon courage pour la suite de tes développements.

  5. Didi dit :

    Salut. J’aimerai faire ouvrir les fichiers .z64 à l’application N64oid, car elle n’apparait pas dans la liste des applications que Android me propose pour ouvrir ces fichiers. Est-il possible d’utiliser ce genre de script pour faire ça ?

    • Benoît dit :

      Normalement oui. A priori les fichiers z64 n’ont pas de type mime à eux donc j’utiliserai le nom de l’extension. Il y a un exemple dans cet article. Par contre, cette solution ne fonctionnera pas avec Gmail. Regarde les commentaires que j’ai pu échanger avec Anthony dans ce même article. Mais avec un explorateur de fichiers ça ne devrait pas poser problème.

      • Didi dit :

        Ok, merci pour cette réponse rapide.
        Par contre heu… Je n’ai pas compris quel fichier je dois éditer pour y ajouter ce code… ‘^^ Ca se trouve où ?

    • Anthony dit :

      Salut,
      si j’ai bien compris tu veux rajouter la gestion des fichiers z64 pour une application que tu ne developpe pas toi même ? Si c’est le cas ça me parait compromis.

      Par contre si c’est pour ton application, il suffit d’éditer le manifest comme expliqué dans le tutoriel plus haut.

      • Didi dit :

        Non ce n’est pas mon application, mais l’auteur n’a pas implémenté ça, donc je cherche un moyen de l’ajouter. Ca doit etre fait avant la compilation ou ça peut etre édité dans un fichier caché (mon appareil est rooté) ?

      • Anthony dit :

        En fait le manifest permet de dire a Android « mon application utilise tel mimetype, donc si quelqu’un veut ouvrir un fichier de ce type, appellez moi ».
        Donc même si tu arrives à modifier le manifest de l’application en question, il faudrait que celle-ci soit capable derière de gérer l’intent correctement etc, donc de toucher au code source.

        Tu peux voir le fichier manifest en utilisant l’application ManifestViewer sur le market : https://play.google.com/store/apps/details?id=jp.susatthi.ManifestViewer
        Mais ta seule chance serait que le système est bien été prévu, mais mal implémenté au niveau du manifest, ce qui est peu probable.

  6. Didi dit :

    Merci les gars pour ces infos précieuses, j’ai réussi. 🙂
    J’ai jeté un coup d’oeuil au manifest et j’y ai vu ceci :

    Apparement c’était déjà prévu. J’ai donc créé l’extension z64 dans Astro en lui donnant « application » et « x-n64-rom » et maintenant ça fonctionne, N64oid apparait même enfin dans la liste lorsque je veux créer un raccourci sur le bureau. 🙂

  7. Anthony dit :

    GG ^^
    Envoit leur peut etre un email, pour leur signaler l’erreur 😉

  8. Ludo dit :

    Bonjour a tous, merci pour ce post.

    Je me bats depuis 2 jours pour faire apparaitre les fichiers .ogm dans Android comme un fichier « video » … mais je n’y arrive pas.

    Le but est d’associer les .ogm à MXPlayer via un explorateur (comme ESexplorer)
    ESexplorer peut le lancer mais en faisant « appuis long/ouvrir comme/video…. » pas rapide 😦

    Merci de me dire si c’est faisable ou pas.
    Ludovic

    • Anthony dit :

      Bonjour Ludo,

      Si je comprend bien tu cherches à faire la même chose que Didi, mais avec des fichier .ogm.
      Je t’invite à lire les messages précédent et à tenter la même manipulation, le type mime des fichiers ogm est video/ogg.

    • Benoît dit :

      Bonjour, le comportement que tu décris me semble être lié à Esexplorer. Avec le gestionnaire que j’utilise (fourni par cyanogen) je n’ai pas le même comportement. Une fois associé à MXPlayer, un simple clic lance cette application.

      J’ai testé Esexplorer, et un clic simple (pas un long) me propose effectivement « Ouvrir comme ».

      Essaie d’autre explorateurs sinon, il y en a des tas ! Tu trouveras sûrement ton bonheur 🙂

      • Ludo dit :

        Merci pour votre rapidite et connaissances,

        Oui j’ai lu vos échanges et j’ai suivi la méthode de Didi (car la partie code, c’est du chinois pour moi 😉

        Je suis passé par l’explorateur « Astro » , pour lui ajouter une extension « .ogm » et l’associer a un lecteur video (MxPlayer) et le faire passer pour un « .avi ».

        Par contre la dernier mouture d’Astro(v4) ne permet plus de rajouter et d’associer des extension (je pense) , il m’a fallut retrouver une ancienne version (la 3).

        Du coup le fichier « .ogm » s’execute direct dans MXPlayer en cliquant dessus, et tout ce passe bien…maiqs…en interne (sur SDCARD ou Ext_SD)

        Mais mon souhait est de lire sur ma tablette android mes videos stockées sur mon PC (Win7) via le SMB ou UPNP (wifi)

        Du coup j’ai bataillé pour mettre en place le SMB sur ASTRO , et une fois fais, un message annoce que le streaming et ou transfert de fichier ne peut se faire, Grrrr

        Normalement BSPlayer propose la navigation via SMB et association de tous fichiers video, mais je sais pas pourquoi ma tablette (PIPO M1) bug avec ce puissant logiciel (j’ai rooté, flashé des stock ROM ou custom, et rien ne change)

        Donc je desire passer par un explorateur ou player acceptant le SMB ou UPNP et acceptant « tous » les formats video

        Et c’est là que ça coince, il se « confortent » tous a la definition MIME TYPE de mon Android, c’est a dire « .ogm » inconnu , Grrrr
        Ces fichiers ne sont donc pas visible ou non executable ou non executable par un simple clic (comme ESexplorer qui me repond « Désolé, aucune application disponible »)

        Voila, c’est anecdotique, peu important, mais emmerdant de ne pouvoir associer un fichier a un logiciel … c’est si simple sur un PC…

        Merci pour vos lumières.
        Ludo

      • Benoît dit :

        Pourquoi ne pas utiliser un browser spécialisé UPnP/DLNA. Il en existe pas mal aussi. C’est vrai qu’ils ont leur propre lecteur intégré et n’utilisent pas MXPlayer.

        https://play.google.com/store/apps/details?id=com.dbapp.android.mediahouse par exemple

        Je l’ai testé rapidement sur mon serveur DLNA et ça a l’air de bien marcher.

  9. Ludo dit :

    Merci pour tes reponses Benoit,
    Mais non, rien ne fonctionne : les OGM n’etant pas reconnu par android comme un fichier video, les explorateurs via UPnP/DNLA ne font rien mieux « qu’explorer » et ne veulent pas executer ces fichiers…et certain ne les montrent meme pas…vraiment naze.

    Bref je ne me prend pas la tete (j’en ai deja trop fait) , il viendra un temps ou un « astucieux » developpeur mettra en oeuvre un prog pour lier des fichiers a des progs dans le system…patience…
    et continuons a bidouiller cet Android

    Encore merci
    Ludo

Répondre à Anthony Annuler la réponse.