呃那个,最近公司项目又用到了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'
这两个都是引入的哈,因为工具版本不一样,对了权限别忘记了
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是一个聊天的功能,默认链接的地址是测试服务器,跑通后可以直接使用,具体不懂的,可以在里面自己查看
资源Demo