Zum Hauptinhalt springen

Android WebSocket-Beispiele

WebSocket ist ein Protokoll, das es ermöglicht, eine bidirektionale interaktive Kommunikationssitzung zwischen dem Client und dem Server zu eröffnen. Es bietet Vollduplex-Kommunikationskanäle über eine einzige TCP-Verbindung.

Dieses Protokoll definiert eine API, die eine „Socket“-Verbindung zwischen einem Webbrowser und einem Server herstellt. Anstatt lange abzufragen, um Updates beispielsweise von einer Livescore-App zu erhalten, können Sie Websockets verwenden, um eine dauerhafte Verbindung zwischen dem Client und dem Server herzustellen. Daher aktualisiert sich die App automatisch, sobald neuere Updates verfügbar sind.

Dadurch wird der Aufwand vermieden, eine zusätzliche HTTP-Anfrage zu senden, um zu prüfen, ob neuere Updates verfügbar sind.

Somit müssen Client und Server nur einen Handshake durchführen, und es kann direkt eine dauerhafte Verbindung zwischen beiden hergestellt und eine bidirektionale Datenübertragung durchgeführt werden.

![Websocket](https://camo.githubusercontent.com/a985b5f6ece41fbd5ebcf5e126ac275cc0aab8f1d92c09696421f4c40e685f8a/68747470733a2f2f696d672d626c6f672e6373646e 696d672e636e2f32303139303130373130353635383936322e706e673f782d6f73732d70726f636573733d696d6167652f77617465726d61726b2c74797 0655f5a6d46755a33706f5a57356e6147567064476b2c736861646f775f31302c746578745f6148523063484d364c7939696247396e4c6d4e7a5a473475 626d56304c325a7662576c755833706f64513d3d2c73697a655f31362c636f6c6f725f4646464646462c745f3730)

Websocket verwendet denselben TCP-Port wie HTTP, wodurch die meisten Firewall-Einschränkungen umgangen werden können. Standardmäßig verwendet das Websocket-Protokoll Port 80; Bei der Ausführung über TLS wird standardmäßig Port 443 verwendet. Seine Protokollkennung ist ws. Wenn wss zur Verschlüsselung verwendet wird, ist die Server-Webadresse eine URL, wie zum Beispiel:

ws://www.example.com/
wss://www.example.com/

Vorteile von Websocket

  • Geringerer Kontrollaufwand: Nach dem Herstellen der Verbindung ist der für die Protokollsteuerung verwendete Datenpaket-Header beim Datenaustausch zwischen Server und Client relativ klein
  • Stärkere Echtzeitleistung: Da das Protokoll Vollduplex ist, kann der Server jederzeit aktiv Daten an den Client senden
  • Behalten Sie den Verbindungsstatus bei: Im Gegensatz zu HTTP muss Websocket zuerst eine Verbindung erstellen, was es zu einem zustandsbehafteten Protokoll macht, und dann kann ein Teil der Statusinformationen bei der Kommunikation weggelassen werden. Die HTTP-Anfrage muss möglicherweise in jeder Anfrage Statusinformationen enthalten (z. B. Identitätsauthentifizierung usw.).
  • Bessere Binärunterstützung: Websocket definiert binäre Frames, die binäre Inhalte einfacher verarbeiten können als HTTP
  • Besserer Komprimierungseffekt: Im Vergleich zur HTTP-Komprimierung kann Websocket den Kontext des vorherigen Inhalts mit ordnungsgemäßer Erweiterungsunterstützung verwenden und die Komprimierungsrate bei der Übertragung ähnlicher Daten erheblich verbessern.

Beispiel 1: Android WebSockets-Beispiel

In diesem Tutorial erfahren Sie, wie Sie WebSockets mit OkHTTP verwenden. Die URL (ws://echo.websocket.org) wird zum Einrichten von Websockets verwendet.

Schritt 1: Okhttp installieren

Fügen Sie in Ihrem build.gradle auf App-Ebene die folgende Implementierungsanweisung hinzu:

implementation 'com.squareup.okhttp3:okhttp:3.6.0'

Schritt 2: Internetberechtigung hinzufügen

Fügen Sie in Ihrem Android-Manifest die Internetberechtigung wie folgt hinzu:

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

Schritt 3: Layout entwerfen

Erstellen Sie ein Layout mit einer Textansicht und einer Schaltfläche. Die Textansicht zeigt das Ergebnis vom Server. Der Button hingegen leitet die Verbindung ein:

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>

Schritt 4: Code schreiben

Erstellen Sie zunächst eine Hilfsmethode, um das Ergebnis vom Server in einer Textansicht zu drucken. Dies geschieht im UI-Thread:

    private void print(final String message) {
runOnUiThread(new Runnable() {
@Override
public void run() {
textResult.setText(textResult.getText().toString() + "\n" + message);
}
});
}

Erstellen Sie einen EchoWebListener als innere Klasse. Diese Klasse erweitert den 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());
}
}

Die folgende Methode initiiert die WebSocket-Verbindung. Die OkHTTP-Request-Klasse wird instanziiert und die URL wird an die Methode „url()“ übergeben. Instanziieren Sie dann einen EchoWebSocketListener und übergeben Sie sowohl das Request-Objekt als auch die EchoWebListener-Instanz an die Methode „newWebSocket()“.

Hier ist die vollständige Methode:

    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();
}

Hier ist der vollständige Code:

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);
}
});
}
}

Referenz

Unten finden Sie den Download-Link.

Nein.Link
1.Herunterladen Code
2.Folgen Code-Autor

Beispiel 2: Kotlin Android Websocket-Beispiel mit Okhttp

Hier ist ein weiteres Android-Websocket-Beispiel, dieses Mal jedoch in Kotlin geschrieben. Es verwendet weiterhin OkHttp als Netzwerkbibliothek.

Schritt 1: Projekt erstellen

Erstellen Sie zunächst ein leeres „Android Studio“-Projekt.

Schritt 2: Abhängigkeiten

Wir werden zwei OkHttp-Bibliotheken installieren:

    implementation 'com.squareup.okhttp3:okhttp:3.12.6'
implementation 'com.squareup.okhttp3:mockwebserver:3.12.1'

Fügen Sie diese in Ihre „app/build.gradle“ ein und synchronisieren Sie sie.

Schritt 3: Layout entwerfen

Fügen Sie im Layout Ihrer „MainActivity“ mehrere Schaltflächen und einen Bearbeitungstext hinzu, wie unten gezeigt:

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>

Schritt 4: Erstellen Sie einen Nachrichten-Listener

Dabei handelt es sich um eine Schnittstelle mit mehreren Rückrufen, die abhängig vom Status der Verbindung ausgelöst werden, z. B. bei erfolgreicher Verbindung, Schließung, Fehler usw.:

MessageListener.kt

interface MessageListener {
fun onConnectSuccess () // successfully connected
fun onConnectFailed () // connection failed
fun onClose () // close
fun onMessage(text: String?)
}

Schritt 5: Erstellen Sie einen Websocket-Manager

Erstellen Sie einen „WebSocketM“.anager.kt` und beginnen Sie dann mit dem Hinzufügen der folgenden Importe:

import  android.util.Log
import okhttp3.*
import okio.ByteString
import java.util.concurrent.TimeUnit

Erstellen Sie eine „WebSocketManager“-Objektklasse mit den folgenden privaten Feldern;

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

Dann übergibt die Init-Funktion die URL sowie den MessageListener. Hier initialisieren Sie den „OkHTTP“-Client:

    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
}

Erstellen Sie nun eine Funktion zum Verbinden:

    fun connect() {
if (isConnect()) {
Log.i(TAG, "web socket connected")
return
}
client.newWebSocket(request, createListener())
}

Erstellen Sie außerdem eine Funktion zum erneuten Verbinden:

    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"
)
}
}

Wir werden auch Funktionen zum Senden einer Nachricht haben:

    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)
}

Und eine Funktion zum Schließen der Verbindung:

    fun close() {
if (isConnect()) {
mWebSocket.cancel()
mWebSocket.close( 1001 , "The client actively closes the connection " )
}
}

Hier ist der vollständige Code:

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()
}
}
}
}

Schritt 6: MainActivity-Code schreiben

Hier ist der vollständige Code für die „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()
}
}

Laufen

Kopieren Sie den Code oder laden Sie ihn über den untenstehenden Link herunter, erstellen Sie ihn und führen Sie ihn aus.

Referenz

Hier sind die Referenzlinks:

NummerLink
1.Herunterladen Beispiel
2.Folgen Code-Autor