Android之okhttp實現socket通訊(非原創)

文章大綱

一、okhttp基礎介紹
二、socket通訊代碼實戰
三、項目源碼下載
四、參考文章

 

一、okhttp基礎介紹

https://www.jianshu.com/p/e3291b7808e7

二、socket通訊代碼實戰

1. 添加依賴和權限

app的build.gradle下添加okhttp依賴

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

AndroidManifest.xml文件添加網絡權限

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

2. 添加布局文件

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

    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="start"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/start2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="start2"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/text2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

3. MainActivity邏輯實現

package aidl_customer.com.wj.http_socket;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

/**
 * okhttp是3.5以後才添加對WebSocket的支持
 */
public class MainActivity extends AppCompatActivity {

    private Button start;
    private TextView text;

    private Button start2;
    private TextView text2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        start = (Button) findViewById(R.id.start);
        text = (TextView) findViewById(R.id.text);

        start2 = (Button) findViewById(R.id.start2);
        text2 = (TextView) findViewById(R.id.text2);

        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                connect();
            }
        });

        start2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                OkHttpClient  client = new OkHttpClient.Builder()
                        .readTimeout(3, TimeUnit.SECONDS)
                        .build();


                Request request = new Request.Builder()
                        .url("ws://echo.websocket.org")
                        .build();
                WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
                    @Override
                    public void onOpen(WebSocket webSocket, Response response) {
                        super.onOpen(webSocket, response);
                    }

                    @Override
                    public void onMessage(WebSocket webSocket, String text) {
                        super.onMessage(webSocket, text);
                    }

                    @Override
                    public void onMessage(WebSocket webSocket, ByteString bytes) {
                        super.onMessage(webSocket, bytes);
                    }

                    @Override
                    public void onClosing(WebSocket webSocket, int code, String reason) {
                        super.onClosing(webSocket, code, reason);
                    }

                    @Override
                    public void onClosed(WebSocket webSocket, int code, String reason) {
                        super.onClosed(webSocket, code, reason);
                    }

                    @Override
                    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                        super.onFailure(webSocket, t, response);
                    }
                });
            }
        });
    }

    /**
     *WebSocket官網就提供了相應url可以測試
     */
    private void connect() {

        //建立連接
        EchoWebSocketListener listener = new EchoWebSocketListener();
        Request request = new Request.Builder()
                .url("ws://echo.websocket.org")
                .build();
        OkHttpClient client = new OkHttpClient();
        client.newWebSocket(request, listener);

        client.dispatcher().executorService().shutdown();
    }

    /**
     * 重寫了WebSocketListener中的幾個方法,這幾個方法很好理解,是用來異步回調的,
     * 這裏簡單說一下:onOpen當WebSocket和遠程建立連接時回調;兩個onMessage就是接收到消息時回調,
     * 只是消息內容的類型不同;onClosing是當遠程端暗示沒有數據交互時回調(即此時準備關閉,但連接還沒有關閉);
     * onClosed就是當連接已經釋放的時候被回調;onFailure當然是失敗時被回調(包括連接失敗,發送失敗等)。
     *
     * send用來發送消息;close用來關閉連接
     */
    private final class EchoWebSocketListener extends WebSocketListener {

        @Override
        public void onOpen(WebSocket webSocket, Response response) {

            webSocket.send("hello world");
            webSocket.send("welcome");
            webSocket.send(ByteString.decodeHex("adef"));
            webSocket.close(1000, "再見");
        }

        @Override
        public void onMessage(WebSocket webSocket, String text) {
            output("onMessage: " + text);
        }

        @Override
        public void onMessage(WebSocket webSocket, ByteString bytes) {
            output("onMessage byteString: " + bytes);
        }

        @Override
        public void onClosing(WebSocket webSocket, int code, String reason) {
            webSocket.close(1000, null);
            output("onClosing: " + code + "/" + reason);
        }

        @Override
        public void onClosed(WebSocket webSocket, int code, String reason) {
            output("onClosed: " + code + "/" + reason);
        }

        @Override
        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            output("onFailure: " + t.getMessage());
        }
    }

    private void output(final String content) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                text.setText(text.getText().toString() + content + "\n");
            }
        });
    }
}

溫馨提示:
(1)EchoWebSocketListener繼承OkHttp中的抽象類WebSocketListener,重寫了幾個方法,是用來異步回調的,這裏簡單說一下:onOpen當WebSocket和遠程建立連接時回調;兩個onMessage就是接收到消息時回調,只是消息內容的類型不同;onClosing是當遠程端暗示沒有數據交互時回調(即此時準備關閉,但連接還沒有關閉);onClosed就是當連接已經釋放的時候被回調;onFailure當然是失敗時被回調(包括連接失敗,發送失敗等)。
(2)send用來發送消息;close用來關閉連接
(3)WebSocket官網就提供了相應url可以測試,測試地址爲:ws://echo.websocket.org
(4)關閉連接方式,OkHttp提供兩個方法來關閉連接:
  1)close webSocket.close(0, “bye”);請求服務器優雅地關閉連接然後等待確認。在關閉之前,所有已經在隊列中的消息將被傳送完畢。 既然涉及到交互,那麼socket可能不會立即關閉。如果初始化和關閉連接是和Activity的生命週期綁定的(比如onPause/onResume),有一些消息可能是在close被調用之後接收到,所以這需要小心去處理。
  2)cancel;cancel更加殘忍:它會丟棄所有已經在隊列中的消息然後殘忍地關閉socket。這樣也有優點:不必等待家政(housekeeping)和已在隊列中消息的傳送。然而,選擇cancel還是close取決於使用場景。

4. 項目運行與訪問

安裝apk後,運行主頁面如下:

 

點擊START按鈕,出現以下結果

 

三、項目源碼下載

鏈接:https://pan.baidu.com/s/1t8OmZy8WLZr2aKI8S2XcwQ
提取碼:jwzi

四、參考文章

    1. https://blog.csdn.net/xlh1191860939/article/details/75452342/
    2. https://blog.csdn.net/xlh1191860939/article/details/75452513
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章