Exemples de code Android

Client TCP de base

Cette classe est un exemple d'application qui utilise un socket TCP pour envoyer des requêtes à un serveur et lire ses réponses. Deux choses sont à remarquer :

  1. toutes les opérations réseau se font dans des threads secondaires (threads différents du thread principal chargé de l'interface utilisateur, aussi appelé UI Thread);
  2. toutes les modifications de l'interface utilisateur sont effectuées par le thread principal lui-même.

Ce client peut être testé avec un serveur écho ou tout autre serveur fonctionnant selon le mode requête-réponse où les requêtes et les réponses sont des lignes de texte.

MainActivity.java

package net.codeandroid.clienttcp;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

public class MainActivity extends AppCompatActivity {
    // adresse et port du serveur
    public static final String ADRESSE = "144.217.5.158";
    public static final int PORT = 2020;

    // communication
    private Socket mSocket;
    private BufferedReader mReader;
    private PrintWriter mWriter;

    // interface utilisateur
    private EditText etRequete;
    private TextView tvReponse;
    private String mTexte;

    // autres
    private boolean mConnexionActive = false;

    // ------------------------------------------------------------------------
    // Point d'entrée de l'application.
    // ------------------------------------------------------------------------
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        etRequete = (EditText)findViewById(R.id.etRequete);
        tvReponse = (TextView) findViewById(R.id.tvReponse);
    }

    // ------------------------------------------------------------------------
    // Connexion au serveur dans un thread secondaire.
    // ------------------------------------------------------------------------
    private void connecter() {
        mConnexionActive = true;

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mSocket = new Socket(ADRESSE, PORT);
                    mReader = new BufferedReader(
                            new InputStreamReader(mSocket.getInputStream()));
                    mWriter = new PrintWriter(
                            new OutputStreamWriter(mSocket.getOutputStream()));
                } catch (IOException ioe) {
                    mTexte = ioe.getMessage();
                    afficher();
                }
            }
        }).start();
    }

    // ------------------------------------------------------------------------
    // Déconnexion du serveur dans un thread secondaire (pas utilisé ici).
    // ------------------------------------------------------------------------
    private void deconnecter() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mReader.close();
                    mWriter.close();
                    mSocket.close();
                } catch (IOException ioe) {
                    mTexte = ioe.getMessage();
                    afficher();
                }
            }
        }).start();
    }

    // ------------------------------------------------------------------------
    // Écriture dans le composant TextView par le thread principal.
    // ------------------------------------------------------------------------
    private void afficher() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tvReponse.setText(mTexte);
            }
        });
    }

    // ------------------------------------------------------------------------
    // Envoi de la requête et réception de la réponse dans un thread secondaire.
    // ------------------------------------------------------------------------
    public void envoyerRequete(View vue) {
        // va chercher la requête dans le composant EditText et l'efface ensuite
        final String requete = etRequete.getText().toString();
        etRequete.setText("");

        new Thread(new Runnable() {
            @Override
            public void run() {
                if (!mConnexionActive) {
                    connecter();
                    // attendre que la connexion soit complétée avant de continuer
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ie) {
                        // improbable
                    }
                }

                // envoi de la requête
                mWriter.println(requete);
                mWriter.flush();
                try {
                    // réception de la réponse
                    mTexte = mReader.readLine();
                } catch (IOException ioe) {
                    mTexte = ioe.getMessage();
                }
                afficher();
            }
        }).start();
    }
}

activity_main.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:padding="50dp">

    <!-- boîte d'entrée de la requête -->
    <EditText
        android:id="@+id/etRequete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:hint="Entrez la requête"/>

    <!-- bouton d'envoi (lance la méthode envoyerRequete) -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:textSize="20sp"
        android:text="Envoyer"
        android:onClick="envoyerRequete" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:text="Réponse"/>

    <!-- espace pour l'affichage de la réponse -->
    <TextView
        android:id="@+id/tvReponse"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:padding="10dp"
        android:background="#eeeeff"/>

</LinearLayout>

AndroidManifest.xml.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.codeandroid.clienttcp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ClientTcp">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>

</manifest>