呃那个,最近公司项目又用到了websocket,呃,其实,这个东西我也不是很懂,目前也是从网上学习和抄写了,不过,也是自己整理了一下,不能算抄袭,自我觉得,顶多算是借鉴,哈哈,自我安慰的一种体现哈,下面,我直接上正题,不啰嗦
1、首先,我们要想将okhttp3引进项目中取,你可以从网上找jar包引入,呃,这里不提供,我这里提供从android studio 里面的buile.gradle里面,Eclipse我不怎么用了意思很相近,如果你用Eclipse,那自己琢磨吧
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
这个时候已经将okhttp引入项目了,很方便吧,呃,这个,如果你的studio 版本是3.1以上,恩,对,应该是,这个版本以上,这里用implementation ,如果是以下,可能就需要用
compile'com.squareup.okhttp3:okhttp:3.9.0'
这两个都是引入的哈,因为工具版本不一样,对了权限别忘记了
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
2、这个时候,就加我们的wsmananger,用于连接与交互
public class WsManager implements IWsManager { private final static int RECONNECT_INTERVAL = 10 * 1000; //重连自增步长 private final static long RECONNECT_MAX_TIME = 120 * 1000; //最大重连间隔 private Context mContext; private String wsUrl; private WebSocket mWebSocket; private OkHttpClient mOkHttpClient; private Request mRequest; private int mCurrentStatus = WsStatus.DISCONNECTED; //websocket连接状态 private boolean isNeedReconnect; //是否需要断线自动重连 private boolean isManualClose = false; //是否为手动关闭websocket连接 private Lock mLock; private Handler wsMainHandler = new Handler(Looper.getMainLooper()); private int reconnectCount = 0; //重连次数 private Runnable reconnectRunnable = new Runnable() { @Override public void run() { Log.e("websocket", "服务器重连接中..."); buildConnect(); } }; private static VideoPresenter videoPresenter = new VideoPresenter(); private WebSocketListener mWebSocketListener = new WebSocketListener() { @Override public void onOpen(WebSocket webSocket, final Response response) { mWebSocket = webSocket; setCurrentStatus(WsStatus.CONNECTED); connected(); if (Looper.myLooper() != Looper.getMainLooper()) { JSONObject jo = new JSONObject(); jo.put("act", 1); jo.put("projectname", App.getConfig().getProjectname()); jo.put("mac", App.getConfig().getMac()); jo.put("lightid", App.getConfig().getLightid()); jo.put("version", App.getConfig().getVcode()); // jo.put("act", 1); // jo.put("data", App.getConfig()); sendMessage(jo.toJSONString()); } else { Log.e("websocket", "服务器连接成功"); } } @Override public void onMessage(WebSocket webSocket, final ByteString bytes) { if (Looper.myLooper() != Looper.getMainLooper()) { wsMainHandler.post(new Runnable() { @Override public void run() { Log.e("websocket", "WsManager-----onMessage"); } }); } else { Log.e("websocket", "WsManager-----onMessage"); } } @Override public void onMessage(WebSocket webSocket, final String text) { if (Looper.myLooper() != Looper.getMainLooper()) { wsMainHandler.post(new Runnable() { @Override public void run() { Log.e("websocket", "WsManager-----onMessage"); } }); } else { Log.e("websocket", "WsManager-----onMessage"); } } @Override public void onClosing(WebSocket webSocket, final int code, final String reason) { if (Looper.myLooper() != Looper.getMainLooper()) { wsMainHandler.post(new Runnable() { @Override public void run() { Log.e("websocket", "服务器连接关闭中"); } }); } else { Log.e("websocket", "服务器连接关闭中"); } } @Override public void onClosed(WebSocket webSocket, final int code, final String reason) { if (Looper.myLooper() != Looper.getMainLooper()) { wsMainHandler.post(new Runnable() { @Override public void run() { Log.e("websocket", "服务器连接已关闭"); } }); } else { Log.e("websocket", "服务器连接已关闭"); } } @Override public void onFailure(WebSocket webSocket, final Throwable t, final Response response) { try { tryReconnect(); Log.e("liusehngjei", "[走的链接失败这里!!!!!!!!!!!!!!!!]"); if (Looper.myLooper() != Looper.getMainLooper()) { wsMainHandler.post(new Runnable() { @Override public void run() { Log.e("websocket", "服务器连接失败"); } }); } else { Log.e("websocket", "服务器连接失败"); } } catch (Exception e) { e.printStackTrace(); } } }; public WsManager(Builder builder) { mContext = builder.mContext; wsUrl = builder.wsUrl; isNeedReconnect = builder.needReconnect; mOkHttpClient = builder.mOkHttpClient; this.mLock = new ReentrantLock(); } private void initWebSocket() { if (mOkHttpClient == null) { mOkHttpClient = new OkHttpClient.Builder() .retryOnConnectionFailure(true) .build(); } if (mRequest == null) { mRequest = new Request.Builder() .url(wsUrl) .build(); } mOkHttpClient.dispatcher().cancelAll(); try { mLock.lockInterruptibly(); try { mOkHttpClient.newWebSocket(mRequest, mWebSocketListener); } finally { mLock.unlock(); } } catch (InterruptedException e) { } } @Override public WebSocket getWebSocket() { return mWebSocket; } @Override public synchronized boolean isWsConnected() { return mCurrentStatus == WsStatus.CONNECTED; } @Override public synchronized int getCurrentStatus() { return mCurrentStatus; } @Override public synchronized void setCurrentStatus(int currentStatus) { this.mCurrentStatus = currentStatus; } @Override public void startConnect() { isManualClose = false; buildConnect(); } @Override public void stopConnect() { isManualClose = true; disconnect(); } private void tryReconnect() { if (!isNeedReconnect | isManualClose) { return; } Log.e("liusehngjei", "reconnectCount2222222[" + reconnectCount + "]"); if (!isNetworkConnected(mContext)) { setCurrentStatus(WsStatus.DISCONNECTED); Log.e("liusehngjei", "[请您检查网络,未连接]"); // return; } setCurrentStatus(WsStatus.RECONNECT); Log.e("liusehngjei", "reconnectCount11111111[" + reconnectCount + "]"); long delay = reconnectCount * RECONNECT_INTERVAL; // wsMainHandler.postDelayed(reconnectRunnable, delay > RECONNECT_MAX_TIME ? RECONNECT_MAX_TIME : delay); wsMainHandler.postDelayed(reconnectRunnable, 10000); Log.e("liusehngjei", "reconnectCount[" + reconnectCount + "]"); reconnectCount++; } private void cancelReconnect() { wsMainHandler.removeCallbacks(reconnectRunnable); reconnectCount = 0; } private void connected() { cancelReconnect(); } private void disconnect() { if (mCurrentStatus == WsStatus.DISCONNECTED) { return; } cancelReconnect(); if (mOkHttpClient != null) { mOkHttpClient.dispatcher().cancelAll(); } if (mWebSocket != null) { boolean isClosed = mWebSocket.close(WsStatus.CODE.NORMAL_CLOSE, WsStatus.TIP.NORMAL_CLOSE); //非正常关闭连接 if (!isClosed) { Log.e("websocket", "服务器连接失败"); } } setCurrentStatus(WsStatus.DISCONNECTED); } private synchronized void buildConnect() { if (!isNetworkConnected(mContext)) { setCurrentStatus(WsStatus.DISCONNECTED); // return; } switch (getCurrentStatus()) { case WsStatus.CONNECTED: case WsStatus.CONNECTING: break; default: setCurrentStatus(WsStatus.CONNECTING); initWebSocket(); } } //发送消息 @Override public boolean sendMessage(String msg) { return send(msg); } @Override public boolean sendMessage(ByteString byteString) { return send(byteString); } private boolean send(Object msg) { boolean isSend = false; if (mWebSocket != null && mCurrentStatus == WsStatus.CONNECTED) { if (msg instanceof String) { isSend = mWebSocket.send((String) msg); } else if (msg instanceof ByteString) { isSend = mWebSocket.send((ByteString) msg); } //发送消息失败,尝试重连 if (!isSend) { tryReconnect(); } } return isSend; } //检查网络是否连接 private boolean isNetworkConnected(Context context) { if (context != null) { ConnectivityManager mConnectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); @SuppressLint("MissingPermission") NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); if (mNetworkInfo != null) { return mNetworkInfo.isAvailable(); } } return false; } public static final class Builder { private Context mContext; private String wsUrl; private boolean needReconnect = true; private OkHttpClient mOkHttpClient; public Builder(Context val) { mContext = val; } public Builder wsUrl(String val) { wsUrl = val; return this; } public Builder client(OkHttpClient val) { mOkHttpClient = val; return this; } public Builder needReconnect(boolean val) { needReconnect = val; return this; } public WsManager build() { return new WsManager(this); } } }
3、里面还有一个接口需要
interface IWsManager { WebSocket getWebSocket(); void startConnect(); void stopConnect(); boolean isWsConnected(); int getCurrentStatus(); void setCurrentStatus(int currentStatus); boolean sendMessage(String msg); boolean sendMessage(ByteString byteString); }
4、还有一个工具类,记录状态
public class WsStatus { public final static int CONNECTED = 1; public final static int CONNECTING = 0; public final static int RECONNECT = 2; public final static int DISCONNECTED = -1; class CODE { public final static int NORMAL_CLOSE = 1000; public final static int ABNORMAL_CLOSE = 1001; } class TIP { public final static String NORMAL_CLOSE = "normal close"; public final static String ABNORMAL_CLOSE = "abnormal close"; } }
5、下面就是调用链接了,在调用界面首先要实例化WsMnanger
WsManager wsManager = new WsManager.Builder(getBaseContext()).client( new OkHttpClient().newBuilder() .pingInterval(15, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build()) .needReconnect(true) .wsUrl("ws://192.168.3.145:80/MayaCloud_Lightpush//ws") .build();6、连接可以直接使用
wsManager.startConnect();
7、停止链接使用下面方法
if (wsManager != null) { wsManager.stopConnect(); wsManager = null; }
8、在onDestory()里面要记得停止链接
@Override protected void onDestroy() { if (wsManager != null) { wsManager.stopConnect(); wsManager = null; } }
9、哦了,就这么简单,里面做了断线重连机制,我设定的是,当断线后,十秒后重连,一般这个时间都能接受,时间太短,会导致卡死,所以,十秒应该还是能接受的,
10、结束语:如果大神看到,有不足的地方,还望大神批评指正,小弟一定更改,力求做到更好,今天仅在此记录此功能,需要demo的请链接下方地址,由于小弟没有积分了,特希望各位能不计较这点小分,此demo是一个聊天的功能,默认链接的地址是测试服务器,跑通后可以直接使用,具体不懂的,可以在里面自己查看