最近公司要做一款內(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