Envoyer des données avec Android – Intent & ACTION_SEND

L’une des fonctionnalité bien pratique sous Android est l’envoi de données. Je l’utilise dans Scores Keeper pour envoyer les détails d’un tournoi. En utilisant les Intent et l’intention ACTION_SEND, il est possible de démarrer une « intention d’envoi », le système propose alors à l’utilisateur différentes façon d’envoyer ces données (mail, sms, …).

Voici un petit tutorial qui vous en présentera les principes de base.

Mise à jour : Coup de gueule contre Facebook qui ne gère pas ou très mal l’intent ACTION_SEND. Il est seulement possible de poster un lien et non un texte libre. Je ne comprend pas pourquoi mais on dirait qu’Android ne les intéresse pas. Étrange ! 😦

Voici un exemple de code permettant d’envoyer un simple message :

Main.java (activité principale) :

package org.bbt.actionsend;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;

public class Main extends Activity {

	/**
	 * Text qui sera envoyé
	 */
	private EditText text;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		findViewById(R.id.send).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				send();
			}
		});

		text = (EditText) findViewById(R.id.text);
	}

	/**
	 * Envoyer le message
	 */
	private void send() {
		// intention d'envoi
		Intent intent = new Intent(Intent.ACTION_SEND);
		// contenu à envoyer
		intent.setType("text/plain");
		intent.putExtra(Intent.EXTRA_TEXT, text.getText().toString());
		// envoi de l'intention
		startActivity(Intent.createChooser(intent, "Send a simple text"));
	}
}

main.xml (vue attaché à l’activité) :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">

	<EditText android:layout_width="fill_parent"
		android:layout_height="wrap_content" android:text="Un petit message à envoyer"
		android:lines="5" android:gravity="top" android:id="@+id/text"/>

	<Button android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:layout_gravity="right"
		android:id="@+id/send" android:text="Envoyer" />

</LinearLayout>

La partie interressante est dans la fonction send de l’activité Main. On créé une intention d’envoi de données. On précise que c’est du texte qu’on envoi text/plain et l’on démarre l’activité. Et pis c’est tout 🙂 Android propose alors cet écran :

On voit dans cette liste toutes les applications qui se sont déclarées auprès du système pour réceptionner des données de type texte. On retrouve les incontournables Mail, Messages ou Facebook dans cette liste par exemple. Si l’on clique sur Messages par exemple, on se retrouve dans l’application de messagerie, prêt à envoyer un message avec le contenu déjà pré-rempli. Il ne reste plus qu’à renseigner les destinataires :

A ce stade, nous avons quitté notre application et on se retrouve dans l’application d’envoi de messages. L’utilisateur a donc la liberté de modifier le message, choisir ses destinataires. Ce système est juste une aide pré-remplissant un message. De plus c’est l’utilisateur qui choisi ou non d’envoyer le message et non notre application.

Pour envoyer des mails, il suffit de faire un petit peu évoluer notre méthode send :

	/**
	 * Envoyer le message
	 */
	private void send() {
		// intention d'envoi
		Intent intent = new Intent(Intent.ACTION_SEND);
		// contenu à envoyer
		intent.setType("message/rfc822");
		intent.putExtra(Intent.EXTRA_TEXT, text.getText().toString());
		intent.putExtra(Intent.EXTRA_SUBJECT, "Sujet du mail");
		intent.putExtra(Intent.EXTRA_EMAIL, new String[] { "blogde@benoit.com" });
		// envoi de l'intention
		startActivity(Intent.createChooser(intent, "Send a message"));
	}

En souhaitant envoyer un mail, on peut utiliser d’autres Extra pour enrichir l’Intent. EXTRA_SUBJECT permet de préciser un sujet pour le mail. EXTRA_MAIL permet de préciser le/les destinataire(s) du mail. Après avoir déclenché cette intention on se retrouve sur l’écran d’envoi de mail pré-rempli :

Enfin terminons par l’envoi de fichier. On précise alors le type mime précis du fichier que l’on souhaite envoyer (image/png par exemple si c’est une image PNG).

	/**
	 * Envoyer le message
	 */
	private void send() {
		// intention d'envoi
		Intent intent = new Intent(Intent.ACTION_SEND);
		// fichier à envoyer
		File file = ...;
		// contenu à envoyer
		intent.setType("type mime du fichier");
		intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
		// envoi de l'intention
		startActivity(Intent.createChooser(intent, "Send a file"));
	}

Attention à ne pas envoyer un fichier qui se situe dans le context de l’application. C’est le cas si l’on utilise la méthode openFileOutput à partir du context de notre application. En effet il est nécessaire que l’application tierce (Gmail, Facebook, …) puisse accéder à ce fichier. N’oublions pas que l’envoi s’effectue en dehors de notre application. Il est possible de l’enregistrer sur la carte SD pour résoudre ce problème par exemple.

En espérant que cet article vous sera utile 😉

Tags:, , , , , , , ,

15 réponses à “Envoyer des données avec Android – Intent & ACTION_SEND”

  1. Mutuelle santé dit :

    Merci pour ce billet. Je viens également de parler cette thèmatique via mon blog. Je viens de poster votre lien vers cet article.

  2. Remy01 dit :

    Merci, je me suis permis d’utiliser votre article sur mon blog.

  3. Christophe Gasnier dit :

    Bonjour,

    Sais-tu s’il est possible de récupérer le résultat de l’activité (avec onActivityResult) afin de savoir si le mail a bien été envoyé ou si l’envoi a été annulé?

    Je suis bloqué car je voudrais modifier le status des données pour les noter comme « envoyée » mais je n’y parviens pas. L’activité me retourne toujours un RESULT_CANCELED car je suis obligé d’appuyer sur le bouton « retour » pour récupérer mon activité.

    Merci d’avance.

    • Benoît dit :

      Salut Chris,

      Il est effectivement possible de savoir si le message a bien été envoyé avec la méthode que tu décrit dans ton message. Je l’ai testé avec Gmail et cela fonctionne. Par contre les applications Bluetooth ou Seesmic retrounent RESULT_CANCELED que le texte soit envoyé ou non.
      J’ai envie de dire que le résultat de l’activité n’est pas fiable. Il dépend complètement de l’application que tu appelles. Par curiosité, quelle application te demande forcément d’appuyer sur « retour » ?

      Une autre méthode serait de se passer d’ ACTION_SEND et d’écrire l’envoi des données pour maîtriser complètement ce processus. Mais ça demande beaucoup plus de travail je suis d’accord et cela s’intègre moins bien à l’environnement d’Android 🙂

  4. Khaled Ben Hammouda dit :

    Bonjour, J’ai essayé votre code , ça me donne juste la possibilité d’envoyer via e-mail et Gmail seulement 😦 j’aimerait bien que ça me donne la possibilité d’envoyer par SMS et bluetooth aussi , mais je sais pas comment faire pour qu’ils s’ajoutent automatiquement dans le menu contextuel……
    merci pour votre aide

    khaled

    • Benoît dit :

      Bonjour Khaled. Si tu veux pouvoir envoyer un message par SMS et Bluetooth il faut utiliser le type « text/plain ». D’après ce que tu me dis, j’ai l’impression que tu utilises le type « message/rfc822 » ce qui expliquerait que tu n’ai que les applications de mail. Ceci dit, même si tu utilises le style « text/plain » tu pourras tout de même rajouter les extras EXTRA_SUBJECT et EXTRA_EMAIL (ou d’autres). Ce sont les applications appelées qui décideront si oui ou non elles en ont besoin (les applications de mail l’utiliseront mais pas l’application SMS par exemple).
      J’espère avoir répondu à ta question.

      Benoît

      • khaledbha79 dit :

        merci beaucoup Benoit , t’as répondu à ma question. on faite je suis débutant dans la programmation et surtout la programmation android. alors j’ai commencé par faire des petites exemples qui concernent la partie graphique surtout , je voudrais te demander si je me bloque sur un problème est ce que je peux t’écrire pour m’aider???

        Khaled

      • Benoît dit :

        Bonjour, je suis content que ça t’ai aidé. Je n’ai rien contre donner un coup de main, bien au contraire :). Par contre je ne souhaite pas répondre à des messages privées. Je veux avant tout partager mon expérience sur ce blog. Tes interrogations pourraient servir à d’autres personnes.

        Benoît

  5. khaledbha79 dit :

    Bonjour ,

    dans mon petit exercice j’ai créé 2 boutons , j’ai voulais que chaque bouton affiche un menu contextuel propre à lui . mon problème c’est que quand j’appuie sur le premier bouton il m’affiche tous les items (ceux que j’ai voulu qu’il s’affiche en appuyant sur lui (item1 et item2) et ceux que j’ai voulu en appuyant sur l’autre bouton (item3 et item4)) de même pour l’autre bouton!! pourtant j’ai créé 2 fichier XML , un fichier pour chaque menu contextuel voici l’extrait du code :
    @Override

    public void onCreateContextMenu(ContextMenu menu, View v,

    ContextMenuInfo menuInfo) {

    super.onCreateContextMenu(menu, v, menuInfo);

    MenuInflater inflater = getMenuInflater();

    inflater.inflate(R.menu.menucontextuel1, menu);

    inflater.inflate(R.menu.menucontextuel2, menu);

    }

    • Benoît dit :

      Bonjour, me suis permis d’enlever un peu de code de ton commentaire pour ne pas surcharger la page. Ton problème viens de la méthode OnCreateContextMenu. Tu « inflate » les 2 fichier xml d’affilé, ça me semble normal que le menu créé ai les 2 boutons. De plus il devrait y avoir un autre problème. OnCreateContextMenu n’est appelé qu’une seule fois pour ne pas avoir à créer plusieurs fois le menu. Tu devrais utiliser la méthode onPrepareOptionsMenu pour personaliser ton menu suivant le bouton qui a été cliqué.

      • khaledbha79 dit :

        merci merci merci Benoit ,j’ai réussi à le faire , voici le code:

        public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {

        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();

        if (ID == R.id.buttonupload)
        inflater.inflate(R.menu.uploadcontextuel, menu);
        else
        inflater.inflate(R.menu.mediacontextuel, menu);
        }

        public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        return true;
        }

  6. Théo dit :

    Salut Benoît,

    J’ai pas mal cherché des infos ces derniers temps pour tenter d’envoyer un message à un destinataire en particulier vers le hangout ou le facebook d’une personne avec son adresse email ou le compte facebook par le biais d’un intent.

    Résultat… Je n’ai pas trouvé d’autre moyen que de pré-fabriquer, comme tu as montré, un « template » d’email ou autre et de choisir manuellement le contact

    J’ai pas mal sondé des forums sans trouver de réponses.

    Du coup, j’attends de tes nouvelles si tu vois du nouveau pour facebook ou hangout.

    A plus et bon courage pour la suite

    • Benoît dit :

      Salut,

      Je regarde régulièrement pour facebook mais je crois qu’ils ne permettent toujours pas d’utiliser l’ACTION_SEND pour leur réseau. Ils préfèrent que l’on passe par leur API mais cela demande pas mal de travail.
      Du peu que j’ai pu voir de hangout, je n’ai pas l’impression qu’il prenne en compte le mail associé à l’intent ACTION_SEND pour définir le destinataire. Je ne pense pas qu’il en tienne compte tout simplement. Vu que c’est leur application qui a décider de fonctionner comme cela je ne pense pas que tu puisse y faire grand chose.

      @+ et bonne continuation.

Laisser un commentaire