com.ibm.pickmeup.utils.MqttHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.pickmeup.utils.MqttHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2014 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 *
 * The Eclipse Public License is available at
 *   http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 ******************************************************************************/
package com.ibm.pickmeup.utils;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
import org.json.JSONException;

/**
 * MqttHandler is a utils class that interacts with the MQTT service. Use this class to perform the
 * basic operations on the MQTT service such as connect, subscribe, unsubscribe and
 * publish.
 * <p/>
 * MqttHandler implements MqttCallback which allows it to process incoming message from the MQTT
 * service.
 */
public class MqttHandler implements MqttCallback {

    private final static String TAG = MqttHandler.class.getName();
    private static MqttHandler instance;
    private MqttAndroidClient client;
    private Context context;

    private MqttHandler(Context context) {
        this.context = context;
        initMqttConnection();
    }

    public static MqttHandler getInstance(Context context) {
        if (instance == null) {
            instance = new MqttHandler(context);
        }
        return instance;
    }

    /**
     * Initialisation method to create an MqttAndroidClient base on the connection preferences
     */
    private void initMqttConnection() {
        Log.d(TAG, ".initMqttConnection() entered");

        //connection setting are stored in SharedPreferences
        SharedPreferences settings = context.getSharedPreferences(Constants.SETTINGS, context.MODE_PRIVATE);
        String serverHost = settings.getString(Constants.SETTINGS_MQTT_SERVER, "");
        String serverPort = settings.getString(Constants.SETTINGS_MQTT_PORT, "");
        String clientId = settings.getString(Constants.SETTINGS_NAME, "");

        Log.d(TAG, ".initMqttConnection() - Host name: " + serverHost + ", Port: " + serverPort + ", client id: "
                + clientId);

        String connectionUri = "tcp://" + serverHost + ":" + serverPort;
        client = new MqttAndroidClient(context, connectionUri, clientId);
        client.setCallback(this);
    }

    /**
     * Connect MqttAndroidClient to the MQTT broker
     */
    public void connect() {
        Log.d(TAG, ".connect() entered");

        // check if client is already connected
        if (!isMqttConnected()) {
            // create ActionListener to handle connection results
            ActionListener listener = new ActionListener(context, Constants.ActionStateStatus.CONNECTING);
            // create MqttConnectOptions and set the clean session and the Last Will message
            MqttConnectOptions options = new MqttConnectOptions();
            options.setCleanSession(true);
            options.setWill(TopicFactory.getInstance(context).getPassengerTopLevelTopic(), new byte[0], 0, true);

            try {
                // connect
                client.connect(options, context, listener);
            } catch (MqttException e) {
                Log.e(TAG, "Exception caught while attempting to connect to server", e.getCause());
                if (e.getReasonCode() == (Constants.ERROR_BROKER_UNAVAILABLE)) {
                    // error while connecting to the broker - send an intent to inform the user
                    Intent actionIntent = new Intent(Constants.ACTION_INTENT_CONNECTIVITY_MESSAGE_RECEIVED);
                    actionIntent.putExtra(Constants.CONNECTIVITY_MESSAGE, Constants.ERROR_BROKER_UNAVAILABLE);
                    context.sendBroadcast(actionIntent);
                }
            }
        }
    }

    /**
     * Disconnect MqttAndroidClient from the MQTT broker
     */
    public void disconnect() {
        Log.d(TAG, ".disconnect() entered");

        // check if client is actually connected
        if (isMqttConnected()) {
            try {
                // disconnect
                client.disconnect();
            } catch (MqttException e) {
                Log.e(TAG, "Exception caught while attempting to disconnect from server", e.getCause());
            }
        }
    }

    /**
     * Subscribe MqttAndroidClient to a topic
     *
     * @param topic to subscribe to
     * @param qos   to subscribe with
     */
    public void subscribe(String topic, int qos) {
        Log.d(TAG, ".subscribe() entered");

        // check if client is connected
        if (isMqttConnected()) {
            try {
                // create ActionListener to handle subscription results
                ActionListener listener = new ActionListener(context, Constants.ActionStateStatus.SUBSCRIBE);
                Log.d(TAG, ".subscribe() - Subscribing to: " + topic + ", with QoS: " + qos);
                client.subscribe(topic, qos, context, listener);
            } catch (MqttException e) {
                Log.e(TAG, "Exception caught while attempting to subscribe to topic " + topic, e.getCause());
            }
        } else {
            handleMqttDisconnected();
        }
    }

    /**
     * Unsubscribe MqttAndroidClient from a topic
     *
     * @param topic to unsubscribe from
     */
    public void unsubscribe(String topic) {
        Log.d(TAG, ".unsubscribe() entered");

        // check if client is connected
        if (isMqttConnected()) {
            try {
                // create ActionListener to handle unsubscription results
                ActionListener listener = new ActionListener(context, Constants.ActionStateStatus.UNSIBSCRIBE);
                client.unsubscribe(topic, context, listener);
            } catch (MqttException e) {
                Log.e(TAG, "Exception caught while attempting to unsubscribe from topic " + topic, e.getCause());
            }
        } else {
            handleMqttDisconnected();
        }
    }

    /**
     * Publish message to a topic
     *
     * @param topic    to publish the message to
     * @param message  JSON object representation as a string
     * @param retained true if retained flag is requred
     * @param qos      quality of service (0, 1, 2)
     */
    public void publish(String topic, String message, boolean retained, int qos) {
        Log.d(TAG, ".publish() entered");

        // check if client is connected
        if (isMqttConnected()) {
            // create a new MqttMessage from the message string
            MqttMessage mqttMsg = new MqttMessage(message.getBytes());
            // set retained flag
            mqttMsg.setRetained(retained);
            // set quality of service
            mqttMsg.setQos(qos);
            try {
                // create ActionListener to handle message published results
                ActionListener listener = new ActionListener(context, Constants.ActionStateStatus.PUBLISH);
                Log.d(TAG, ".publish() - Publishing " + message + " to: " + topic + ", with QoS: " + qos
                        + " with retained flag set to " + retained);
                client.publish(topic, mqttMsg, context, listener);
            } catch (MqttPersistenceException e) {
                Log.e(TAG, "MqttPersistenceException caught while attempting to publish a message", e.getCause());
            } catch (MqttException e) {
                Log.e(TAG, "MqttException caught while attempting to publish a message", e.getCause());
            }
        } else {
            handleMqttDisconnected();
        }
    }

    /**
     * Helper method to handle situations when MQTT client is not connected while attempting
     * actions on the client
     */
    private void handleMqttDisconnected() {
        Log.d(TAG, ".handleMqttDisconnected() entered");
        Log.d(TAG, "MqttAndroidClient is not connected");

        // add error handling and reconnect logic
    }

    @Override
    public void connectionLost(Throwable throwable) {
        Log.d(TAG, ".connectionLost() entered");
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        Log.d(TAG, ".messageArrived() entered");
        String payload = new String(mqttMessage.getPayload());
        Log.d(TAG, ".messageArrived - Message received on topic " + topic + ": message is " + payload);
        try {
            // send the message through the application logic
            MessageConductor.getInstance(context).steerMessage(payload, topic);
        } catch (JSONException e) {
            Log.e(TAG, ".messageArrived() - Exception caught while steering a message", e.getCause());
            e.printStackTrace();
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        Log.d(TAG, ".deliveryComplete() entered");
    }

    /**
     * Checks if the MQTT client has an active connection
     */
    private boolean isMqttConnected() {
        Log.d(TAG, ".isMqttConnected() entered");
        boolean connected = false;
        try {
            if ((client != null) && (client.isConnected())) {
                connected = true;
            }
        } catch (Exception e) {
            // swallowing the exception as it means the client is not connected
        }
        Log.d(TAG, ".isMqttConnected() - returning " + connected);
        return connected;
    }
}