Android WebSocket状态管理框架 - WebSocketGo

2023-11-07

阅读本文需要 Integer.MAX_VALUE 分钟。

故事背景

笔者所在的公司主营业务是智能家居,笔者在公司负责的Android端App的开发。关于智能家居,估计现在百分之八九十的童鞋都听过,但真正了解或者使用过的估计就不占多数了。本文不谈行业前景,只谈技术。

为了方便大家更加了解故事的背景,顺便科普一下智能家居,想直奔WebSocket主题的童鞋可以直接第二章节

智能家居,算是物联网的一个典型应用场景。什么是物联网呢,字面意思就是把众多物体连接起来组成一个网络,英文是Internet of things(IoT)。小到一个你的手机跟蓝牙耳机,大到一个城市的各个角落,究极形态就是“万物互联”。(为什么突然想起万佛朝宗 -_-!)

IoT其实不在意网络的协议,也不在意连接的到底是什么东东,就这种形态本身而言,就是IoT。其实这个概念其实很早就有了,在笔者上大学那会,不怕暴露年龄的说是在09到10年左右就听说过物联网这个词。还记得实验课的GPRS智能抄表系统么,你可能没有觉得多么高大上,不就是水表上插个SIM卡,定期把值发到客户端上么,再也不怕被人上门查水表啦~ 没错,这也是IoT的一种体现。

但这么多年,物联网但一直不温不火。至于为什么最近几年又被提出来呢,智能家居在其中扮演了很重要的作用。另外AI这把火也起到了推波助澜的作用,任何产品都要加上智能二字。所以有了AI + IoT,也就是AIOT。具体就不详述了,以后可以再单开一文详细介绍下物联网。

说回智能家居,智能家居是家庭为单位的物联网,简单说就是你可以通过家里中控或者App控制制家里的灯、插座、监控、电器等等。

文字算个球,一图解千愁,上架构图

简单解释一下,网关的作用是负责连接屋内的所有设备,网关和设备之间一般不会采用HTTP(个别单品除外),而会采用比如zigbee、lora等近场通信协议(或者直接用有线方式更稳定),因为功耗低,比较省电,你想家里如果装了几十个开关面板,总归每个月也能节约十几二十块钱的电费吧。当然最重要的原因还是因为方案也比较成熟。所以使用这类设备之前需要有个“组网”的操作,把设备组到网关上。如果断开了,网关就认为设备离线了。

网关会将设备的状态上报给云平台,云平台就将状态下发给客户端了。同样,客户端控制设备就是个反向的过程。当然如果以后5G普及了,设备直接通过5G网络连接云平台,因为5G功耗低、延迟低、速度快,就可以不需要网关了。

整体的架构还算是比较简单的,当然中间也有很多复杂的逻辑,涉及到比如设备状态、人员、权限、房屋的管理等等这里就不关注了。

在服务器下发设备状态的时候就涉及到了推送。因为智能家居有情景模式的概念,比如回家模式,执行一个请求,咔咔打开十几个灯,所以靠请求的返回值判断状态是不太现实的,只能依靠推送。

由于业务的特殊性,智能家居的推送需要有较高的实时性,比如用户打开了灯(无论在app上打开或者直接打开),app上的灯的状态都需要立即变成开。如果等个3、5秒状态再发生改变,这样的用户体验很不好。

我们最早使用的是某光推送,发现延迟严重,有时需要等十几秒才收到推送,毕竟适用场景毕竟不一样。所以决定自建长连接当推送。经过选型,决定采用本文的主角,WebSocket。

WebSocket状态管理现存的问题

市面上有很多现成的WebSocket连接库,比较著名的有Java-WebSocket,OkHttp也自带WebSocket支持。

最初因为项目内已经接入了OkHttp,所以直接使用了OkHttp。使用的方式很简单,熟悉OkHttp的童鞋应该很懂,

OkHttpClient client = OkHttpClient.Builder().build();
Request request = new Request.Builder().build();
client.newWebSocket(request, new WebSocketListener() {
    @Override
    public void onOpen(okhttp3.WebSocket webSocket, Response response) {}

    @Override
    public void onMessage(okhttp3.WebSocket webSocket, String text) {}

    @Override
    public void onClosed(okhttp3.WebSocket webSocket, int code, String reason) {}

    @Override
    public void onFailure(okhttp3.WebSocket webSocket, Throwable t, Response response) {}
});
复制代码 

调用方便,回调状态也很清晰。Java-Websocket也差不多类似,但总体来说有以下几个问题:

1. 心跳机制

无论OkHttp还是Java-WebSocket,都是有心跳机制的。但OkHttp的心跳间隔,也就是pingInterval,在创建client时候就已经固定了,是不支持中途调整的。(Jake大神还在github上回复过相关问题,意思是调用者不需要关注这些。但往往确实有这种需求的啊

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android WebSocket状态管理框架 - WebSocketGo 的相关文章

  • 在 JellyBean 上使用 LogCat

    我有一个非常随机发生的错误 所以我依赖LogCat我从 Play 商店购买的监控应用程序 以查看发生时设备上抛出的异常 自从使用 Jelly Bean 以来 我没有看到任何日志记录 我读过 使用 Jelly Bean 应用程序只能看到Log
  • Android studio Gradle 同步和构建错误

    我是 android studio 和 gradle 的新手 我得到了 AS 0 5 我下载了0 8 1更新包并通过删除已安装的文件并将更新文件复制到program files文件夹进行更新 它运行正确 但当我尝试同步 gradle 时 出
  • 如何设置自定义谷歌地图标记的背景图像?

    我有一个用于 Google 标记的自定义图像 但我必须在其背景上设置另一个图像 是否可以设置地图标记的背景图像 是的你可以 试试这个所以问题如何使用 Android 地图 API v2 创建自定义形状的位图标记 https stackove
  • 如何在Android中的多个Activity之间切换

    我有 8 个屏幕 我为此准备了 8 个活动 在第一个活动中我给出了这段代码 从 Is 活动切换到 IInd 在图像按钮上给出单击 public void onClick View v Intent myIntent new Intent v
  • 如何在 Android 中检查与配对设备的蓝牙连接状态

    我开发了一个蓝牙应用程序 它将连接到配对的设备并发送消息 但我必须先测试连接 我尝试了很多选择 但没有一个效果很好 那么您能给我发送任何可以做到这一点的代码示例吗 我创建了一个线程 但无法获得良好的连接状态来构建 if 函数 这是代码 pa
  • getWidth() 和 getHeight 在 onMeasure() 之后返回零(特定设备)

    我注意到在调用 onMeasure 后 我的应用程序的视图为 getWidth 和 getHeight 返回 0 这种情况只发生在少数设备上 对于大多数 Android 设备 以下代码可以正常工作 我的 checkViewAndLoad 函
  • android以编程方式打开电池设置

    我正在寻找一种从 Android 应用程序打开电池设置屏幕的方法 到目前为止我发现了两个意图 Intent ACTION POWER USAGE SUMMARY Settings ACTION BATTERY SAVER SETTINGS
  • Gradle 控制台 - 获取更多日志输出

    我正在使用Android Studio 在 gradle 控制台中收到以下错误消息 编译错误 查看日志了解更多详情 尝试 使用 stacktrace 选项运行以获取堆栈跟踪 使用 info 或 debug 选项运行以获得更多日志输出 构建失
  • addToBackStack 之后的 popBackStack() 不起作用

    我的项目包含两个片段 FragmentA 应用启动时默认加载的fragment FragmentB 替换fragmentA当单击按钮完成时 这是我的主视图的 XML
  • 使用 navhost 停止底部导航中的片段刷新

    这个问题已经被问过几次了 但现在已经是 2020 年了 有没有人找到一个好的可用的解决方案呢 我希望能够使用底部导航控件进行导航 而无需在每次选择片段时刷新片段 这是我目前拥有的 导航 main xml
  • 如何检查应用程序是否违反 Google 的假冒政策

    我的应用程序已从 Google Play 商店中删除 原因如下 经审核 我的应用 有 由于政策罢工而被暂停并从 Google Play 中删除 因为 它违反了假冒政策 有没有其他方法可以在发布之前检查应用程序是否遵守所有 Google 政策
  • 何时取消订阅

    我有一个关于如何取消订阅可观察的问题 我有两个代码 但我不确定哪一个更好 示例 1 gt 流结束后取消订阅订阅者 Subscriber
  • 如何从 Android L 预览设计制作 Android 列表视图设计

    我制作Android L预览图像样式列表项 这是我针对这些类似设计的代码 可绘制 list item bg xml
  • 如何检查 HoneyComb 或更高版本是否正在运行,并相应地调用该版本的方法?

    对于Android 3 0及更高版本 我想调用某个方法 有没有办法检查某个方法在运行的 Android 版本中是否可用 更准确地说 我的MinSDK是7 Android 2 1 TargetSDK是8 Android 2 2 我需要测试 如
  • 存储 FCM 的令牌

    我正在尝试将我的令牌存储在我的云数据库中 我稍后将在云函数中使用此令牌 以便向已添加为好友的用户发送通知 然而 推送设备令牌不起作用 因为用户未经授权 授权后我无法保存它 因为令牌是在安装应用程序时生成的 private static fi
  • Xamarin.Forms 用相机拍照显示方向错误并且后退按钮崩溃

    我正在使用此处的 Xamarin Forms Camera 示例 https github com XForms Xamarin Forms Labs Samples tree master XF Labs CameraSample htt
  • Android 中的垂直(旋转)标签

    我需要两种在 Android 中显示垂直标签的方法 水平标签逆时针旋转 90 度 字母在侧面 带有字母的水平标签 如商店招牌 我是否需要为这两种情况 一种情况 开发自定义小部件 我可以使 TextView 以这种方式呈现吗 如果我需要完全自
  • Android 2.2 中不带预览的相机捕获

    我需要捕获图像而不显示预览 我想在后台作为服务来完成它 可以这样做吗 是有可能实现的 您应该定义一个处理 Camera 对象的类 例如调用 Camera open 等 不要为相机对象提供以下行以禁用预览 mCamera setPreview
  • 在另一个布局中以编程方式膨胀布局

    我的 Android 应用程序需要帮助 我需要在另一个布局中膨胀一个布局 但我不知道该怎么做 我的xml代码是这样的 item xml 我需要膨胀多个 xml 取决于可变数量
  • 水平 RecyclerView 顶部的滚动条

    我正在做简单的演示卧式RecyclerView 我想与回收视图一起显示滚动条 所以我添加了android scrollbars horizontal and android scrollbarSize 5dp 在 XML 中 我可以获得滚动

随机推荐

  • 使用docker需要知道的基础知识

    一 docker概念 1 1 docker仓库 镜像 容器的作用和三者之间的关系是什么 答 Docker 仓库 用来保存镜像 可以理解为代码控制中的代码仓库 Docker 镜像 是用于创建 Docker 容器的模板 Docker 容器 是独
  • 前端工程化详解——理解与实践前端工程化

    前言 前端工程化一直是一个老生常谈的问题 不管是面试还是我们在公司做基建都会经常提到前端工程化 那么为什么经常会说到前端工程化 并没有听过后端工程化 Java工程化或者Python工程化呢 我们理解的前端工程化是不是一直都是Webpack的
  • 回望2001年的雪鸟城:引发全球软件革命的“敏捷宣言”是如何诞生的?

    将人们置于流程之上 专注于开发可以工作的软件 而不是软件的文档 和你的客户一起工作 而不是为一份合同而争吵 在此过程中 要对改变持开放态度 编者按 敏捷 Agile 这个对于开发真来说不在陌生的概念 已经提出了近17年了 其背后的哲学理念也
  • [CSDN竞赛]第五期参赛回顾

    CSDN竞赛 第五期参赛回顾 体验感想 第一次参加 本来有点小期待 那天还起晚了 结果登录不上去 发现大家都有问题 对我来说反而是好事 本来早上没有下午晚上更加精神 下面是提的建议 上次的登录问题 希望官方下次不要再出现 一定要准备充足 为
  • Unity Shader:用几何着色器实现复联3灭霸的终极大招灰飞烟灭

    图1 正常渲染 图2 几何着色器粒子化特效进行中 图3 几何着色器粒子化特效进行中 1 用几何着色器进行图元转换 在OpenGL渲染管线中 几何着色器Geometry Shader有一个独一无二的功能 既是图元转换 可简单理解为对基本图元点
  • 微信小程序默认下拉刷新和自定义下拉刷新的方式

    1 默认下拉刷新 在指定页面对应的 json配置文件中加入 enablePullDownRefresh true backgroundTextStyle dark 在对应的 js文件中 写入onPullDownRefresh 如果存在则替换
  • 手把手教你做一套“能源管理系统” A

    hello 大家好 我是CC 今天让CC来手把手教大家设计一套 能源管理系统 上个视频咱们有说到 能源管理系统 的范围很广 可以粗分为面向供给侧和面向消费侧 其中面向消费侧又可以分为 家庭能源管理系统HEMS 社区 园区能源管理系统CEMS
  • EQ频响曲线绘制和DRC特性曲线绘制

    目录 1 EQ 系数计算和频响曲线绘制 1 1 基本流程 1 2 EQ参数输入 1 3 滤波器系数计算 1 4 频率响应计算 1 5 曲线绘制 2 DRC特性曲线绘制 2 1 基本流程 2 2 参数输入 2 3 增益计算 2 4 静态特性曲
  • Java学习书籍推荐(步步为营)

    概述 本文只要介绍 Java学习的书籍 进阶之路 始于行动 编程重在理解加多实践 在当今快速发展的时代 要学会站在巨人的肩膀上 吸取经验 看书就是最快与最低成本的进阶之路 史上没有最好的书籍 只有适合自己的书籍 小伙伴们开始行动吧 Java
  • Qt5.14.2中使用QCamera实现切换相机、分辨率和图像捕获功能

    demo中主要涉及的Qt类有 相机类QCamera 取景器类QCameraViewfinder 图像捕获类QCameraImageCapture 因此添加模块multimedia multimediawidgets QT core gui
  • 在 uni-app 中使用 webview 打开本地文件,打开不成功

    在 uni app 中使用 webview 打开本地文件 打开不成功出现套娃现象的解决方案 小程序仅支持加载网络网页 不支持本地html 排查本地文件是否按照官方给出的路径建立的 uni app 项目根目录 gt hybrid gt htm
  • 全民奇迹修复云服务器跨服,越过服务器来打你 全民奇迹跨服战玩法全面解析...

    在全民奇迹当中 玩家与玩家之间的PK往往是解决问题最好的方法 一言不合就开打才是所有奇迹勇士的特点 本篇全民奇迹跨服战玩法全面解析 973手游网小编就来为大家说说跨服战 全民奇迹 16人的对决 幻影寺院 实力的对决 在幻影寺院中 玩家被分为
  • bluez——dbus接口api

    bluez dbus接口api bluez的api接口的说明文档在 doc 路径下 我这先重点分析下adapter agent和device这几个文件 这里面包含的是常用的api 1 agent c 这里现在注册的几个dbus方法 void
  • Winform SplitContainer控件可调整大小

    IsSpliterFixed属性设为False FixedPannel属性设为Pannel1 要固定的面板的名称 之后鼠标移动到控件中间的分隔线 就可以调整大小了
  • 多项式加法

    多项式的加法 一 创建链表 二 初始化链表 三 打印链表 四 打印结点 五 添加数据 六 相加 七 测试代码 八 测试结果 一 创建链表 typedef struct LinkNode int coefficient int exponen
  • MIT6.824分布式系统lecture1笔记:Intro,MapReduce

    lecture1先对分布式系统的设计进行了概述 然后介绍了MapReduce的案例 Intro 为什么要使用分布式系统 1 追求高性能 通过分布式系统进行并行计算 2 使系统具有容错性 一台计算机计算错误 可以转移到另一台计算机 3 一些问
  • Docker部署Redis单机版

    1 拉取镜像 docker pull redis latest 2 创建挂载目录 mkdir r home egn redis conf mkdir r home egn redis data 3 修改配置文件 新建redis conf 节
  • 关于java.lang.NoClassDefFoundError: Could not initialize class xxx错误的原因和处理办法

    关于NoClassDefFoundError错误出现的原因有多种 网上其他博主也给出各种答案 但说的都比较广泛 这里博主说一下由于初始化失败而造成的NoClassDefFoundError错误 博主在一个Test这个类中使用了静态代码块 类
  • C#集合总结

    1 为什么引入集合 因为数组长度是固定的 为了建立一个动态的 数组 所以引入了集合 2 为什么引入ArrayList 非泛型集合 ArrayList可以填补数组的不足 进行元素的动态维护 数组的长度是固定的 而ArrayList的容量可以根
  • Android WebSocket状态管理框架 - WebSocketGo

    阅读本文需要 Integer MAX VALUE 分钟 故事背景 笔者所在的公司主营业务是智能家居 笔者在公司负责的Android端App的开发 关于智能家居 估计现在百分之八九十的童鞋都听过 但真正了解或者使用过的估计就不占多数了 本文不