Thursday, 25 August 2016

Android MQTT Client example Part-2



  In last post we have discuss about ,What is Mqtt and how to publish message using MQTT.Here I am going to explain how to receive message using Mqtt

MQTTService.class

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.net.ConnectivityManager;
import android.app.Service;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import  android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import org.eclipse.paho.client.mqttv3.IMqttAsyncClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
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.MqttSecurityException;
import org.eclipse.paho.client.mqttv3.internal.ExceptionHelper;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.io.UnsupportedEncodingException;
import java.security.spec.ECField;

/**
 * Created by AS0060 on 8/24/2016.
 */
public class MQTTService extends Service {

    private static final String TAG = "MQTTService";
    private static boolean hasWifi = false;
    private static boolean hasMmobile = false;
    private ConnectivityManager mConnMan;
    public static volatile IMqttAsyncClient mqttClient;
    private String deviceId;

    MQTTBroadcastReceiver broadcastReceiver;


    class MQTTBroadcastReceiver extends BroadcastReceiver {

        MQTTBroadcastReceiver() {

        }


        @Override
        public void onReceive(Context context, Intent intent) {


            IMqttToken token;


            boolean hasConnectivity = false;
            boolean hasChanged = false;
            NetworkInfo infos[] = mConnMan.getAllNetworkInfo();

            for (int i = 0; i < infos.length; i++) {
                if (infos[i].getTypeName().equalsIgnoreCase("MOBILE")) {
                    if ((infos[i].isConnected() != hasMmobile)) {
                        hasChanged = true;
                        hasMmobile = infos[i].isConnected();
                    }
                 
                } else if (infos[i].getTypeName().equalsIgnoreCase("WIFI")) {
                    if ((infos[i].isConnected() != hasWifi)) {
                        hasChanged = true;
                        hasWifi = infos[i].isConnected();
                    }
                   
                }
            }

            hasConnectivity = hasMmobile || hasWifi;

            if (hasConnectivity && hasChanged && (mqttClient == null || !mqttClient.isConnected()))
           {
                doConnect();
            } else if (!hasConnectivity && mqttClient != null && mqttClient.isConnected()) {

                try {
                    token = mqttClient.disconnect();
                    token .waitForCompletion(1000);
                } catch (MqttException e) {
                    e.printStackTrace();
                }
            }
        }

    }



    public class MQTTBinder extends Binder {
        public MQTTService getService() {
            return MQTTService.this;
        }
    }



    @Override
    public void onCreate()
    {
        IntentFilter intentf = new IntentFilter();
        setClientID();
        broadcastReceiver = new MQTTBroadcastReceiver();
        intentf.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(broadcastReceiver,
        new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 
        mConnMan = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);                                                                                    
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Log.d(TAG, "onConfigurationChanged()");
        android.os.Debug.waitForDebugger();
        super.onConfigurationChanged(newConfig);

    }

    private void setClientID() {
        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 
        WifiInfo wInfo = wifiManager.getConnectionInfo();
        deviceId = wInfo.getMacAddress();
        if (deviceId == null) {
            deviceId = MqttAsyncClient.generateClientId();
        }
    }

    private void doConnect()
    {
       
        IMqttToken token;
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(true);
        try {
            mqttClient = new MqttAsyncClient("tcp://test.mosquitto.org:1883",                                                               deviceId, new MemoryPersistence());
            token= mqttClient.connect();
            token.waitForCompletion(3500);
            mqttClient.setCallback(new MqttEventCallback());
            token = mqttClient.subscribe("test", 1);
            token.waitForCompletion(5000);
        } catch (MqttSecurityException e) {
            e.printStackTrace();
        } catch (MqttException e) {
            doConnect();
            switch (e.getReasonCode()) {
                case MqttException.REASON_CODE_BROKER_UNAVAILABLE:
                case MqttException.REASON_CODE_CLIENT_TIMEOUT:
                case MqttException.REASON_CODE_CONNECTION_LOST:
                case MqttException.REASON_CODE_SERVER_CONNECT_ERROR:
                    Log.v(TAG, "c" + e.getMessage());
                    e.printStackTrace();
                    break;
                case MqttException.REASON_CODE_FAILED_AUTHENTICATION:
                    Intent i = new Intent("ANDROIDDHINA");
                    i.putExtra("ALLARM", e);
                    Log.e(TAG, "b" + e.getMessage());
                    break;
                default:
                    Log.e(TAG, "a" + e.getMessage());
            }
        }
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.v(TAG, "onStartCommand()");


        return START_STICKY;
    }

    private class MqttEventCallback implements MqttCallback {

        @Override
        public void connectionLost(Throwable arg0) {


        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {

        }

        @Override
        @SuppressLint("NewApi")
        public void messageArrived(String topic, final MqttMessage msg
        throws Exception {

            Handler h = new Handler(getMainLooper());
            h.post(new Runnable() {
                @Override
                public void run() {

                Toast.makeText(getApplicationContext(), "MQTT Message:\n" +new String(msg.getPayload()),Toast.LENGTH_SHORT).show();                   
                }
            });
        }
    }


    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "onBind called");
        return null;
    }

   

}



AndroidManifest.xml


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

 <service android:name=".MQTTService"></service>


Happy Coding:)