1. 程式人生 > >使用OkHttp之Websocket實現長連線

使用OkHttp之Websocket實現長連線

最近因為專案中用到了長連線,本來打算使用Socket,無意間發現了Websocket,實現起來很方便。

首先在在build.gradle中新增對Okhttp的支援

compile 'com.squareup.okhttp3:okhttp:3.8.1'
    compile 'com.squareup.okhttp3:mockwebserver:3.8.1'

佈局檔案

<?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" tools:context="com.yinzhendong.websocket.MainActivity">
<ScrollView android:layout_width="match_parent" android:layout_height
="wrap_content">
<LinearLayout android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation
="vertical">
<Button android:id="@+id/start" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="連線" android:textSize="17sp"/> <TextView android:id="@+id/output" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:textSize="16sp"/> </LinearLayout> </ScrollView> </RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button btnStart;
    private TextView tvOutput;
    private WebSocket mSocket;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnStart = (Button) findViewById(R.id.start);
        tvOutput = (TextView) findViewById(R.id.output);
        btnStart.setOnClickListener(this);
    }

    private void start() {
        OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
                .readTimeout(3, TimeUnit.SECONDS)//設定讀取超時時間
                .writeTimeout(3, TimeUnit.SECONDS)//設定寫的超時時間
                .connectTimeout(3, TimeUnit.SECONDS)//設定連線超時時間
                .build();

        Request request = new Request.Builder().url("ws://echo.websocket.org").build();
        EchoWebSocketListener socketListener = new EchoWebSocketListener();
        mOkHttpClient.newWebSocket(request, socketListener);
        mOkHttpClient.dispatcher().executorService().shutdown();
    }

    /**
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start://開始連線
                start();
                break;
        }
    }


    private final class EchoWebSocketListener extends WebSocketListener {

        @Override
        public void onOpen(WebSocket webSocket, Response response) {
            super.onOpen(webSocket, response);
            mSocket = webSocket;
            String openid = "1";
            //連線成功後,傳送登入資訊
            String message = "{\"type\":\"login\",\"user_id\":\""+openid+"\"}";
            mSocket.send(message);
            output("連線成功!");

        }

        @Override
        public void onMessage(WebSocket webSocket, ByteString bytes) {
            super.onMessage(webSocket, bytes);
            output("receive bytes:" + bytes.hex());
        }

        @Override
        public void onMessage(WebSocket webSocket, String text) {
            super.onMessage(webSocket, text);
            output("receive text:" + text);
            //收到伺服器端傳送來的資訊後,每隔25秒傳送一次心跳包
            final String message = "{\"type\":\"heartbeat\",\"user_id\":\"heartbeat\"}";
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    mSocket.send(message);
                }
            },25000);
        }

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

        @Override
        public void onClosing(WebSocket webSocket, int code, String reason) {
            super.onClosing(webSocket, code, reason);
            output("closing:" + reason);
        }

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

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

這裡寫圖片描述