IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Création d'activité Android


Sujet :

Android

  1. #21
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Parcequ'il ne faut pas appeler "run()" mais "start()" pour démarrer le thread....

    Par contre, tu as tout interêt à utiliser les outils offerts par le framework plutot que réinventer la roue et utiliser les classes bas-niveau. Par exemple "AsyncTask".
    Ceci te permettra de signaler à l'activité quand la tâche est terminée sans aucun problème (l'utilisation d'un Thread nécessitera un Handler, etc...).

  2. #22
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Par défaut
    Bonjour,

    Merci Nicoman; En effet ça marche nettement mieux en mettant la méthode start() avant le run().

    Ça copie bien le fichier.

    J'ai donc avancé et fait une petite recherche pour copier une image.

    Je modicie dons ma classe FileUtils de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
     
    	public static byte [] ImageToByte(File file) throws FileNotFoundException{
    		FileInputStream fis = new FileInputStream(file);
    		ByteArrayOutputStream bos = new ByteArrayOutputStream();
    		byte[] buf = new byte[1024];
    		try {
    			for (int readNum; (readNum = fis.read(buf)) != -1;) {
    				bos.write(buf, 0, readNum);     
    //				System.out.println("read " + readNum + " bytes,");
    			}
    		} catch (IOException ex) {
    			ex.printStackTrace();
    		}
    		byte[] bytes = bos.toByteArray();
     
    		return bytes;
    	}	
     
    	public boolean save2Samba(byte[] text, String fileName) {
     
    //		jcifs.Config.setProperty("jcifs.netbios.wins", "192.168.1.78");
     
    		String username="mcotte";
        	String password="toto";
        	String domaine="mondomaine";
        	Log.d("Password", password);
     
        	String url = "smb://" + fileName;
     
            Log.d("Url", url);
     
        	NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domaine,
                     username, password);
     
    		SmbFile sFile;
            try { 
    			sFile = new SmbFile(url, auth);
    			Log.d("sFile11", sFile.getURL().toString());
    			Log.d("Can write", ""+sFile.canWrite());
        		SmbFileOutputStream out = new SmbFileOutputStream( sFile, false);
        		Log.d("debug","après SMBOS");
        	    for (byte octet : text){
        	    	out.write(octet);
        	    }
     
    			Log.d("debug","après out.write");
                try {
     
                    out.flush();
                    out.close();
     
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
     
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

    Par contre, je n'ai pas compris la fin de ton explication. Pourrais tu me la détailler un peut plus s'il te plaît ?

    Et dans ma mainactivity :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    	@Override
    	protected void onResume() {
    		// TODO Auto-generated method stub
    		super.onResume();
    		ThreadCopyFile thread = new ThreadCopyFile();
     
    	    // Activation du thread
    		thread.start();
    		thread.run();
    Ca a l'air de marche mais j'ai toujours en warning (orange) l'exception suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    07-17 14:34:35.562: W/System.err(12948): android.os.NetworkOnMainThreadException
    Plus un certain nombre d'autre, qui ne me font pas planter la copie.
    Simplement à la fin quand j'essaye d'ouvrir le fichier j'ai une fenêtre modale de message d'erreur qui me dit "Encountered a sharin violation while accessing..."


    Par contre, tu as tout interêt à utiliser les outils offerts par le framework plutot que réinventer la roue et utiliser les classes bas-niveau. Par exemple "AsyncTask".
    Ceci te permettra de signaler à l'activité quand la tâche est terminée sans aucun problème (l'utilisation d'un Thread nécessitera un Handler, etc...).
    Qu'est-ce que le AsyncTask ? Comment implémenter sinon, le Handler ?

    Ça fait beaucoup de question quand même, j'en suis conscient. J'espère que ça n'est pas trop ?

    Par avance merci.

    Marco.

  3. #23
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Citation Envoyé par cotmar
    Ca a l'air de marche mais j'ai toujours en warning (orange) l'exception suivante :
    Tu n'aurais pas, par hasard, modifié les paramètres de sécurité ?

    Pour la NetworkOnMainThread, je t'ai déjà dit ça plus tôt :
    Citation Envoyé par Hizin Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    NetworkOnMainThreadException
    Tu réalises un appel réseau dans le main thread, le thread graphique, ce qui est totalement déconseillé quelle que soit la plate-forme et le langage.

    Il faut que tu fasses une tâche en background pour réaliser ta copie. Je te suggères de t'intéresser soit à une AsyncTask, soit à un couple Thread/Handler.
    Qu'est une AsyncTask ? Une classe particulière permettant de gérer facilement des appels asynchrone (d'où son nom). Plus de renseignements dans la documentation.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  4. #24
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Par défaut
    Bonjour Hizin,

    Je reconnais que mes questions n'étaient pas très bien posées.
    Pour le moment je cherche à approfondir le sujet et si je comprends, pour que le thread ne soit pas considéré comme faisant partie du thread principal, il faut qu'il sur lancé par un évènement (onClick d'un bouton par exemple) ou un Asynctask ?

    En ce moment j'essaye d'aprofondir la chose avec Asynctask et ça a m'a l'air assez coton, d'autant que la documentation ne m'a pas l'air très explicite sur le sujet. Du coup, je serais assez preneur d'une petite explication sur le sujet s'il te plait ?

    Par avance merci.

    Cordialement,
    Marco.

  5. #25
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Citation Envoyé par cotmar
    Pour le moment je cherche à approfondir le sujet et si je comprends, pour que le thread ne soit pas considéré comme faisant partie du thread principal, il faut qu'il sur lancé par un évènement (onClick d'un bouton par exemple) ou un Asynctask ?
    Non
    Tu as le thread principal (graphique), et les autres. Tu peux lancer ton thread depuis le principal, quelle que soit la raison ("parce que", clic, service, déclenchement horaire, senseur...), pas de problème ensuite.

    Concernant les AsyncTask, c'est une classe "sucre syntaxique" assez facile à utiliser, la difficulté résidant dans les paramètres génériques. Sa spécificité est que certaines méthodes sont exécutées sur le thread graphique, et d'autre sont exécutées en background.
    Cette classe considère que le thread qui l'a lancé est le thread graphique, attention donc.

    Tout d'abord, les types génériques de cette classe. Il y en a 3 :
    • paramètres d'entrés : c'est le type de données qui sera utilisé pour lancer la tâche via execute. Attention, c'est une ellipse, donc un tableau non borné => paramètre de doInBackground
    • progrès : le type de données qui sera utilisé pour la publication des progrès => paramètre de onPublishProgress
    • paramètres de sortie : c'est le type de données qui sera renvoyé à la fin du traitement => paramètre de onPostExecute


    Elle est composée de 3 méthodes principalement : onProgressUpdate(?), doInBackground(?...) et onPostExecute(?). Il y en a d'autre, bien sûr, qui sont aussi intéressante et pratique, mais ces trois-là sont "le minimum".

    La principale est doInBackground(), c'est dans celle-ci que doit être ton code relatif au traitement de tes données. Cette méthode est exécutée en tâche de fond et ne doit en aucun cas toucher à quoi que ce soit de graphique.

    Ensuite, onPostExecute(?) est invoquée quand le traitement effectué dans doInbackground(?...) est fini. Cette méthode est invoquée sur le thread graphique, et sert a mettre à jour les divers éléments (enlever le Dialog d'attente, mettre à jour les données de la vue, etc...).

    Enfin, onProgressUpdate(?) est invoquée suite à l'appel de la méthode publishProgress(?). Elle est invoquée sur le thread graphique et sert généralement à notifier l'état d'avancement à l'utilisateur. La méthode l'invoquant (publishProgress) est généralement utilisée dans doInBackground(?...), celle-ci faisant le traitement, c'est le seul endroit où on sait où il en est.

    Tu dois créer ta propre classe héritant d'AsyncTask et implémentant les comportements que tu désirs, au minimum le doInBackground pour ton traitement et le onPostExecute pour le retour.

    Si tu ne désirs pas un paramètre (comme le type de publication, par exemple, si l'utilisateur n'a pas besoin d'être notifié du progrès de la tâche), mets le à Void.

    Ce que j'ai écris plus haut n'est pas totalement exact, mais devrait te suffire.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  6. #26
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    C'est simple AsyncTask fait l'interface entre le thread UI et ... un bout de code qui doit être réalisé dans "un autre thread"....

    grosso modo:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    class MyTask extends AsyncTask<TYPEENTREE,TYPEPROGRESS,TYPESORTIE>
    {
        public void onPreExecute(TYPEENTREE ... params)
        {
             // sera effectué dans l'UI thread, on peut donc manipuler l'UI ici comme afficher une progress bar...
        }
     
        public TYPESORTIE doInBackground(TYPEENTREE ... params)
        {
             // sera effectué dans un autre thread....
        }
     
        public void onPublishProgress(TYPEPROGRESS ... state)
        {
             // sera effectué dans l'UI thread, à chaque fois que la fonction doInBackground appelle "postProgress", permet de mettre à jour une progress bar ou autre
        }
     
        public void onPostExecute(TYPESORTIE sortie)
        {
             //  sera effectué dans l'UI thread, à la fin de l'execution...
             // permet donc de mettre à jour l'interface, changer d'activité, etc...
        }
    }
    L'utilisation est ensuite très simple, il "suffit" d'appeler execute() sur la tâche pour que toutes les opérations soient réalisées...

  7. #27
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Par défaut
    Bonjour,

    Merci de ces deux réponses les amis.

    Je pense que je ne suis pas encore sorti d'affaire, mais ça m'aide quand même pas mal à progresser.

    En tous les cas, pour le moment j'essaye de "recoller" les morceaux de mon projet qui jusque là étaient séparés.

    Le projet comporte plusieurs éléments :

    - Faire des séries de photos (threads différents),
    - Utilisation concurrente d'un composant externe piloté par Android,
    - Sauvegardes photos sur un serveur externe.

    Ici lorsque je sauvegarde vers le serveur externe (en incluant une bibliothèque Jar) via le protocole SAMBA en WiFi (depuis le téléphone Android), je n'ai pas la totalité de mon image de départ.

    Je reviendrais plus tard sur la prise de photos, mais est-ce que selon vous, le fait que je n'ai pas un bon résultat lors de la sauvegarde est dû au fait que je lance cette même sauvegarde dans le thread principal. Ici au débug, je vois la trace de toutes les interruptions qui semblent parasiter la sauvegarde. D'où ma question ?

    Par avance merci.

    Marco.

  8. #28
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Par défaut
    Bonjour,

    Alors j'ai créé un thread avec un handler en m'inspirant de ce que vous m'avez donné plus les tutos pour faire une copie d'un fichier (avec SAMBA) vers un serveur depuis le téléphone Android.

    A présent je voudrais lancer ça via une Asynctask, mais apparemment il ne rentre pas dedans.

    Est-ce que vous pourriez me dire ce qui ne va pas s'il vous plaît ?

    Dans mon activité principale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
     
    package com.example.threadexample;
     
    import java.net.URL;
     
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.View;
    import android.widget.Toast;
     
    public class ThreadExample extends Activity {
     
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_thread_example);
    	}
     
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		getMenuInflater().inflate(R.menu.thread_example, menu);
    		return true;
    	}
     
    	public void buttonClick(View view){
     
        	Runnable runnable = new Runnable() {
    	        public void run() {
     
    	    		TaskCopyFile taskCopyFile = new TaskCopyFile();
     
    	    		URL urls[]=new URL[2];
    	    		try{
    	    			URL urlSource = new URL("storage/extCard/DCIM/Camera/toto.jpg");
    	    			Toast.makeText(getApplicationContext(), "urlSource : "+urlSource, Toast.LENGTH_LONG);
    	    			URL urlDest = new URL("XXX.XXX.X.XX/ESPACE/TESTS/EssaiMarc/toto.jpg");
    	    			Toast.makeText(getApplicationContext(), "urlDest : "+urlDest, Toast.LENGTH_LONG);
     
    	    			urls[0]=urlSource;
    	    			urls[1]=urlDest;
    	    		}catch (Exception e){
    	    			e.printStackTrace();
    	    		}
     
    	    		taskCopyFile.execute(urls);
     
    		    };
    		};	
    	}
    }
    Dans mon asynctask :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
     
    package com.example.threadexample;
     
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.net.URL;
    import java.text.SimpleDateFormat;
    import java.util.Date;
     
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
     
    public class TaskCopyFile extends AsyncTask<URL[], Integer, Long> {
     
    	Handler handler = new Handler() {
    	@Override
    		public void handleMessage(Message msg) {			  
    			Bundle bundle = msg.getData();
    			String string = bundle.getString("myKey");
    			//ToDo : Communication avec l'interface
    //			TextView myTextView = (TextView)findViewById(R.id.myTextView);
    //			myTextView.setText(string);
          	}
    	}; 
     
    	@Override
    	protected void onCancelled() {
    		// TODO Auto-generated method stub
    		super.onCancelled();
    	}
     
    	@Override
    	protected void onPostExecute(Long result) {
    		// TODO Auto-generated method stub
    		super.onPostExecute(result);
    	}
     
    	@Override
    	protected Long doInBackground(URL[]... urls) {
    		// TODO Auto-generated method stub
        	Runnable runnable = new Runnable() {
    	        public void run() {
    				Message msg = handler.obtainMessage();
    				Bundle bundle = new Bundle();
    				SimpleDateFormat dateformat = new SimpleDateFormat("HH:mm:ss MM/dd/yyyy");
    				String dateString = dateformat.format(new Date());
     
    				//Préparation de la copie
    				FileUtils fu = new FileUtils();
     
    				String source = "/storage/extSdCard/DCIM/Camera/toto.jpg";
     
    				String dest = "XXX.XXX.X.XX/ESPACE/TESTS/EssaiMarc/toto.jpg";
     
    				byte[] image = null;
    				try {
    					image = FileUtils.extractBytes(source);
    				} catch (FileNotFoundException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				} catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				fu.save2Samba(image, dest);
     
    				fu.setDest(dest);
    				fu.setSource(source);
    				bundle.putString("myKey", fu.toString());
    				msg.setData(bundle);
    				handler.sendMessage(msg);
    	        }
        	};
     
    		Thread mythread = new Thread(runnable);
    		mythread.start();
    		return null;
     
    	}
     
    }
    J'ai essayé de tracer avec le débuguer, mais visiblement il passé sur le "runable" et va ensuite directement à la fin. Pourriez-vous m'expliquer où jefais des erreurs s'il vous plaît ?

    Par avance ce je vous remercies.

    Cordialement,
    Marco.

  9. #29
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Tu ne lances jamais ton Thread.
    Invoque sa méthode start().
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  10. #30
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Par défaut
    Bonjour Hizin,

    Merci de ta réponse.
    En fait si il y a bein le start, mais dans le Asynctask (à la fin) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    Thread mythread = new Thread(runnable);
    		mythread.start();
    		return null;
    Mais peut-être est-il mal placé ou mal employé ?

    Par avance merci.

    Marco.

  11. #31
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Non mais il ne faut pas mélanger AsyncTask et Thread.....


    Pour exécuter le truc il te faut le faire dans un thread séparé de l'UI...
    Ce thread séparé peut être obtenu par:
    * Utilisation de la classe Java "Thread"... La communication avec l'UI doit alors se faire par Handler... (nécessité de gestion des Thread / Handler / Synchronisations).
    * Utilisation de la classe Android "AsyncTask" (qui se charge de créer son propre thread/handler, en fait même pas, puisqu'elle utilise une pool de threads partagés, bien plus optimisé que la *très* longue construction d'un nouveau thread à chaque appel, et de réutiliser le Handler de l'UI par défaut).

    Mais c'est l'un ou l'autre...

Discussions similaires

  1. Réponses: 37
    Dernier message: 26/03/2014, 00h15
  2. Création d'activité à la volée ?
    Par Invité dans le forum Android
    Réponses: 9
    Dernier message: 02/04/2012, 14h18
  3. Premiers pas création appli sous android
    Par enrico83600 dans le forum Android
    Réponses: 3
    Dernier message: 17/04/2011, 14h10
  4. Réponses: 13
    Dernier message: 17/12/2010, 11h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo