WebSocket 長(zhǎng)鏈接

最近公司要做一款內(nèi)部使用的工具類app,方便銷售部門打電話(其實(shí)就是在后臺(tái)有好多用戶數(shù)據(jù),之前銷售部門同事?lián)艽螂娫?,需要自己從銷售后臺(tái)查看用戶手機(jī)號(hào)等信息,然后自己拿自己手機(jī)撥號(hào),然后打出去?,F(xiàn)在想實(shí)現(xiàn)銷售的同事,點(diǎn)擊銷售后臺(tái)的按鈕,自己的手機(jī)直接撥號(hào)的功能)。為此,開(kāi)始著手思考,怎么實(shí)現(xiàn)銷售后臺(tái)點(diǎn)擊按鈕,手機(jī)app端能收到點(diǎn)擊按鈕的監(jiān)聽(tīng)。

首先,后臺(tái)提供一個(gè)接口,在服務(wù)器端不斷的調(diào)用接口以監(jiān)聽(tīng)后臺(tái)按鈕的點(diǎn)擊事件以及收到后臺(tái)傳過(guò)來(lái)的信息。這樣太繁瑣,而且不斷的調(diào)接口,比較耗性能,肯定不合適。然后想到建立一個(gè)長(zhǎng)連接,在app端寫(xiě)一個(gè)長(zhǎng)連接(用Socket或者WebSocket),并加入心跳檢測(cè),定期的去檢測(cè)長(zhǎng)連接是否連接正常,如果連接中斷,執(zhí)行重新連接。于是乎自己寫(xiě)了個(gè)Socket的長(zhǎng)連接,加入了心跳檢測(cè)。但是等和后臺(tái)聯(lián)調(diào)的時(shí),后臺(tái)的同事提議用WebSocket長(zhǎng)連接,這樣也許能方便些。于是自己又不情愿的把Socket長(zhǎng)連接換成WebSocket方式實(shí)現(xiàn)的長(zhǎng)連接。還好我網(wǎng)絡(luò)請(qǐng)求用的鴻洋大神的OkttpUtils,里面提供了一個(gè)關(guān)于WebSocket連接的回調(diào)。最終實(shí)現(xiàn)了這一功能。好了廢話不多說(shuō),上代碼了。。。。

1.首先需要在AndroidManifest.xml中開(kāi)啟一個(gè)服務(wù):

<service android:name=".service.BackService" />

2.寫(xiě)一個(gè)類BackService繼承Service:

public class BackService extends Service{
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

3.在BackService的onCreate()方法中開(kāi)啟一個(gè)線程:

   @Override
    public void onCreate() {
        super.onCreate();
        new InitSocketThread().start();
    }

class InitSocketThread extends Thread {
        @Override
        public void run() {
            super.run();
            try {
                initSocket();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 心跳檢測(cè)時(shí)間
     */
    private static final long HEART_BEAT_RATE = 15 * 1000;//每隔15秒進(jìn)行一次對(duì)長(zhǎng)連接的心跳檢測(cè)
    private static final String WEBSOCKET_HOST_AND_PORT = "ws://xxx:9501";//可替換為自己的主機(jī)名和端口號(hào)
    private WebSocket mWebSocket;
    // 初始化socket
    private void initSocket() throws UnknownHostException, IOException {
        OkHttpClient client = new OkHttpClient.Builder().readTimeout(0, TimeUnit.MILLISECONDS).build();
        Request request = new Request.Builder().url(WEBSOCKET_HOST_AND_PORT).build();
        client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {//開(kāi)啟長(zhǎng)連接成功的回調(diào)
                super.onOpen(webSocket, response);
                mWebSocket = webSocket;
            }
 
            @Override
            public void onMessage(WebSocket webSocket, String text) {//接收消息的回調(diào)
                super.onMessage(webSocket, text);
                //收到服務(wù)器端傳過(guò)來(lái)的消息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, @Nullable Response response) {//長(zhǎng)連接連接失敗的回調(diào)
                super.onFailure(webSocket, t, response);
            }
        });
        client.dispatcher().executorService().shutdown();
        mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//開(kāi)啟心跳檢測(cè)
    }

4.開(kāi)啟心跳檢測(cè):

private long sendTime = 0L;
// 發(fā)送心跳包
    private Handler mHandler = new Handler();
    private Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
                boolean isSuccess = mWebSocket.send("");//發(fā)送一個(gè)空消息給服務(wù)器,通過(guò)發(fā)送消息的成功失敗來(lái)判斷長(zhǎng)連接的連接狀態(tài)
                if (!isSuccess) {//長(zhǎng)連接已斷開(kāi)
                    mHandler.removeCallbacks(heartBeatRunnable);
                    mWebSocket.cancel();//取消掉以前的長(zhǎng)連接
                    new InitSocketThread().start();//創(chuàng)建一個(gè)新的連接
                } else {//長(zhǎng)連接處于連接狀態(tài)
                    
                }
 
                sendTime = System.currentTimeMillis();
            }
            mHandler.postDelayed(this, HEART_BEAT_RATE);//每隔一定的時(shí)間,對(duì)長(zhǎng)連接進(jìn)行一次心跳檢測(cè)
        }
    };

5.當(dāng)BackService關(guān)閉時(shí),關(guān)閉掉長(zhǎng)連接:

@Override
    public void onDestroy() {
        super.onDestroy();
        if (mWebSocket != null) {
            mWebSocket.close(1000, null);
        }

轉(zhuǎn)發(fā):
原文:https://blog.csdn.net/u010257931/article/details/79694911

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容