//本项目
compile 'com.dhh:websocket:1.3.0'
//由于项目是基于okhttp,RxJava,RxAndroid编写,所以还需加入如下依赖.
//okhttp,RxJava,RxAndroid
compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'io.reactivex:rxjava:1.3.1'
compile 'io.reactivex:rxandroid:1.2.1'
OkHttpClient yourClient = new OkHttpClient();
RxWebSocketUtil.getInstance().setClient(yourClient);
RxWebSocketUtil.getInstance().setShowLog(BuildConfig.DEBUG);
RxWebSocketUtil.getInstance().getWebSocketInfo(url)
.subscribe(new Action1() {
@Override
public void call(WebSocketInfo webSocketInfo) {
mWebSocket = webSocketInfo.getWebSocket();
Log.d("MainActivity", webSocketInfo.getString());
Log.d("MainActivity", "ByteString:" + webSocketInfo.getByteString());
}
});
mWebSocket.send("hello word");
//get StringMsg
RxWebSocketUtil.getInstance().getWebSocketString(url)
.subscribe(new Action1() {
@Override
public void call(String s) {
}
});
// get ByteString
RxWebSocketUtil.getInstance().getWebSocketByteString(url)
.subscribe(new Action1() {
@Override
public void call(ByteString byteString) {
}
});
//get WebSocket
RxWebSocketUtil.getInstance().getWebSocket(url)
.subscribe(new Action1() {
@Override
public void call(WebSocket webSocket) {
}
});
// 带timeout的WebSocket,当在指定时间内没有收到消息,就重连WebSocket.为了适配小米平板.
//小米平板测试的时候,出现网络断连,不发送错误,导致不能重连
RxWebSocketUtil.getInstance().getWebSocketInfo(url,10, TimeUnit.SECONDS)
.subscribe(new Action1() {
@Override
public void call(WebSocketInfo webSocketInfo) {
}
});
//用WebSocket的引用直接发
mWebSocket.send("hello word");
//url 对应的WebSocket已经打开可以这样send,否则报错
RxWebSocketUtil.getInstance().send(url, "hello");
RxWebSocketUtil.getInstance().send(url, ByteString.EMPTY);
//异步发送,若WebSocket已经打开,直接发送,若没有打开,打开一个WebSocket发送完数据,直接关闭.
RxWebSocketUtil.getInstance().asyncSend(url, "hello");
RxWebSocketUtil.getInstance().asyncSend(url, ByteString.EMPTY);
//注意取消订阅,有多种方式,比如 rxlifecycle
mSubscription = RxWebSocketUtil.getInstance().getWebSocketInfo(url)
.subscribe(new Action1<WebSocketInfo>() {
@Override
public void call(WebSocketInfo webSocketInfo) {
mWebSocket = webSocketInfo.getWebSocket();
if (webSocketInfo.isOnOpen()) {
Log.d("MainActivity", " on WebSocket open");
} else {
String string = webSocketInfo.getString();
if (string != null) {
Log.d("MainActivity", string);
textview.setText(Html.fromHtml(string));
}
ByteString byteString = webSocketInfo.getByteString();
if (byteString != null) {
Log.d("MainActivity", "webSocketInfo.getByteString():" + byteString);
}
}
}
});
//注销
if (mSubscription != null) {
mSubscription.unsubscribe();
}
//lifecycle注销,详情看demo
RxWebSocketUtil.getInstance().getWebSocketString(url)
.compose(this.<String>bindOnActivityEvent(ActivityEvent.onDestory))
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
}
});
public class WebSocketInfo {
private WebSocket mWebSocket;
private String mString;
private ByteString mByteString;
private boolean onOpen;
//其他省略
}
private final class WebSocketOnSubscribe implements Observable.OnSubscribe {
private String url;
private WebSocket webSocket;
private WebSocketInfo startInfo, stringInfo, byteStringInfo;
public WebSocketOnSubscribe(String url) {
this.url = url;
startInfo = new WebSocketInfo(true);
stringInfo = new WebSocketInfo();
byteStringInfo = new WebSocketInfo();
}
@Override
public void call(final Subscriber super WebSocketInfo> subscriber) {
if (webSocket != null) {
//降低重连频率
if (!"main".equals(Thread.currentThread().getName())) {
SystemClock.sleep(2000);
}
}
initWebSocket(subscriber);
}
private void initWebSocket(final Subscriber super WebSocketInfo> subscriber) {
webSocket = client.newWebSocket(getRequest(url), new WebSocketListener() {
@Override
public void onOpen(final WebSocket webSocket, Response response) {
if (showLog) {
Log.d("RxWebSocketUtil", url + " --> onOpen");
}
webSocketMap.put(url, webSocket);
AndroidSchedulers.mainThread().createWorker().schedule(new Action0() {
@Override
public void call() {
if (!subscriber.isUnsubscribed()) {
subscriber.onStart();
startInfo.setWebSocket(webSocket);
subscriber.onNext(startInfo);
}
}
});
}
@Override
public void onMessage(WebSocket webSocket, String text) {
if (!subscriber.isUnsubscribed()) {
stringInfo.setWebSocket(webSocket);
stringInfo.setString(text);
subscriber.onNext(stringInfo);
}
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
if (!subscriber.isUnsubscribed()) {
byteStringInfo.setWebSocket(webSocket);
byteStringInfo.setByteString(bytes);
subscriber.onNext(byteStringInfo);
}
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
if (showLog) {
Log.e("RxWebSocketUtil", t.toString() + webSocket.request().url().uri().getPath());
}
if (!subscriber.isUnsubscribed()) {
subscriber.onError(t);
}
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(1000, null);
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
if (showLog) {
Log.d("RxWebSocketUtil", url + " --> onClosed:code= " + code);
}
}
});
subscriber.add(new MainThreadSubscription() {
@Override
protected void onUnsubscribe() {
webSocket.close(3000, "手动关闭");
}
});
}
}
Observable.create(new WebSocketOnSubscribe(url))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
Observable.create(new WebSocketOnSubscribe(url))
//自动重连
.timeout(timeout, timeUnit)
.retry()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
Observable.create(new WebSocketOnSubscribe(url))
//自动重连
.timeout(timeout, timeUnit)
.retry()
//共享
.doOnUnsubscribe(new Action0() {
@Override
public void call() {
observableMap.remove(url);
webSocketMap.remove(url);
if (showLog) {
Log.d("RxWebSocketUtil", "注销");
}
}
})
.doOnNext(new Action1() {
@Override
public void call(WebSocketInfo webSocketInfo) {
if (webSocketInfo.isOnOpen()) {
webSocketMap.put(url, webSocketInfo.getWebSocket());
}
}
})
.share()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
public Observable getWebSocketInfo(final String url, final long timeout, final TimeUnit timeUnit) {
Observable observable = observableMap.get(url);
if (observable == null) {
observable = Observable.create(new WebSocketOnSubscribe(url))
//自动重连
.timeout(timeout, timeUnit)
.retry()
//共享
.doOnUnsubscribe(new Action0() {
@Override
public void call() {
observableMap.remove(url);
webSocketMap.remove(url);
if (showLog) {
Log.d("RxWebSocketUtil", "注销");
}
}
})
.doOnNext(new Action1() {
@Override
public void call(WebSocketInfo webSocketInfo) {
if (webSocketInfo.isOnOpen()) {
webSocketMap.put(url, webSocketInfo.getWebSocket());
}
}
})
.share()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
observableMap.put(url, observable);
} else {
observable = Observable.merge(Observable.just(new WebSocketInfo(webSocketMap.get(url), true)), observable);
}
return observable;
}
//使用merge操作符,将onOpen事件发给订阅者
observable = Observable.merge(Observable.just(new WebSocketInfo(webSocketMap.get(url), true)), observable);
/**
* default timeout: 30 days
*
* 若忽略小米平板,请调用这个方法
*
*/
public Observable getWebSocketInfo(String url) {
return getWebSocketInfo(url, 30, TimeUnit.DAYS);
}
public Observable getWebSocketString(String url) {
return getWebSocketInfo(url)
.map(new Func1() {
@Override
public String call(WebSocketInfo webSocketInfo) {
return webSocketInfo.getString();
}
})
.filter(new Func1() {
@Override
public Boolean call(String s) {
return s != null;
}
});
}
public Observable getWebSocketByteString(String url) {
return getWebSocketInfo(url)
.map(new Func1() {
@Override
public ByteString call(WebSocketInfo webSocketInfo) {
return webSocketInfo.getByteString();
}
})
.filter(new Func1() {
@Override
public Boolean call(ByteString byteString) {
return byteString != null;
}
});
}
public Observable getWebSocket(String url) {
return getWebSocketInfo(url)
.map(new Func1() {
@Override
public WebSocket call(WebSocketInfo webSocketInfo) {
return webSocketInfo.getWebSocket();
}
});
}
/**
* 如果url的WebSocket已经打开,可以直接调用这个发送消息.
*
* @param url
* @param msg
*/
public void send(String url, String msg) {
WebSocket webSocket = webSocketMap.get(url);
if (webSocket != null) {
webSocket.send(msg);
} else {
throw new IllegalStateException("The WebSokcet not open");
}
}
/**
* 如果url的WebSocket已经打开,可以直接调用这个发送消息.
*
* @param url
* @param byteString
*/
public void send(String url, ByteString byteString) {
WebSocket webSocket = webSocketMap.get(url);
if (webSocket != null) {
webSocket.send(byteString);
} else {
throw new IllegalStateException("The WebSokcet not open");
}
}
/**
* 不用关心url 的WebSocket是否打开,可以直接发送
*
* @param url
* @param msg
*/
public void asyncSend(String url, final String msg) {
getWebSocket(url)
.first()
.subscribe(new Action1() {
@Override
public void call(WebSocket webSocket) {
webSocket.send(msg);
}
});
}
/**
* 不用关心url 的WebSocket是否打开,可以直接发送
*
* @param url
* @param byteString
*/
public void asyncSend(String url, final ByteString byteString) {
getWebSocket(url)
.first()
.subscribe(new Action1() {
@Override
public void call(WebSocket webSocket) {
webSocket.send(byteString);
}
});
}