文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

android websocket快速上手使用和详细讲解

2022-06-06 14:21

关注

1、快速使用

项目中的使用,以github的开源库org.java-websocket:Java-WebSocket:1.3.8为例,并且封装了工具类,快速上手。
1、org.java-websocket:Java-WebSocket的github地址:https://github.com/TooTallNate/Java-WebSocket
2、我封装的工具类WebSocketUtils.java的代码(下面有使用和讲解),思想是这样的:

一、重连机制。代码中有备注,在close()中重连。
二、心跳机制。工具类中,我是通过Observable.interval定时执行,10秒钟一次心跳。
三、后台返回的消息和给后台发送消息。在onMessage()中返回,和后台约定需要的数据,发送数据是通过sendMessage(),也是和后台约定好数据格式就好。

public class WebSocketUtils {
    private String TAG = "web_socket";
    private static WebSocketUtils instance = null;
    WebSocketClient client;
    //转成的要操作的数据
    URI uri;
    //后台连接的url
    String address = "ws://114.55.103.198:8989/";
    //连接是否关闭,用于判断是主动关闭还是断开,断开需要重连
    boolean isHandClose;
    //记录心跳重联的次数
    int reconnectTimes;
    //心跳timer
    Disposable timerHeart;
    //重连timer
    Disposable timer;
    //懒加载单例模式,synchronized确保线程安全。
    // 适合没有多线程频繁调用的情况,多线程频繁调用的时候,可以用双重检查锁定DCL、静态内部类、枚举 等方法,文章后面会详细介绍。
    public static synchronized WebSocketUtils getInstance() {
        if (instance == null) {
            instance = new WebSocketUtils();
        }
        return instance;
    }
    public void initSocket() {
        if (null != client && client.isOpen()) {
            EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_CONNECT_SUCCESS, "登录成功!", ""));
            return;
        }
        isHandClose = false;
        startSocket();
    }
    public void startSocket() {
        try {
            uri = new URI(address);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        if (null == client || !client.isOpen()) {
            client = new WebSocketClient(uri) {
                @Override
                public void onOpen(ServerHandshake serverHandshake) {
                    reconnectTimes = 0;
                    if (timer != null) {
                        timer.dispose();
                    }
                    //socket连接成功,通过eventbus通知房间,用户可以加入房间了
                    EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_CONNECT_SUCCESS, "连接成功!", ""));
                    LogUtils.eTag(TAG, "连接成功");
                    registerWebSocket();
//10秒钟进行一次心跳,防止异常断开
                    timerHeart = Observable.interval(10, TimeUnit.SECONDS).subscribe(new Consumer() {
                        @Override
                        public void accept(Long aLong) throws Exception {
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("type", "ping");
                            sendMessage(jsonObject.toString());
                        }
                    });
                }
                @Override
                public void onMessage(String s) {
                //后台返回的消息
                    EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_RECEIVE_SUCCESS, "收到消息!", s));
                    LogUtils.eTag(TAG, "收到消息", s);
                }
                @Override
                public void onClose(int i, String s, boolean b) {
                    if (isHandClose) {
                        EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_CONNECT_SUCCESS_BY_HAND, "主动关闭成功!", s));
                        LogUtils.eTag(TAG, "主动关闭成功", s);
                        reconnectTimes = 0;
                        if (timer != null) {
                            timer.dispose();
                        }
                        if (timerHeart != null) {
                            timerHeart.dispose();
                        }
                    } else {
                        //非正常关闭进行重连,重连每次两秒,最多十次
                        timer = Observable.timer(2, TimeUnit.SECONDS).subscribe(new Consumer() {
                            @Override
                            public void accept(Long aLong) throws Exception {
                                LogUtils.eTag(TAG, "重连");
                                reconnectTimes = reconnectTimes + 1;
                                startSocket();
                            }
                        });
                        //重联超过十次没成功,结束重连
                        if (reconnectTimes > 10) {
                            EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_CLOSE_SUCCESS, "关闭成功!", s));
                            LogUtils.eTag(TAG, "关闭成功", s);
                            reconnectTimes = 0;
                            if (timer != null) {
                                timer.dispose();
                            }
                            if (timerHeart != null) {
                                timerHeart.dispose();
                            }
                        }
                    }
                }
                @Override
                public void onError(Exception e) {
                    EventBusUtils.post(new EventBusUtils.EventMessage(EVENT_WEB_SOCKET_ERROR, "出现错误!", ""));
                    LogUtils.eTag(TAG, "出现错误", e.getMessage());
                }
            };
            client.connect();
        }
    }
    //向服务器发送消息
    public void sendMessage(String s) {
        if (client == null || client.isConnecting() || client.isClosed() || !client.isOpen()) {
            LogUtils.eTag(TAG, "未建立实时通信");
            return;
        }
        try {
            client.send(s);
            LogUtils.eTag(TAG, "发送消息:", s);
        } catch (Exception e) {
            e.printStackTrace();
            startSocket();
        }
    }
    //关闭socket
    public void closeSocket() {
        isHandClose = true;
        if (client != null) {
            client.close();
            client = null;
        }
    }
    //向服务器发送初始化信息
    void registerWebSocket() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", "init");
        jsonObject.put("token", MyApplication.getInstance().getToken());
        sendMessage(jsonObject.toString());
    }
    //和服务器约定的传递的参数
    public void sendData(String type, String room_id) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", type);
        jsonObject.put("token", MyApplication.getInstance().getToken());
        jsonObject.put("room_id", room_id);
        sendMessage(jsonObject.toString());
    }
}

3、工具类的使用:
一、在需要用的地方初始化 , WebSocketUtils.getInstance().initSocket()
二、需要传递给后台的数据,举例: WebSocketUtils.getInstance().sendData(“setRoomManager”, id, user_id)。sendData()函数的参数根据情况自己配置,和后台约定好就行。
三、结束使用websocket的时候调用, WebSocketUtils.getInstance().closeSocket()

注:

1、文中用到的eventbus有封装好的类,在我的文章https://blog.csdn.net/u013750244/article/details/105967281:中,可以借鉴,这篇文章我也会讲跨进程数据传输的处理。
2、Observable.interval定时执行的使用和讲解我写在一篇文章,可以看看。

详细讲解:

把这篇文章放到语音直播间分类,是因为语音直播间刚刚用到,而且端对端的实时通信用websocket节省带宽和性能。Android与服务器的通信方式主要是两种:一是Http通信,一是Socket通信。两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求。

龙腾腾 原创文章 47获赞 13访问量 1万+ 关注 私信 展开阅读全文
作者:龙腾腾


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯