Introduction to MQTT Android client

Introduction to MQTT Android client

.

brief introduction

MQTT (Message Queuing Telemetry Transport) is an instant messaging protocol developed by IBM.

It is a publish / subscribe, extremely simple and lightweight messaging protocol designed for limited devices and low bandwidth, high latency or unreliable networks. Its design idea is light, open, simple, standardized and easy to implement. These characteristics make it a good choice for many scenarios, especially for limited environments, such as machine to machine communication (M2M) and Internet of things. Compared with XMPP, MQTT is more lightweight and occupies less broadband.

.

.

Introduction to MQTT architecture

network connections

The architecture provided to MQTT by the underlying transport protocol

  • The underlying transport protocol can connect the client and server
  • The underlying transport protocol provides an orderly, reliable, bidirectional byte stream

Application message

Refers to the application data transmitted in the network through MQTT. When the application message is transmitted through MQTT, it will be attached with quality of service (QoS) and topic name.

client

Refers to the program or equipment using MQTT. The client always connects to the server. It can

  • Publish application messages that other clients may be interested in
  • Subscribe to the application messages you are interested in
  • Unsubscribe application message
  • Disconnect from the server

Server

Act as an intermediary between clients who subscribe to or publish application messages. One server

  • Accept client's network connection
  • Accept application messages published by the client
  • Handle client subscription and unsubscribe requests
  • Forward application messages matching client subscriptions

subscribe

A subscription consists of a topic filter and a maximum QoS. A subscription can only be associated with one session. A session can contain multiple subscriptions. Each subscription has a different topic filter.

Topic name

It refers to the label attached to the application message, which is used by the server to match the subscription. The server sends a copy of application information to each matched client.

Topic filter

An expression contained in the subscription to represent one or more topics of interest. Topic filters can contain wildcards.

conversation

The interaction between a stateful client and a server. Some sessions depend on network connections, while others can span multiple continuous network connections between a client and a server.

MQTT control package

A packet containing certain information sent over a network connection. The MQTT specification defines 14 different types of control packets, one of which (PUBLISH packet) is used to transmit application information.

.

.

Advantages of MQTT

.

  1. Lightweight and efficient, minimizing resources required for client and network bandwidth

  2. Use publish / subscribe message mode to provide one to many message publishing and decouple applications

  3. Message transmission shielded from payload content

  4. Provide network connection using TCP/IP (persistent session)

  5. Use SSL/TLS to provide network security and trust

  6. It has a "will" function, which notifies the subscriber client to disconnect abnormally from the MQTT server

  7. Quality of service (QoS) levels can be specified to support message reliability

  • qos is 0: "at least once", and the message publishing completely depends on the underlying TCP/IP network. Message loss or duplication can occur. This level can be used in the following situations: it doesn't matter if the environment sensor data is lost, because there will be a second transmission in the near future
  • qos is 1: "at least once", which ensures that the message arrives, but message duplication may occur. This level can be used in the following situations. You need to get every message, and the repeated sending of messages has no impact on your usage scenario
  • qos is 2: "only once", which ensures that the message arrives once. This level can be used in the following situations. In the billing system, repeated or lost messages will lead to incorrect results

.

.

MQTT core parameter description:

.

  • Topic: it means "topic" in Chinese. Clients who subscribe to the same topic in MQTT will receive message push at the same time. Directly realize the "group chat" function

  • clientId: unique ID of the customer

  • qos: quality of service

  • retained: to retain the last disconnected information

  • userName: the user name to connect to the MQTT server

  • passWord: passWord to connect to MQTT server

.

.

Introduction to the main methods of MQTT:

.

1. connect() method

Function: connect to MQTT server

Parameter Description:

  • options: used to carry a series of parameters for connecting to the server, such as user name, password, etc.
  • userContext: optional object used to pass context to callback. Generally, it can be passed to null.
  • Callback: a callback used to monitor whether MQTT is successfully connected
 @Override
 public IMqttToken connect(MqttConnectOptions options, Object userContext,
   IMqttActionListener callback) throws MqttException {
    //...
}

.

2. publish() method

Function: publish messages and push messages to the server. Send a message to a topic, and then the server will push it to all customers who subscribe to this topic

Parameter Description:

  • Topic: the topic of the published message
  • payload: byte array of message contents
  • qos: provides the quality of service of messages, which can be transmitted to 0, 1 or 2
  • retained: whether to keep the last message after disconnection on the server
 @Override
 public IMqttDeliveryToken publish(String topic, byte[] payload, int qos,
   boolean retained) throws MqttException, MqttPersistenceException {
    //...
 }

.

3. subscribe() method

Role: subscribe to message topics

Parameter Description:

  • Topic: the topic of the subscription message
  • qos: the quality of service of subscription messages, which can be transmitted to 0, 1 or 2
 @Override
 public IMqttToken subscribe(String topic, int qos) throws MqttException,
   MqttSecurityException {
    //...
 }

.

.

Introduction to MQTT Android client

.

In the global build Add to gradle file

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

.

.

In the project build Add dependency to gradle file

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'
}

.

At androidmanifest XML add the following restrictions

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

.

At androidmanifest XML registration Service

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

.

The specific implementation is as follows:

public class MQTTManager {
	

    private final String TAG = "MQTTManager"

    private static MQTTManager instance = null;

    private String host = ""; //Server address (protocol + address + port number)
    private String userName = "";//User name to connect to MQTT server
    private String password = "";//Password to connect to MQTT server
	private String[] topics;//Subscribed 1 topic
	private String clientId ="";

    private MqttClient client;//mqtt client object
    private MqttConnectOptions conOpt;//MQTT connection option object
    
	//Callback of message
    private MqttCallback mCallback = new MyMqttCallback();

	//Double check lock mode of singleton
    public synchronized static MQTTManager getInstance() {
        if (instance == null) {
            instance = new MQTTManager();
        }
        return instance;
    }

	//Create connection (initialize MQTT client)
    public void createConnect(Context context, String host, String userName, String password, String[] topics) {

        this.host = host;
        this.userName = userName;
        this.password = password;


        //Client ID (unique identification number of the device, permission needs to be given first)

		if(getDeviceID(context) != ""){
			clientId = getDeviceID(context);
		}
		
		//Gets the temporary cache directory of the operating system
        String tmpDir = System.getProperty("java.io.tmpdir");

		//Data buffer
        MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(tmpDir);

        try {
			//Create an MQTT connection option object and initialize it
            conOpt = new MqttConnectOptions();

            conOpt.setCleanSession(true);// Clear cache
       		conOpt.setConnectionTimeout(10);//Set timeout in seconds
            conOpt.setKeepAliveInterval(20);// Heartbeat packet sending interval, unit: S
            conOpt.setAutomaticReconnect(true);//Set whether the client will automatically attempt to reconnect to the server if the connection is lost
			
			// User name and password
            if( password != null && userName != null) {

				conOpt.setUserName(userName);
                conOpt.setPassword(password.toCharArray()); 
            }

			//Create MQTT client object
            client = new MqttClient(host, clientId, dataStore);

            // Set MQTT to listen and accept messages
            client.setCallback(mCallback);

            if( topics != null) {
                this.topics = topics;
                client.subscribe(topics);
            }

        } catch (MqttException e) {
            e.printStackTrace();
        }

		//Connect to MQTT server
		doConnect();
    }


	//Connect to MQTT server
    public void doConnect() {
        if (client != null&& !mqttAndroidClient.isConnected() && isConnectIsNomarl()) {
            try {
		    /**
		     * options: It is used to carry a series of parameters for connecting to the server, such as user name, password, etc
		     * userContext: Optional object to pass context to the callback. Generally, it can be passed to null
		     * callback: Callback used to monitor whether MQTT is successfully connected
		     * */	
                client.connect(conOpt, null, iMqttActionListener);
          
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
  
    }

    //Callback to connect to the server
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {

        @Override
		//Connection successful
        public void onSuccess(IMqttToken arg0) {
            Log.i(TAG, "Connection successful ");
            try {
                // Subscribe to topics
                client.subscribe(topics,2);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        @Override
		 // Connection failed, reconnect
        public void onFailure(IMqttToken arg0, Throwable arg1) {
             
			doConnect()	//Connection failed, reconnect (you can shut down the server for simulation)

			 Log.i(TAG, "connection failed "+arg1.printStackTrace());
        }
    };


	//Re subscribe to topics
    public void subscribeTopics(String[] topics) throws MqttException {

		if(topics !=null){
			this.topics = topics;
		}
        
		/**
		 * topic: The subject of the subscription message
		 * qos: The quality of service of the subscription message can be transmitted to 0, 1 or 2
		 * */
        client.subscribe(topics,2);
    }



	//Publish message (true: indicates that the sending is successful; false: indicates that the sending fails)
    public boolean publish(String topicName, int qos, String msg) {
        try {

            if (client == null || !client.isConnected()) {
                return false;
            }

            //Create and configure messages
            MqttMessage message = null;
            try {
				//Initialize message object
                message = new MqttMessage(msg.getBytes("utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            message.setQos(qos);

		    /**
		     * topic: Subject of the announcement
		     * payload: Byte array of messages
		     * qos: Provides the quality of service of messages, which can be transmitted to 0, 1 or 2
		     * retained: Do you want to keep the last message after disconnection on the server
		     * */
            client.publish(topicName, message);
            return true;
        } catch (MqttException e) {
            Log.e("mq", e.toString());
        }
        return false;
    }

    //Cancel connection
    public void disConnect() throws MqttException {
        if (client != null && client.isConnected()) {
            client.disconnect();
        }
    }

	//Disconnect
    public void close() {
        if (client != null && client.isConnected()) {
            try {
                client.disconnect();
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

	//Get the device ID of the mobile phone as the ID of the MQTT client
    public static String getDeviceID(Context context) {

        TelephonyManager tm = (TelephonyManager) context.getSystemService(Activity.TELEPHONY_SERVICE);
        if (tm != null) {
            return tm.getDeviceId();
        }
        return "";
  	 	}

    //Judge whether the network is connected
    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, "Current network name:" + name);
            return true;
        } else {
            Log.i(TAG, "No network available");
            /*When there is no available network, delay 3 seconds before trying to reconnect*/
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    doConnect();
                }
            }, 3000);
            return false;
        }
    }
}

.

Callback to receive information sent by MQTT server

public class MyMqttCallback implements MqttCallbackExtended {

    @Override
    /**
     *This method is called when a message arrives from the server
     * topic:The name of the message subject is published to
     * message:Actual information
     * */
    public void messageArrived(String topic, MqttMessage message) throws Exception {

		String str1 = new String(message.getPayload());

		Log.i("TAG", "Receive content:" + str1);
		Log.i("TAG", "Subscribed Topic:" + topic);

		response(topic,1,"Message received");

    }

    @Override
	//Called when the message delivery is complete and all acknowledgments have been received
    public void deliveryComplete(IMqttDeliveryToken token) {

    }

    @Override
    public void connectComplete(boolean reconnect, String serverURI) {
    }

    @Override
	//This method is called when the connection to the server is lost
    public void connectionLost(Throwable cause) {

		// Lost connection

    }
}


//Response (after receiving the message from the server and the client, respond to inform the other party that the message has arrived or that there is a problem with the message, etc.)
public void response(String topic,int qos,String message) {
    Boolean retained = false;
    try {
        //The parameters are: subject, byte array of message, quality of service, and whether to keep the last message after disconnection in the server
        mqttAndroidClient.publish(topic, message.getBytes(), qos.intValue(), retained.booleanValue());
    } catch (MqttException e) {
        e.printStackTrace();
    }
}

.

Use of MQTT

Writing a Service class to call the methods in the above MQTTManager class can realize the function of MQTT. How to write it is not introduced here, but to call the methods directly.

.

.

reference material

Keywords: Java Android websocket

Added by ecg on Sun, 30 Jan 2022 18:54:56 +0200