webSocket: 跟服务端保持长连接,实时可以进行数据的发送跟接收,我这里主要用来跟服务端实时告警交互。一般应用于社交类应用
/**
* onClose code
* 1000 CLOSE_NORMAL 正常关闭; 无论为何目的而创建, 该链接都已成功完成任务。
* 1001 CLOSE_GOING_AWAY 终端离开, 可能因为服务端错误, 也可能因为浏览器正从打开连接的页面跳转离开。
* 1002 CLOSE_PROTOCOL_ERROR 由于协议错误而中断连接。
* 1003 CLOSE_UNSUPPORTED 由于接收到不允许的数据类型而断开连接 (如仅接收文本数据的终端接收到了二进制数据)。
* 1004 - 保留。 其意义可能会在未来定义。
* 1005 CLOSE_NO_STATUS 保留。 表示没有收到预期的状态码。
* 1006 CLOSE_ABNORMAL 保留。 用于期望收到状态码时连接非正常关闭 (也就是说, 没有发送关闭帧)。
* 1007 Unsupported Data 由于收到了格式不符的数据而断开连接 (如文本消息中包含了非 UTF-8 数据)。
* 1008 Policy Violation 由于收到不符合约定的数据而断开连接。 这是一个通用状态码, 用于不适合使用 1003 和 1009 状态码的场景。
* 1009 CLOSE_TOO_LARGE 由于收到过大的数据帧而断开连接。
* 1010 Missing Extension 客户端期望服务器商定一个或多个拓展, 但服务器没有处理, 因此客户端断开连接。
* 1011 Internal Error 客户端由于遇到没有预料的情况阻止其完成请求, 因此服务端断开连接。
* 1012 Service Restart 服务器由于重启而断开连接。 [Ref]
* 1013 Try Again Later 服务器由于临时原因断开连接, 如服务器过载因此断开一部分客户端连接。 [Ref]
* 1014 - 由 WebSocket 标准保留以便未来使用。
* 1015 TLS Handshake 保留。 表示连接由于无法完成 TLS 握手而关闭 (例如无法验证服务器证书)。
* 1016–1999 - 由 WebSocket 标准保留以便未来使用。
* 2000–2999 - 由 WebSocket 拓展保留使用。
* 3000–3999 - 可以由库或框架使用。 不应由应用使用。 可以在 IANA 注册, 先到先得。
* 4000–4999 - 可以由应用使用。
*/
首先创建一个服务,用来保持跟后台实时连接,别忘了manifest 注册一个服务,用到EventBus 交互无需开启一个新的进程不然无法接收其他组件发送的消息
public class socketServiceextends Service {//服务
private JWebSocketClientsocketClient;
private Handlerhandler;
private final int Time =20 *60 *1000;//心跳连接时间,websocket 30分钟关闭,我这里设置20m
private StringloginId ="-1"; //loginId 根据Id 推送指定账号
@Nullable
@Override
public IBinderonBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {//多次调用startService()会多次调用
loginId = intent.getStringExtra("loginId");
init();
Log.e("JWebSClientService0", "onStartCommand:" +loginId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {//创建一次
super.onCreate();
EventBus.getDefault().register(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(String id ) {//如果Login id 失效i重新登陆获取id
loginId = socketData.getLoginId();
handler.removeCallbacks(runnable);
handler.post(runnable);
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky =true)
public void onEvent(boolean close) {//是否需要关闭连接,如果登陆失效或者登出,需要关闭,不然还会收到告警信息。
if (socketClient !=null &&socketClient.isOpen() && connect.isClose())
socketClient.close();
}
public void init() {//因为onCreate 先调用所以onStartCommand 初始化
handler =new Handler();
// 设置webSocket,webUrl,地址,跟服务器连接的地址
URI uri = URI.create(MyApplication.getInstance().getWebsocketUrl());
closeConnect();
socketClient =new JWebSocketClient(uri) {
@Override
public void onOpen(ServerHandshake handshakedata) {
}
//接收服务端数据
@Override
public void onMessage(String message) {
if (message.contains("State")) {//心跳状态数据
try {
JSONObject jsonObject =new JSONObject(message);
HashMap hashMap =new HashMap<>();
hashMap.put("state", jsonObject.getString("State"));
hashMap.put("Information", jsonObject.getString("Information"));
hashMap.put("time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
MyApplication.getInstance().getHashMaps().add(hashMap);
}catch (JSONException e) {
e.printStackTrace();
}
}
if (message.contains("AlarmDataList")) {//告警数据
Gson gson =new Gson();
AlarmDataListItem dataListItem = gson.fromJson(message, AlarmDataListItem.class);
String IEndTime ="";
String IStartTime ="";
String AlarmRecID ="";
if (dataListItem.getAlarmDataList().size() >0) {
IEndTime = dataListItem.getAlarmDataList().get(0).getEndTime();
IStartTime = dataListItem.getAlarmDataList().get(0).getStartTime();
AlarmRecID = dataListItem.getAlarmDataList().get(0).getAlarmRecID();
}
String call ="";
switch (dataListItem.getAlarmType()) {
case 2://确认告警
// if (IEndTime.length() < 1)
// return;
// call = String.format("javascript:PJO_SE.CallDeleteRunAlarm('%1$s')", AlarmRecID);
// MyApplication.getInstance().m_ReportAlarm = true;
break;
case 0://批量开始告警
call = String.format("javascript:PJO_SE.CallAddRunAlarm('%1$s')", message);
MyApplication.getInstance().m_ReportAlarm =true;
if (Alarmsettings.isScreenedwarningspeech(message)) {
startAlarm();
}
break;
case 1://批量结束告警
call = String.format("javascript:PJO_SE.CallDeleteRunAlarm('%1$s')", message);
stopAlarm();
break;
}
if (!TextUtils.isEmpty(call)) {
final String finalCall = call;
MyApplication.getInstance().getWebView().post(new Runnable() {
@Override
public void run() {
MyApplication.getInstance().getWebView().loadUrl(finalCall);
}
});
}
}
}
//socket关闭调用
@Override
public void onClose(int code, String reason, boolean remote) {
Log.e("JWebSClientService3", reason +"==" + remote +"==" + code);
handler.postDelayed(runnable, 1000);
}
//连接异常信息
@Override
public void onError(Exception ex) {
Log.e("JWebSClientService2", ex.getMessage());
}
};
handler.postDelayed(runnable, Time);
try {
boolean connect =socketClient.connectBlocking();
if (connect)
socketClient.send(loginId);
}catch (InterruptedException e) {
e.printStackTrace();
ToastUtil.show(this, "服务器端口连接失败!");
}
}
//用来定时发送心跳跟检查连接状态
public Runnablerunnable =new Runnable() {
@Override
public void run() {
handler.removeCallbacks(runnable);
if (socketClient !=null) {
if (socketClient.isClosed()) {
reconnectWs();
}else {
Log.e("JWebSClientService10", loginId +"==");
socketClient.send(loginId);
}
}else {
init();
}
Log.e("JWebSClientService10.2", "==========");
handler.postDelayed(runnable, Time);
}
};
//重连
private void reconnectWs() {
handler.removeCallbacks(runnable);
new Thread(new Runnable() {
@Override
public void run() {
try {
Log.e("JWebSClientService10.0", socketClient.isClosed() +"==" +socketClient.getReadyState() +"==");
socketClient.reconnectBlocking();
}catch (InterruptedException e) {
e.printStackTrace();
Log.e("JWebSClientService10.1", e.getMessage());
}
}
}).start();
}
private void closeConnect() {// 断开WebSocket连接
try {
if (null !=socketClient &&socketClient.isOpen()) {
socketClient.close();
if (handler !=null &&runnable !=null) {
handler.removeCallbacks(runnable);
runnable =null;
}
}
}catch (Exception e) {
e.printStackTrace();
}finally {
socketClient =null;
}
}
//告警声音提示
private MediaPlayermPlayer;
public void startAlarm() {
if (mPlayer ==null) {
mPlayer = MediaPlayer.create(MyApplication.getInstance(), R.raw.alarmex);
//设置可以重复播放
mPlayer.setLooping(false);
}
if (!mPlayer.isPlaying())
mPlayer.start();
}
public void stopAlarm() {
// if (mPlayer != null) {
// mPlayer.stop();
// mPlayer.release();
// }
}
public void stopPlay() {//停止播放
if (mPlayer !=null &&mPlayer.isPlaying()) {
mPlayer.stop();
mPlayer.release();
mPlayer =null;
}
}
@Override
public void onDestroy() {
// closeConnect();
Log.e("JWebSClientService11", "onDestroy");
stopPlay();
super.onDestroy();
}
}
//启动
if (!isMyServiceRunning(getString(R.string.websocket))) {//第一次启动服务,后续LoginId改变只需要通知service 更新
Intent intent =new Intent(MainActivity.this, socketService.class);
intent.putExtra("loginId", loginId);
startService(intent);
}else {
EventBus.getDefault().post(new socketData(loginId));
}
//判断服务是否启动
public boolean isMyServiceRunning(String name) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (service.service.getClassName().equals(name)) {
return true;
}
}
return false;
}