Exemples de WebSocket Android
WebSocket est un protocole qui permet d'ouvrir une session de communication interactive bidirectionnelle entre le client et le serveur. Il fournit des canaux de communication en duplex intégral sur une seule connexion TCP.
Ce protocole définit une API qui établit une connexion "socket" entre un navigateur Web et un serveur. Plutôt que de longues interrogations pour obtenir des mises à jour, par exemple à partir d'une application de scores en direct, vous pouvez utiliser des websockets pour créer une connexion persistante entre le client et le serveur. Ainsi, l'application se met à jour automatiquement chaque fois que de nouvelles mises à jour sont disponibles.
Cela évite la surcharge liée à l'envoi d'une requête HTTP supplémentaire pour vérifier s'il existe de nouvelles mises à jour.
Ainsi, le client et le serveur n'ont qu'à effectuer une poignée de main, et une connexion persistante peut être créée directement entre les deux, et un transfert de données bidirectionnel peut être effectué.

Websocket utilise le même port TCP que HTTP, qui peut contourner la plupart des restrictions de pare-feu. Par défaut, le protocole Websocket utilise le port 80 ; lors de l'exécution au-dessus de TLS, le port 443 est utilisé par défaut. Son identifiant de protocole est ws. Si wss est utilisé pour le chiffrement, l'adresse Web du serveur est une URL, par exemple :
ws://www.example.com/
wss://www.example.com/
Avantages de Websocket
- Moins de surcharge de contrôle : après la création de la connexion, lorsque des données sont échangées entre le serveur et le client, l'en-tête de paquet de données utilisé pour le contrôle du protocole est relativement petit
- Performances en temps réel renforcées : étant donné que le protocole est en duplex intégral, le serveur peut envoyer activement des données au client à tout moment
- Conserver l'état de la connexion : contrairement à HTTP, Websocket doit d'abord créer une connexion, ce qui en fait un protocole avec état, puis une partie des informations d'état peut être omise lors de la communication. La requête HTTP peut devoir contenir des informations d'état dans chaque requête (telles que l'authentification d'identité, etc.)
- Meilleure prise en charge binaire : Websocket définit des trames binaires, qui peuvent gérer le contenu binaire plus facilement que HTTP
- Meilleur effet de compression : par rapport à la compression HTTP, Websocket peut utiliser le contexte du contenu précédent avec un support d'extension approprié, et peut améliorer considérablement le taux de compression lors du transfert de données similaires.
Exemple 1 : Exemple de WebSockets Android
Dans ce didacticiel, vous apprendrez à utiliser les websockets à l'aide d'OkHTTP. L'URL (ws://echo.websocket.org) est utilisée pour configurer les websockets.
Étape 1 : Installez Okhttp
Dans votre build.gradle au niveau de l'application, ajoutez la déclaration d'implémentation suivante :
implementation 'com.squareup.okhttp3:okhttp:3.6.0'
### Étape 2 : Ajouter une autorisation Internet
Dans votre manifeste Android, ajoutez l'autorisation Internet comme suit :
<uses-permission android:name="android.permission.INTERNET"/>
Étape 3 : Conception de la mise en page
Créez une mise en page avec une vue de texte et un bouton. La vue textuelle affichera le résultat du serveur. Le bouton d'autre part initiera la connexion :
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/buttonSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="SEND"
android:layout_marginTop="60dp"
android:textSize="20sp"/>
<TextView
android:id="@+id/textResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/buttonSend"
android:layout_centerHorizontal="true"
android:textSize="18sp"
android:layout_marginTop="40dp"/>
</RelativeLayout>
Étape 4 : Écrire le code
Commencez par créer une méthode d'assistance pour imprimer le résultat du serveur sur une vue de texte. Cela se fait sur le thread de l'interface utilisateur :
private void print(final String message) {
runOnUiThread(new Runnable() {
@Override
public void run() {
textResult.setText(textResult.getText().toString() + "\n" + message);
}
});
}
Créez un EchoWebListener en tant que classe interne. Cette classe étendra le WebSocketListener :
private final class EchoWebSocketListener extends WebSocketListener {
private static final int CLOSE_STATUS = 1000;
@Override
public void onOpen(WebSocket webSocket, Response response) {
webSocket.send("What's up ?");
webSocket.send(ByteString.decodeHex("abcd"));
webSocket.close(CLOSE_STATUS, "Socket Closed !!");
}
@Override
public void onMessage(WebSocket webSocket, String message) {
print("Receive Message: " + message);
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
print("Receive Bytes : " + bytes.hex());
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(CLOSE_STATUS, null);
print("Closing Socket : " + code + " / " + reason);
}
@Override
public void onFailure(WebSocket webSocket, Throwable throwable, Response response) {
print("Error : " + throwable.getMessage());
}
}
La méthode suivante lancera la connexion websocket. La classe OkHTTP Request est instanciée et l'url est passée à la méthode url(). Instanciez ensuite un EchoWebSocketListener et transmettez à la fois l'objet Request et l'instance EchoWebListener à la méthode newWebSocket().
Voici la méthode complète :
private void start() {
Request request = new Request.Builder().url("ws://echo.websocket.org").build();
EchoWebSocketListener listener = new EchoWebSocketListener();
WebSocket webSocket = mClient.newWebSocket(request, listener);
mClient.dispatcher().executorService().shutdown();
}
Voici le code complet :
MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class MainActivity extends AppCompatActivity {
private Button buttonSend;
private TextView textResult;
private OkHttpClient mClient;
private final class EchoWebSocketListener extends WebSocketListener {
private static final int CLOSE_STATUS = 1000;
@Override
public void onOpen(WebSocket webSocket, Response response) {
webSocket.send("What's up ?");
webSocket.send(ByteString.decodeHex("abcd"));
webSocket.close(CLOSE_STATUS, "Socket Closed !!");
}
@Override
public void onMessage(WebSocket webSocket, String message) {
print("Receive Message: " + message);
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
print("Receive Bytes : " + bytes.hex());
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(CLOSE_STATUS, null);
print("Closing Socket : " + code + " / " + reason);
}
@Override
public void onFailure(WebSocket webSocket, Throwable throwable, Response response) {
print("Error : " + throwable.getMessage());
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonSend = (Button) findViewById(R.id.buttonSend);
textResult = (TextView) findViewById(R.id.textResult);
mClient = new OkHttpClient();
buttonSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
start();
}
});
}
private void start() {
Request request = new Request.Builder().url("ws://echo.websocket.org").build();
EchoWebSocketListener listener = new EchoWebSocketListener();
WebSocket webSocket = mClient.newWebSocket(request, listener);
mClient.dispatcher().executorService().shutdown();
}
private void print(final String message) {
runOnUiThread(new Runnable() {
@Override
public void run() {
textResult.setText(textResult.getText().toString() + "\n" + message);
}
});
}
}
Référence
Ci-dessous le lien de téléchargement.
| Non | Lien |
|---|---|
| 1. | [Télécharger] (https://github.com/sayanmanna/WebSocketOkhttp/archive/refs/heads/master.zip) code |
| 2. | Suivre auteur du code |
Exemple 2 : Exemple de Websocket Android Kotlin avec Okhttp
Voici un autre exemple de websocket Android mais cette fois-ci écrit en Kotlin. Il utilise toujours OkHttp comme bibliothèque réseau.
### Étape 1 : Créer un projet
Commencez par créer un projet Android Studio vide.
Étape 2 : Dépendances
Nous allons installer deux bibliothèques OkHttp :
implementation 'com.squareup.okhttp3:okhttp:3.12.6'
implementation 'com.squareup.okhttp3:mockwebserver:3.12.1'
Ajoutez-les dans votre app/build.gradle et synchronisez.
Étape 3 : Conception de la mise en page
Dans la mise en page de votre "MainActivity", ajoutez plusieurs boutons et un texte d'édition comme indiqué ci-dessous :
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/connectBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android : text = " Connect "
app:layout_constraintRight_toLeftOf="@+id/clientSendBtn"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/clientSendBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android : text = " Send from the client "
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/closeConnectionBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="10dp"
android : text = " Client is closed "
app:layout_constraintLeft_toRightOf="@+id/clientSendBtn"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/contentEt"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:background="@color/colorGray"
android:enabled="false"
android:gravity="top"
android:padding="5dp"
android:textColor="@color/colorWhite"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/clientSendBtn"
app:layout_constraintVertical_weight="1" />
</androidx.constraintlayout.widget.ConstraintLayout>
Étape 4 : Créer un écouteur de message
Il s'agira d'une interface avec plusieurs rappels déclenchés en fonction de l'état de la connexion, par exemple en cas de connexion réussie, de fermeture, d'échec, etc. :
MessageListener.kt
interface MessageListener {
fun onConnectSuccess () // successfully connected
fun onConnectFailed () // connection failed
fun onClose () // close
fun onMessage(text: String?)
}
Étape 5 : Créer un gestionnaire de Websocket
Créer un WebSocketManager.kt puis commencez par ajouter les importations suivantes :
import android.util.Log
import okhttp3.*
import okio.ByteString
import java.util.concurrent.TimeUnit
Créez une classe d'objets WebSocketManager avec les champs privés suivants ;
object WebSocketManager {
private val TAG = WebSocketManager::class.java.simpleName
private const val MAX_NUM = 5 // Maximum number of reconnections
private const val MILLIS = 5000 // Reconnection interval, milliseconds
private lateinit var client: OkHttpClient
private lateinit var request: Request
private lateinit var messageListener: MessageListener
private lateinit var mWebSocket: WebSocket
private var isConnect = false
private var connectNum = 0
Puis la fonction init, passez l'url ainsi que le MessageListener. Vous initialisez le client OkHTTP ici :
fun init(url: String, _messageListener: MessageListener) {
client = OkHttpClient.Builder()
.writeTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.build()
request = Request.Builder().url(url).build()
messageListener = _messageListener
}
Créez maintenant une fonction pour vous connecter :
fun connect() {
if (isConnect()) {
Log.i(TAG, "web socket connected")
return
}
client.newWebSocket(request, createListener())
}
Créez également une fonction pour vous reconnecter :
fun reconnect() {
if (connectNum <= MAX_NUM) {
try {
Thread.sleep(MILLIS.toLong())
connect()
connectNum++
} catch (e: InterruptedException) {
e.printStackTrace ()
}
} else {
Log.i(
TAG,
"reconnect over $MAX_NUM,please check url or network"
)
}
}
Nous aurons également des fonctions pour envoyer un message :
fun sendMessage(text: String): Boolean {
return if (!isConnect()) false else mWebSocket.send(text)
}
fun sendMessage(byteString: ByteString): Boolean {
return if (!isConnect()) false else mWebSocket.send(byteString)
}
Et une fonction pour fermer la connexion :
fun close() {
if (isConnect()) {
mWebSocket.cancel()
mWebSocket.close( 1001 , "The client actively closes the connection " )
}
}
Voici le code complet :
WebSocketManager.kt
import android.util.Log
import okhttp3.*
import okio.ByteString
import java.util.concurrent.TimeUnit
object WebSocketManager {
private val TAG = WebSocketManager::class.java.simpleName
private const val MAX_NUM = 5 // Maximum number of reconnections
private const val MILLIS = 5000 // Reconnection interval, milliseconds
private lateinit var client: OkHttpClient
private lateinit var request: Request
private lateinit var messageListener: MessageListener
private lateinit var mWebSocket: WebSocket
private var isConnect = false
private var connectNum = 0
fun init(url: String, _messageListener: MessageListener) {
client = OkHttpClient.Builder()
.writeTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.build()
request = Request.Builder().url(url).build()
messageListener = _messageListener
}
/**
* connect
*/
fun connect() {
if (isConnect()) {
Log.i(TAG, "web socket connected")
return
}
client.newWebSocket(request, createListener())
}
/**
* Reconnection
*/
fun reconnect() {
if (connectNum <= MAX_NUM) {
try {
Thread.sleep(MILLIS.toLong())
connect()
connectNum++
} catch (e: InterruptedException) {
e.printStackTrace ()
}
} else {
Log.i(
TAG,
"reconnect over $MAX_NUM,please check url or network"
)
}
}
/**
* Whether to connect
*/
fun isConnect(): Boolean {
return isConnect
}
/**
* send messages
*
* @param text string
* @return boolean
*/
fun sendMessage(text: String): Boolean {
return if (!isConnect()) false else mWebSocket.send(text)
}
/**
* send messages
*
* @param byteString character set
* @return boolean
*/
fun sendMessage(byteString: ByteString): Boolean {
return if (!isConnect()) false else mWebSocket.send(byteString)
}
/**
* Close connection
*/
fun close() {
if (isConnect()) {
mWebSocket.cancel()
mWebSocket.close( 1001 , "The client actively closes the connection " )
}
}
private fun createListener(): WebSocketListener {
return object : WebSocketListener() {
override fun onOpen(
webSocket: WebSocket,
response: Response
) {
super.onOpen(webSocket, response)
Log.d(TAG, "open:$response")
mWebSocket = webSocket
isConnect = response.code() == 101
if (!isConnect) {
reconnect()
} else {
Log.i(TAG, "connect success.")
messageListener.onConnectSuccess()
}
}
override fun onMessage(webSocket: WebSocket, text: String) {
super.onMessage(webSocket, text)
messageListener.onMessage(text)
}
override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
super.onMessage(webSocket, bytes)
messageListener.onMessage(bytes.base64())
}
override fun onClosing(
webSocket: WebSocket,
code: Int,
reason: String
) {
super.onClosing(webSocket, code, reason)
isConnect = false
messageListener.onClose()
}
override fun onClosed(
webSocket: WebSocket,
code: Int,
reason: String
) {
super.onClosed(webSocket, code, reason)
isConnect = false
messageListener.onClose()
}
override fun onFailure(
webSocket: WebSocket,
t: Throwable,
response: Response?
) {
super.onFailure(webSocket, t, response)
if (response != null) {
Log.i(
TAG,
"connect failed:" + response.message()
)
}
Log.i(
TAG,
"connect failed throwable:" + t.message
)
isConnect = false
messageListener.onConnectFailed()
reconnect()
}
}
}
}
Étape 6 : Écrivez le code MainActivity
Voici le code complet de MainActivity :
MainActivity.kt
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlin.concurrent.thread
class MainActivity : AppCompatActivity(), MessageListener {
private val serverUrl = "ws://192.168.18.145:8086/socketServer/abc"
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate (savedInstanceState)
setContentView(R.layout.activity_main)
WebSocketManager.init(serverUrl, this)
connectBtn.setOnClickListener {
thread {
kotlin.run {
WebSocketManager.connect()
}
}
}
clientSendBtn.setOnClickListener {
if ( WebSocketManager .sendMessage( " Client send " )) {
addText( " Send from the client \n " )
}
}
closeConnectionBtn.setOnClickListener {
WebSocketManager.close()
}
}
override fun onConnectSuccess() {
addText( " Connected successfully \n " )
}
override fun onConnectFailed() {
addText( " Connection failed \n " )
}
override fun onClose() {
addText( " Closed successfully \n " )
}
override fun onMessage(text: String?) {
addText( " Receive message: $text \n " )
}
private fun addText(text: String?) {
runOnUiThread {
contentEt.text.append(text)
}
}
override fun onDestroy() {
super .onDestroy ()
WebSocketManager.close()
}
}
Courir
Copiez le code ou téléchargez-le dans le lien ci-dessous, créez et exécutez.
Référence
Voici les liens de référence :
| Numéro | Lien |
|---|---|
| 1. | Télécharger Exemple |
| 2. | Suivre auteur du code |