基于Mqtt协议Paho项目实现Android消息推送
服务端的部署
服务端的选择,笔者只测试过Apollo: 官网地址: 以及Mosquitto服务器: 官网地址
- 前者安装配置比较方便,可以在后台中直观的查看当前连接的客户端、发布、订阅的Topic以及消息,但是需要单独写一个服务端来发送消息。
- 后者需要安装Cygwin,相对Apollo服务器安装起来较为繁琐,但是好处之一是可以通过命令行直接发布消息。
总之,两者都是非常强大的服务器,笔者也只是刚刚入门还有很多功能需要继续探索,本文为了演示效果选择Mosquitto服务器来演示。
关于Mosquitto服务器的部署,可以参考上一篇文章,传送门。
客户端的实现
客户端的实现基于Paho项目,主要使用其中的MqttClient类来实现与服务端的连接以及对消息的订阅。
重要的一点,在本地进行测试的时候,其中的serverURI不要使用localhost或者127.0.0.1,换成自己本机的实际i地址
因为某些原因只贴出部分关键代码进行分析:
首选需要初始化MqttClient以及MqttConnectionOptions:
初始化MqttConnectOptions,这里需要配置了Mosquitto服务器设置的用户的用户名与密码,并设置了连接超时时间以及心跳包发送间隔时间,这些根据自己的需求进行配置即可。
private void initMqttConnectionOptions() { conOpt = new MqttConnectOptions(); conOpt.setCleanSession(true); conOpt.setUserName(userName); conOpt.setPassword(passWord.toCharArray()); conOpt.setConnectionTimeout(CONNECTION_TIMEOUT); conOpt.setKeepAliveInterval(KEEP_ALIVE_INTERVAL); } 1 2 3 4 5 6 7 8 9
初始化MqttClient,其中host即serverUri,这里是本地进行测试,但是需要注意的是需要使用实际的ip地址,而非localhost。
另外设置了回调接口,当收到订阅的消息时候通过Handler发送并进行处理。
private void initMqttClient() { // TODO Auto-generated method stub initMqttConnectionOptions(); try { client = new MqttClient(host, "LHY", null); client.setCallback(mCallBack); // 开始连接 connect(); } catch (MqttException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private MqttCallback mCallBack = new MqttCallback() { @Override public void messageArrived(String topic, MqttMessage message) throws Exception { // TODO Auto-generated method stub if (message != null) { Log.d(TAG, "messageArrived, topic: " + topic + "; message: " + new String(message.getPayload())); Message msg = Message.obtain(); Map<String, Object> map = new HashMap(); map.put("topic", topic); map.put("mqttMsg", message); msg.what = HandlerType.MESSAGEARRIVED.getType(); msg.obj = map; handler.sendMessage(msg); } } @Override public void deliveryComplete(IMqttDeliveryToken token) { // TODO Auto-generated method stub if (token != null) { try { Log.d(TAG, "deliveryComplete: " + new String(token.getMessage().getPayload())); } catch (MqttException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void connectionLost(Throwable cause) { // TODO Auto-generated method stub Log.d(TAG, "connectionLost"); // 重连机制 } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
当连接成功之后,通过client.subscribe()方法来订阅主题,内部最终通过socket来完成和服务端的消息的交互,此时我们通过Mosquitto服务器发送指定Topic的消息,客户端就可以接收到了。
Log.d(TAG, getString(R.string.connect_success)); try { client.subscribe(mqttTopic, QOS); } catch (Exception e) { e.printStackTrace(); } 1 2 3 4 5 6
演示Gif:
直接发布中文或者使用utf-8编码的时候,客户端中接收到的消息会乱码,因此需要转成GBK编码格式