Android APP must have advanced functionality, MQTT for message push

1. Several Ways to Implement Message Push on Android

  1. Polling: The client requests data from the server regularly. Pseudo-push. Disadvantage: Power consumption, flow consumption.
  2. Intercept text messages. When the server needs to send a notification to the client, it sends a short message. After receiving a specific short message, the client first gets the information, and then intercepts the short message. Pseudo-push. Disadvantage: expensive and text messages may be intercepted by security software.
  3. Push: Establish a long-term connection between the client and the server. Real push.  
    1. Google's C2DM (Cloudto Device Messaging). Need scientific Internet access, most users in China can not use it.
    2. XMPP. XMPP (Extensible Communication and Representation Protocol) is a protocol based on Extensible Markup Language (XML). androidpn is an open source java Android push notification implementation based on XMPP protocol. It includes a complete client and server side.
    3. MQTT. MQTT is a lightweight message publish/subscribe protocol, which is an ideal solution to realize message push server based on mobile client.

2. Introduction to MQTT

MQTT Official website: http://mqtt.org/

MQTT Introduction: http://www.ibm.com

MQTT Android github: https://github.com/eclipse/paho.mqtt.android

MQTT API: http://www.eclipse.org/paho/files/javadoc/index.html

MQTT android API:  http://www.eclipse.org/paho/files/android-javadoc/index.html

It is suggested that students with sufficient time read the five links in order. For those with insufficient time, please refer to the following brief introduction (most of the contents come from the five links above).

MQTT protocol
Clients are small and MQTT protocol uses network bandwidth efficiently, in this sense, it is lightweight. MQTT protocol supports reliable transmission and send-and-drop transmission. In this protocol, message delivery is separated from the application. The degree of disconnection from the application depends on how the MQTT client and MQTT server are written. Separate delivery frees applications from any server connection and waiting for messages. Interaction mode is similar to e-mail, but optimized in application programming.

The protocol has many different functions:

  • It is a publish/subscribe protocol.
  • In addition to providing one-to-many message distribution, publish/subscribe is also separated from the application. These functions are very useful for applications with multiple clients.
  • It has nothing to do with the content of the message.
  • It runs through TCP/IP, which provides basic network connections.
  • It provides three kinds of quality of service for messaging:
    • "At most once"
      Messages are delivered as best they can according to the underlying Internet protocol network. Messages may be lost.  
      For example, this quality of service is used with the communication environment sensor data. It does not matter whether individual reads are lost or whether new reads are published immediately.
    • "At least once"
      Ensure that the message arrives, but there may be duplication.
    • "Just once."
      Make sure you receive only one message.  
      For example, use this quality of service with an accounting system. Repeated or lost messages may cause inconvenience or charge for errors.
  • It is an economic way to manage message flow in a network. For example, fixed-length headings are only 2 bytes long, and protocol switching can minimize network traffic.
  • It has a "will" function that notifies the subscriber client of an unusual disconnection from the MQTT server. Please refer to“ Final news ” Release.

3. MQTT Server Construction

  1. click Here Download the Apollo server and install it after decompression.
  2. The command line goes into the installation directory bin directory (e.g. E:> CD E: MQTT apache-apollo-1.7.1 bin).
  3. Enter apollo create XXX (xxx is the name of the created server instance, example: apollo create mybroker), and then create a folder named XXX in the bin directory. Under the XXX folder, under the etc apollo. XML file is the file that configures server information. The etc users. properties file contains the user name and password used to connect to the MQTT server. The default is admin=password, that is, the account number is admin, and the password is password, which can be changed by itself.
  4. Enter the XXX/bin directory, enter apollo-broker.cmd run to start the server, and see the following interface represents the completion of the build

Then enter it in the browser http://127.0.0.1:61680/ To see if the installation was successful.

4. Implementation of MQTT Android Client

Basic concepts:

  • Topic: Chinese means "topic". Clients that subscribe to the same topic in MQTT receive a message push at the same time. Direct realization of the "group chat" function.
  • clientId: Unique identification of customer identity.
  • qos: quality of service.
  • retained: Keep the last disconnection information.
  • MqttAndroidClient#subscribe(): Subscribe to a topic.
  • MqttAndroidClient#publish(): Send a message to a topic, and then the server pushes it to all customers who subscribe to the topic.
  • userName: userName to connect to the MQTT server.
  • passWord: The passWord to connect to the MQTT server.

Adding dependencies

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

dependencies {
    compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
    compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.0'
}
  •  

Adding Limits

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

Registration Service

        <!-- Mqtt Service -->
        <service android:name="org.eclipse.paho.android.service.MqttService" />
        <service android:name="com.dongyk.service.MQTTService"/>
  •  

Implementation of Android

package com.dongyk.service;

import android.app.Service;
...

/**
 * MQTT Long Connection Service
 *
 * @author One mouthful: yikousamo@gmail.com
 * @version Creation time: 2016/9/16 22:06
 */
public class MQTTService extends Service {

    public static final String TAG = MQTTService.class.getSimpleName();

    private static MqttAndroidClient client;
    private MqttConnectOptions conOpt;

//    private String host = "tcp://10.0.2.2:61613";
    private String host = "tcp://192.168.1.103:61613";
    private String userName = "admin";
    private String passWord = "password";
    private static String myTopic = "topic";
    private String clientId = "test";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        init();
        return super.onStartCommand(intent, flags, startId);
    }

    public static void publish(String msg){
        String topic = myTopic;
        Integer qos = 0;
        Boolean retained = false;
        try {
            client.publish(topic, msg.getBytes(), qos.intValue(), retained.booleanValue());
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private void init() {
        // Server Address (Protocol + Address + Port Number)
        String uri = host;
        client = new MqttAndroidClient(this, uri, clientId);
        // Setting up MQTT listening and receiving messages
        client.setCallback(mqttCallback);

        conOpt = new MqttConnectOptions();
        // Clear Cache
        conOpt.setCleanSession(true);
        // Set timeout time in seconds
        conOpt.setConnectionTimeout(10);
        // Heart beat packet sending interval, in seconds
        conOpt.setKeepAliveInterval(20);
        // User name
        conOpt.setUserName(userName);
        // Password
        conOpt.setPassword(passWord.toCharArray());

        // last will message
        boolean doConnect = true;
        String message = "{\"terminal_uid\":\"" + clientId + "\"}";
        String topic = myTopic;
        Integer qos = 0;
        Boolean retained = false;
        if ((!message.equals("")) || (!topic.equals(""))) {
            // The Last Will
            try {
                conOpt.setWill(topic, message.getBytes(), qos.intValue(), retained.booleanValue());
            } catch (Exception e) {
                Log.i(TAG, "Exception Occured", e);
                doConnect = false;
                iMqttActionListener.onFailure(null, e);
            }
        }

        if (doConnect) {
            doClientConnection();
        }

    }

    @Override
    public void onDestroy() {
        try {
            client.disconnect();
        } catch (MqttException e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }

    /** Connect to MQTT server */
    private void doClientConnection() {
        if (!client.isConnected() && isConnectIsNomarl()) {
            try {
                client.connect(conOpt, null, iMqttActionListener);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

    }

    // Is MQTT Connected Successfully
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {

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

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            arg1.printStackTrace();
              // Connection failure, reconnection
        }
    };

    // MQTT listens and receives messages
    private MqttCallback mqttCallback = new MqttCallback() {

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {

            String str1 = new String(message.getPayload());
            MQTTMessage msg = new MQTTMessage();
            msg.setMessage(str1);
            EventBus.getDefault().post(msg);
            String str2 = topic + ";qos:" + message.getQos() + ";retained:" + message.isRetained();
            Log.i(TAG, "messageArrived:" + str1);
            Log.i(TAG, str2);
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {

        }

        @Override
        public void connectionLost(Throwable arg0) {
            // Lost connection, reconnect
        }
    };

    /** Determine whether the network is connected or not */
    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, "MQTT Current network name:" + name);
            return true;
        } else {
            Log.i(TAG, "MQTT No available network");
            return false;
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
  •  

First initialize the parameters, then connect to the server. After the connection is successful, the http://127.0.0.1:61680/ See the topic with the name "topic" created automatically. Here I use a real machine and a simulator to run the program. http://127.0.0.1:61680/ This is what the server sees.

There are two things to note here.
1. When the simulator runs, host = tcp://10.0.2.2:61613, because 10.0.2.2 is the specific IP set by the simulator and the alias of your computer. The host = tcp://192.168.1.103:61613 when the real machine is running. 192.168.1.103 is the IPv4 address of my host. The cmd command for viewing native IP is ipconfig/all.  
2. clientId cannot be the same at two runtimes (in order to ensure the uniqueness of customer identification).

Here for test In MQTT Service, a public method publish(String msg) is exposed to call MainActivity. The code is as follows

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);
        startService(new Intent(this, MQTTService.class));
        findViewById(R.id.publishBtn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                MQTTService.publish("CSDN A mouthful of steamed buns");
            }
        });
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void getMqttMessage(MQTTMessage mqttMessage){
        Log.i(MQTTService.TAG,"get message:"+mqttMessage.getMessage());
        Toast.makeText(this,mqttMessage.getMessage(),Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

}
  •  

EventBus 3.0 is used to send messages here. You can see what you are interested in. EventBus 3.0 usage and source code parsing . Of course, you can also use interface callbacks to even pop up Toast directly in Service. whatever, now click on Button in a client MainActivity, and both clients can pop up messages at the same time. get to the data. Next, show time~

Tags: Android Eclipse network simulator

Posted on Sat, 22 Jun 2019 11:20:32 -0700 by nileshkulkarni