MQTT Android客户端的使用介绍

.

简介

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议。

它是一种 发布/订阅 ,极其简单和轻量级的消息传递协议,专为受限设备和低带宽,高延迟或不可靠的网络而设计。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境。相对于XMPPMQTT更加轻量级,并且占用的宽带低。

.

.

MQTT体系结构的介绍

网络连接

由底层传输协议提供给MQTT使用的架构

  • 底层传输协议能够连通客户端和服务端
  • 底层传输协议提供有序的,可靠的,双向字节流

应用消息

指通过MQTT在网络中传输的应用程序数据。当应用消息通过MQTT传输的时候会附加上质量服务(QoS)和话题名称。

客户端

指使用MQTT的程序或设备。客户端总是去连接服务端。它可以

  • 发布其他客户端可能会感兴趣的应用消息
  • 订阅自己感兴趣的的应用消息
  • 退订应用消息
  • 从服务端断开连接

服务端

扮演订阅或发布应用消息的客户端之间的中间人。一个服务端

  • 接受客户端的网络连接
  • 接受客户端发布的应用消息
  • 处理客户端订阅和退订的请求
  • 转发匹配客户端订阅的应用消息

订阅

一个订阅由一个话题过滤器和一个最大的QoS组成。一个订阅只能关联一个会话。一个会话可以包含多个订阅。每个订阅都有不同的话题过滤器。

话题名称

指附着于应用消息的标签,服务端用它来匹配订阅。服务端给每个匹配到的客户端发送一份应用信息的拷贝。

话题过滤器

包含在订阅里的一个表达式,来表示一个或多个感兴趣的话题。话题过滤器可以包含通配符。

会话

一个有状态的客户端和服务端的交互。有些会话的存续依赖于网络连接,而其他则可以跨越一个客户端和服务端之间的多个连续的网络连接。

MQTT控制包

通过网络连接发送的包含一定信息的数据包。MQTT规范定义了14个不同类型的控制包,其中一个(PUBLISH包)用来传输应用信息。

.

.

MQTT的优点

.

  1. 轻巧高效,最大限度地减少客户端和网络带宽所需的资源

  2. 使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合

  3. 对负载内容屏蔽的消息传输

  4. 使用 TCP/IP 提供网络连接(持久会话)

  5. 使用 SSL/TLS 提供网络安全和信任

  6. 具有一种“遗嘱”功能,该功能通知订户客户机从 MQTT 服务器异常断开连接

  7. 可以指定服务质量 (QoS) 级别以支持消息可靠性

  • qos为0: “至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送
  • qos为1: “至少一次”,确保消息到达,但消息重复可能会发生。这一级别可用于如下情况,你需要获得每一条消息,并且消息重复发送对你的使用场景无影响
  • qos为2: “只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果

.

.

MQTT核心参数说明:

.

  • topic: 中文意思是“话题”。在MQTT中订阅了(subscribe)同一话题(topic)的客户端会同时收到消息推送。直接实现了“群聊”功能

  • clientId: 客户身份唯一标识

  • qos: 服务质量

  • retained: 要保留最后的断开连接信息

  • userName: 连接到MQTT服务器的用户名

  • passWord: 连接到MQTT服务器的密码

.

.

MQTT最主要方法的介绍:

.

1. connect()方法

作用: 连接MQTT服务器

参数说明:

  • options 用来携带连接服务器的一系列参数,例如用户名、密码等。
  • userContext 可选对象,用于向回调传递上下文。一般传null即可。
  • callback 用来监听MQTT是否连接成功的回调
 @Overridepublic IMqttToken connect(MqttConnectOptions options, Object userContext,IMqttActionListener callback) throws MqttException {//...
}

.

2. publish()方法

作用: 发布消息,向服务端推送消息。向某个话题发送消息,之后服务器会推送给所有订阅了此话题的客户

参数说明:

  • topic 发布消息的主题
  • payload 消息内容的字节数组
  • qos 提供消息的服务质量,可传0、1或2
  • retained 是否在服务器保留断开连接后的最后一条消息
 @Overridepublic IMqttDeliveryToken publish(String topic, byte[] payload, int qos,boolean retained) throws MqttException, MqttPersistenceException {//...}

.

3. subscribe()方法

作用: 订阅消息主题

参数说明:

  • topic 订阅消息的主题
  • qos 订阅消息的服务质量,可传0、1或2
 @Overridepublic IMqttToken subscribe(String topic, int qos) throws MqttException,MqttSecurityException {//...}

.

.

MQTT安卓客户端的使用介绍

.

在全局的build.gradle文件中添加

repositories {maven {url "https://repo.eclipse.org/content/repositories/paho-snapshots/"}
}

.

.

在项目build.gradle文件中添加依赖

dependencies {implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}

.

AndroidManifest.xml 添加下面的限权

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

.

AndroidManifest.xml 注册Service服务

<!--MqttService-->
<service android:name="org.eclipse.paho.android.service.MqttService" />

.

具体实现如下:

public class MQTTManager {private final String TAG = "MQTTManager"private static MQTTManager instance = null;private String host = ""; //服务器地址(协议+地址+端口号)private String userName = "";//连接到MQTT服务器的用户名private String password = "";//连接到MQTT服务器的密码private String[] topics;//订阅得1话题private String clientId ="";private MqttClient client;//mqtt客户端对象private MqttConnectOptions conOpt;//MQTT连接选项对象//消息的回调private MqttCallback mCallback = new MyMqttCallback();//单例的双重校验锁模式public synchronized static MQTTManager getInstance() {if (instance == null) {instance = new MQTTManager();}return instance;}//创建连接(初始化MQTT客户端)public void createConnect(Context context, String host, String userName, String password, String[] topics) {this.host = host;this.userName = userName;this.password = password;//客户端ID(设备唯一识别号,需要先给权限)if(getDeviceID(context) != ""){clientId = getDeviceID(context);}//获取操作系统的缓存临时目录String tmpDir = System.getProperty("java.io.tmpdir");//数据缓冲区MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(tmpDir);try {//创建MQTT连接选项对象,并初始化conOpt = new MqttConnectOptions();conOpt.setCleanSession(true);// 清除缓存conOpt.setConnectionTimeout(10);//设置超时时间,单位:秒conOpt.setKeepAliveInterval(20);// 心跳包发送间隔,单位:秒conOpt.setAutomaticReconnect(true);//设置如果连接丢失,客户端是否会自动尝试重新连接到服务器// 用户名和密码if( password != null && userName != null) {conOpt.setUserName(userName);conOpt.setPassword(password.toCharArray()); }//创建MQTT客户端对象client = new MqttClient(host, clientId, dataStore);// 设置MQTT监听并且接受消息client.setCallback(mCallback);if( topics != null) {this.topics = topics;client.subscribe(topics);}} catch (MqttException e) {e.printStackTrace();}//连接MQTT服务器doConnect();}//连接MQTT服务器public void doConnect() {if (client != null&& !mqttAndroidClient.isConnected() && isConnectIsNomarl()) {try {/*** options:用来携带连接服务器的一系列参数,例如用户名、密码等* userContext:可选对象,用于向回调传递上下文。一般传null即可* callback:用来监听MQTT是否连接成功的回调* */   client.connect(conOpt, null, iMqttActionListener);} catch (Exception e) {e.printStackTrace();}}}//连接服务器的回调private IMqttActionListener iMqttActionListener = new IMqttActionListener() {@Override//连接成功public void onSuccess(IMqttToken arg0) {Log.i(TAG, "连接成功 ");try {// 订阅话题client.subscribe(topics,2);} catch (MqttException e) {e.printStackTrace();}}@Override// 连接失败,重连public void onFailure(IMqttToken arg0, Throwable arg1) {doConnect()    //连接失败,重连(可关闭服务器进行模拟)Log.i(TAG, "连接失败 "+arg1.printStackTrace());}};//重新订阅话题public void subscribeTopics(String[] topics) throws MqttException {if(topics !=null){this.topics = topics;}/*** topic:订阅消息的主题* qos:订阅消息的服务质量,可传0、1或2* */client.subscribe(topics,2);}//发布消息(true:标识发送成功;false:表示发送失败)public boolean publish(String topicName, int qos, String msg) {try {if (client == null || !client.isConnected()) {return false;}//创建并配置消息MqttMessage message = null;try {//初始化消息对象message = new MqttMessage(msg.getBytes("utf-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();}message.setQos(qos);/*** topic:发布消息的主题* payload:消息的字节数组* qos:提供消息的服务质量,可传0、1或2* retained:是否在服务器保留断开连接后的最后一条消息* */client.publish(topicName, message);return true;} catch (MqttException e) {Log.e("mq", e.toString());}return false;}//取消连接public void disConnect() throws MqttException {if (client != null && client.isConnected()) {client.disconnect();}}//断开连接public void close() {if (client != null && client.isConnected()) {try {client.disconnect();} catch (MqttException e) {e.printStackTrace();}}}//获取手机的设备标识作为MQTT客户端的IDpublic static String getDeviceID(Context context) {TelephonyManager tm = (TelephonyManager) context.getSystemService(Activity.TELEPHONY_SERVICE);if (tm != null) {return tm.getDeviceId();}return "";}//判断网络是否连接private boolean isConnectIsNomarl() {ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo info = connectivityManager.getActiveNetworkInfo();if (info != null && info.isAvailable()) {String name = info.getTypeName();Log.i(TAG, "当前网络名称:" + name);return true;} else {Log.i(TAG, "没有可用网络");/*没有可用网络的时候,延迟3秒再尝试重连*/new Handler().postDelayed(new Runnable() {@Overridepublic void run() {doConnect();}}, 3000);return false;}}
}

.

接收MQTT服务端发送过来的信息的回调

public class MyMqttCallback implements MqttCallbackExtended {@Override/***当消息从服务器到达时调用此方法* topic:消息主题的名称发布到* message:实际信息* */public void messageArrived(String topic, MqttMessage message) throws Exception {String str1 = new String(message.getPayload());Log.i("TAG", "接收内容:" + str1);Log.i("TAG", "订阅的Topic:" + topic);response(topic,1,"消息已收到");}@Override//在完成消息传递并且已收到所有确认时调用public void deliveryComplete(IMqttDeliveryToken token) {}@Overridepublic void connectComplete(boolean reconnect, String serverURI) {}@Override//当与服务器的连接丢失时调用此方法public void connectionLost(Throwable cause) {// 失去连接,重连}
}//响应 (收到服务端户端的消息后,响应给对方告知消息已到达或者消息有问题等)
public void response(String topic,int qos,String message) {Boolean retained = false;try {//参数分别为:主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息mqttAndroidClient.publish(topic, message.getBytes(), qos.intValue(), retained.booleanValue());} catch (MqttException e) {e.printStackTrace();}
}

.

MQTT的使用

写一个 Service 类来调用上面的MQTTManager类中的方法就可以实现MQTT的功能了,具体怎样写,这里就不做介绍了,就是直接调用方法就行了。

.

.

参考资料

  • MQTT Android API文档

  • MQTT中文网

  • MQTT Android Github地址

  • Android APP必备高级功能,消息推送之MQTT

  • Android消息推送MQTT实战

MQTT Android客户端的使用介绍相关推荐

  1. android mqtt服务器搭建,Mqtt从服务端到Android客户端搭建(mqtt服务端搭建)

    一.简介 MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议. 此处不再引入官方文字描述,以个人开发认识浅谈一下 本文分为两部分: 1. M ...

  2. mqtt android封装,Android之MQTT封装使用

    一.MQTT协议介绍 客户机较小并且 MQTT 协议高效地使用网络带宽,在这个意义上,其为轻量级.MQTT 协议支持可靠的传送和即发即弃的传输. 在此协议中,消息传送与应用程序脱离. 脱离应用程序的程 ...

  3. android手机照片传苹果电脑版,为知笔记Android/iPhone客户端图片传到电脑客户端的方法介绍...

    为知笔记是一款时下流行的支持多平台的云笔记软件,随时随地记录和查看有价值的信息,非常方便.当我们在用为知笔记电脑客户端编辑笔记时,常有从手机相册中取图片素材的需求,下面小编就来教教大家为知笔记手机传图 ...

  4. 上门洗车APP --- Android客户端开发 之 网络框架封装介绍(一)

    上门洗车APP --- Android客户端开发 之 网络框架封装介绍(一) 上篇文章中给大家简单介绍了一些业务,上门洗车APP --- Android客户端开发 前言及业务简介,本篇文章给大家介绍下 ...

  5. 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(十)使用domoticz+mosquitto+Android客户端实现控制STM32板上的LED(一)

    本文将在前面mini2440建立的domoticz.mosquitto为服务器的基础上,以Android做远程客户端来实现对STM32芯片的开发板的LED进行灯控制,当然,这是一个基本功能的实现,如果 ...

  6. android将拦截短信通过邮箱发送,网易邮箱Android客户端推出 加速布局移动互联网...

    继网易邮箱5.0版本发布后,网易邮件事业部又迅速推出重要的移动互联网战略产品--网易邮箱Android客户端.此前,网易在移动端上已陆续推出适配iPhone/iPad/Android系统的网页版智能邮 ...

  7. Android客户端与服务器之间的通信

    本文将介绍Android客户端与服务器端的通信的简单实现方法. 要两点需要注意的地方: 1.Android 端记得在AndroidManifest.xml里记得获取一下网络权限,否则无法进行网络通信, ...

  8. Tsung MQTT协议简介及MQTT xml文档配置介绍

    MQTT协议简介及MQTT xml文档配置介绍 by:授客 QQ:1033553122 1. MQTT协议介绍 MQTT(Message Queuing Telemetry Transport,消息队 ...

  9. 行代码入门python_新浪微博Android客户端开发视频教程(36讲)

    教程名称:新浪微博Android客户端开发视频教程(36讲) 课程目录: [IT教程网]新浪微博Android客户端介绍 [IT教程网]新浪微博Android客户端相关资料 [IT教程网]新浪微博An ...

最新文章

  1. werkzeug中服务器处理请求的实现
  2. 【转】匈牙利命名法(Hungarian Notation)
  3. elasticsearch 6.2.3 从零开始配置
  4. 简单的封装axios 不包含状态码和提示
  5. IMail邮件服务-1
  6. Linux——分区时出现This partition should be marked for use as an EFI boot partition
  7. 标识符的命名规定java 0126
  8. java smtp pop3_POP3/SMTP指令
  9. DataTable两列转换四列
  10. 【sklearn第二十一讲】矩阵分解问题
  11. mysql 命令 kill_详解mysql数据库实用工具--percona-toolkit的7大分类
  12. 【图像处理】基于matlab GUI图像滤镜(马赛克+蓝色透镜+素描)【含Matlab源码 1145期】
  13. 2021qq服务器维护到什么时候,2021QQ扩列下架了吗怎么没了?QQ暂停服务到什么时候...
  14. 什么是事实表和维度表?什么是维度和度量?
  15. win7专业版设置通电自启动
  16. 聊聊龙芯Java开源
  17. python基础-古诗词填词游戏
  18. 麒麟座IIC-STM32F103RET6(1)-完成基础LED
  19. IIS开启伪静态后html静态页面无法访问的解决方法
  20. DWA动态窗口法的原理及应用

热门文章

  1. cursor设置为自定义图片
  2. 四档开启!windows7系统下载全新体验来袭!
  3. golang-阅读雨痕大神的Go语言学习笔记的心得
  4. 百度人工智能AIP的调用方法
  5. lol服务器4月2日维修公告,lol维护公告最新
  6. Bootstrap Table 中文API 详情
  7. 红米k30 android版本,红米K30至尊版VS红米K30Pro:入手Pro版其实没啥后悔的
  8. Python如何使用Tkinter模块实现简单窗口化
  9. 上传小说《失恋33天》 搜狐网等六家网站被诉侵权
  10. 关于程序猿的经典段子:杀一个程序员不需用枪,改三次需求即可