由于项目中需要使用到 mqtt 协议进行数据通信,所以,我这边就去了解了一些,并做了一个简单的实现。

关于前置内容:

  1. Mqtt实战项目 点评:这个博客很清晰,代码也是可以直接运行的
  2. hivemq 点评:做了一些介绍,但是作用不太大
  3. eclipse paho 实现的 mqtt 开源库 api 点评:这个api 其实不完整,具体连接建立这些逻辑不在这里面
  4. mqtt 协议中文版 点评:内容很多,但是帮助不大
  5. eclise paho 实现的 mqtt 开源库 点评:代码可以直接运行,不过 gradle 什么的比较老,然后代码比较多,不太适合二次开发

好了,前置内容就这些了。不过其实有点多了。

然后,我这里给出一点我的发现。当然,我的实现也是基于开源库提供的 lib 去完成的。

我的实现,最核心的代码是以下几句:

implementation('org.eclipse.paho:org.eclipse.paho.android.service:1.0.2') {
        exclude module: 'support-v4'
    }
  1. 这个库本身实现了一个 sqlite 的数据库,保存的是接收到的新消息。不过不是所有接收到的消息都会保存。前提是:1,该客户端在线,2,没有调用收到数据的监听。满足以上两个前提,才会保存消息。
  2. 已经连接的时候,如果再次连接,会导致订阅的消息多次收到。比如,已经连接了,然后又去调用连接,会成功,但是订阅的消息就会收到两次。
  3. 该库收到消息这些是通过广播回调出去的,然后APP这边通过设置监听就能拿到消息。(不用主动注册任何广播接收器了)
  4. lib 里面本身提供了一个 android.app.Service的实现类,需要在自己的APP 的清单文件里面注册。然后,所有的连接,断开,发送,订阅 都是通过 这个 service 作为入口去调用的。
  5. service 本身不会去调用连接等,而是做了二次转发,让 lib 里面的其他类去做了这些操作。
  6. 建立连接成功之后,lib 里面会自动发心跳包与服务端保存长连接。
  7. 里面的 qos 指定似乎没什么作用,无论订阅者指定是0,1,2 还是发送者指定了 0,1,2 ,只要订阅的话题与发布的话题匹配,就能接收到消息。

由于是 demo , 没有经过大量测试,自测没发现丢消息或者重复收消息的情况。(多次连接导致的重复收消息除外。)

建立连接的大致调用栈:

MqttAndroidClient.connect -> MqttService.connect 
-> MqttConnection.connect -> MqttAsyncClient.connect
-> ClientComms.connect -> [调用 java.net.Socket.connect()]

这时候,一个 socket 连接其实已经建立完成了。不过,这里还不认为是完成,会发生数据到服务器端。因为 mqtt 协议有说明,建立连接其实是要发一些数据的。(发送什么数据,库已经封装了,可以不关心)

// socket.connect 的同时
-> CommsSender.start
 // 拿到 socket 的 outputStream ,然后 out.write 也就是发送数据给服务端了

大体上建立连接会走这些步骤。其实实际代码比这个还多一些并行步骤。

源码里面封装用的很多,然后还有线程,同步 这些处理,比较复杂。

不过调用起来还是比较方便的。

如果要在生产上使用的话,可能需要自建一个新的数据库,用于存储发送的消息,接收的消息,已订阅过的话题,发布的话题这些。

然后还有自动重连。lib 提供了连接丢失的回调,可以在此时去触发重连。

我的实现比较简陋,上面说的这些点都没有去实现,就不放源码链接了。

然后对于 lib 中的 ClientState这个类的代码没怎么看懂,似乎跟数据持久化相关,但是跟数据库无关。

希望有高手可以答疑解惑。