自从使用过 融云 之后,我就很少写自己写长连接了,毕竟自己实现的长连接和 融云,腾讯云,环信等等这些三方SDK比较起来,还是太幼稚,最重要的是好似每一种类型的APP都会要求实现IM功能。
自从16年使用WebSocket写一个简单的直播聊天场景,后来因为要交互一些复杂的场景实现 例如送礼物,发私信,等等。自己实现的IM显然不成熟,基于xxml 制定的传输协议,也不足与应付各种实现。然后采用了融云,三方SDK这个东西,用过一次真的容易上瘾。让平常需要一周,半个月的开发工期简简单单的一两个小时就完美实现。 一个爽字不足以说明当时的顺滑~
但是有时候也受公司商务和领导的限制,所以知道今年这种顺滑的感觉彻底打破,我们在已经接入了腾讯的SDK之后,碰到了需要使用长连接场景的功能,几个领导一碰,我们采用WebSocket !!! 当我得知这个噩耗时候,也尝试挣扎一下,理论上完全可以使用腾讯云提供的长连接方式实现,但是没用,人微言轻。所以就再次拾起了WebSocket 功能。这里记录下使用
步骤一:导包
// WebSocket
api "org.java-websocket:Java-WebSocket:1.4.0"
步骤二:基础封装
WeSoketUtil:封装连接地址, 心跳包时间间隔
public class WeSoketUtil {
public static final String ws = "";//websocket测试地址
public static final long HEART_BEAT_RATE = 30 * 1000;//每隔30秒进行一次对长连接的心跳检测
}
JWebSocketClient: 继承 WebSocketClient 设置 连接,发送,收到消息,出错,关闭的回调
public class JWebSocketClient extends WebSocketClient {
public JWebSocketClient(URI serverUri) {
super(serverUri, new Draft_6455());
}
@Override
public void onOpen(ServerHandshake handshakedata) {
Log.e("JWebSocketClient", "onOpen()");
}
@Override
public void onMessage(String message) {
Log.e("JWebSocketClient", "onMessage()");
}
@Override
public void onClose(int code, String reason, boolean remote) {
Log.e("JWebSocketClient", "onClose()"+reason);
}
@Override
public void onError(Exception ex) {
Log.e("JWebSocketClient", "onError()"+ex.toString());
}
}
JWebSocketClientService :主要功能,设置保活,设置心跳,设置重连
public class JWebSocketClientService extends Service {
public JWebSocketClient client;
private JWebSocketClientBinder mBinder = new JWebSocketClientBinder();
private final static int GRAY_SERVICE_ID = 1001;
//灰色保活
public static class GrayInnerService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
//用于Activity和service通讯
public class JWebSocketClientBinder extends Binder {
public JWebSocketClientService getService() {
return JWebSocketClientService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//初始化websocket
initSocketClient();
mHandler.postDelayed(heartBeatRunnable, WeSoketUtil.HEART_BEAT_RATE);//开启心跳检测
return START_STICKY;
}
@Override
public void onDestroy() {
closeConnect();
super.onDestroy();
}
public JWebSocketClientService() {
}
/**
* 初始化websocket连接
*/
private void initSocketClient() {
URI uri = URI.create(WeSoketUtil.ws);
client = new JWebSocketClient(uri) {
@Override
public void onMessage(String message) {
EventBus.getDefault().post(new SocketMessage(1, message));
}
@Override
public void onOpen(ServerHandshake handshakedata) {
super.onOpen(handshakedata);
EventBus.getDefault().post(new SocketMessage(0, ""));
}
};
connect();
}
/**
* 连接websocket
*/
private void connect() {
new Thread() {
@Override
public void run() {
try {
//connectBlocking多出一个等待操作,会先连接再发送,否则未连接发送会报错
client.connectBlocking();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
/**
* 发送消息
*
* @param msg
*/
public void sendMsg(String msg) {
if (null != client) {
Logger.e("发送的消息:" + msg);
client.send(msg);
}
}
/**
* 断开连接
*/
private void closeConnect() {
try {
if (null != client) {
client.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
client = null;
mHandler.removeCallbacksAndMessages(null);
}
}
private Handler mHandler = new Handler();
private Runnable heartBeatRunnable = new Runnable() {
@Override
public void run() {
Log.e("JWebSocketClientService", "心跳包检测websocket连接状态");
if (client != null) {
if (client.isClosed()) {
reconnectWs();
}
} else {
//如果client已为空,重新初始化连接
client = null;
initSocketClient();
}
//每隔一定的时间,对长连接进行一次心跳检测
mHandler.postDelayed(this, WeSoketUtil.HEART_BEAT_RATE);
}
};
/**
* 开启重连
*/
private void reconnectWs() {
mHandler.removeCallbacks(heartBeatRunnable);
new Thread() {
@Override
public void run() {
try {
Log.e("JWebSocketClientService", "开启重连");
client.reconnectBlocking();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
使用:
<service
android:name=".websocket.JWebSocketClientService"
android:enabled="true"
android:exported="true" />
<service
android:name=".websocket.JWebSocketClientService$GrayInnerService"
android:enabled="true"
android:exported="false"
android:process=":gray" />
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Logger.e("服务与活动成功绑定");
binder = (JWebSocketClientService.JWebSocketClientBinder) iBinder;
jWebSClientService = binder.getService();
client = jWebSClientService.client;
isOpenService = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Logger.e("服务与活动成功断开");
}
};
直接使用
//启动服务
startJWebSClientService();
//绑定服务
bindService();
结束:
这篇文章仅仅是记录,方便以后在遇到当时的问题直接CV,希望以后不要遇到了。