0

I have created an MQTT client that is able to receive messages when app is open and when it is in the background but when i close the app it loses connection. I need it to stay connected as the messages that are being sent will launch my app. I have done some research and seen that creating a service would fix this. I've created the service but still it loses connection when app is closed and I cant figure out why. this is my MQTT service

    public class MQTTService extends Service {
        private MqttAndroidClient clientPhone;
        BroadcastReceiver m_ScreenOffReceiver;
        final String serverUri = "tcp://hairdresser.cloudmqtt.com:15767";
        final String clientId = "CarCrashDetection";
        final String subscriptionTopic = "Topic/+";
        final String username = "username";
        final String password = "password";


        public void     MQTTService() {
            clientPhone = new MqttAndroidClient(this, serverUri, clientId);
            clientPhone.setCallback(new MqttCallback() {
                public void connectComplete(boolean b, String s) {

                }
                @Override
                public void connectionLost(Throwable throwable) {

                }
                @Override
                public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
                    Log.w("Mqtt", mqttMessage.toString());
                    Log.e("message ", String.valueOf(mqttMessage));
                    Toast.makeText(MQTTService.this, "Crash Occurred", Toast.LENGTH_SHORT).show();
                    Intent dialogIntent = new Intent(MQTTService.this, alert.class);
                    dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(dialogIntent);
                }
                @Override
                public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

                }
            });
        }
        @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            throw new UnsupportedOperationException("Not yet implemented");
        }

        @Override
        public void onCreate() {
            super.onCreate();
            registerReceiver();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    MQTTService.this.MQTTService();
                }
            }).start();
        }


        public void setCallback(MqttCallback callback) {
            clientPhone.setCallback(callback);
        }
        private MqttConnectOptions getOptions(){
            MqttConnectOptions options = new MqttConnectOptions();

            if(clientPhone.getServerURI().contains("ssl")) {
                //set ssl config.for example:
                //options.setSocketFactory(clientPhone.getSSLSocketFactory(YOUR_KEYSTORE_FILE, "YOUR_KEYSTORE_PASSWORD"));
                //...
            }
            options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
            options.setAutomaticReconnect(true);
            options.setCleanSession(false);;
            //options.setWill(...);
            options.setUserName(username);
            options.setPassword(password.toCharArray());

            return options;
        }
        private void connectMQTT() {
            try {
                //getOptions is a method that returns your MqttConnectOptions object
                IMqttToken token = clientPhone.connect(getOptions());
                token.setActionCallback(new IMqttActionListener() {
                    @Override
                    public void onSuccess(IMqttToken asyncActionToken) {
                        //do something
                        DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
                        disconnectedBufferOptions.setBufferEnabled(true);
                        disconnectedBufferOptions.setBufferSize(100);
                        disconnectedBufferOptions.setPersistBuffer(false);
                        disconnectedBufferOptions.setDeleteOldestMessages(false);
                        clientPhone.setBufferOpts(disconnectedBufferOptions);
                        subscribeToTopic();
                    }
                    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
                    @Override
                    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                        //do something
                    }
                });
            } catch (MqttException e) {
                //do something
                e.printStackTrace();
            }
        }
        private void subscribeToTopic() {
            try {
                clientPhone.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
                    @Override
                    public void onSuccess(IMqttToken asyncActionToken) {
                        Log.w("Mqtt","Subscribed!");
                    }

                    @Override
                    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                        Log.w("Mqtt", "Subscribed fail!");
                    }
                });

            } catch (MqttException ex) {
                System.err.println("Exception whilst subscribing");
                ex.printStackTrace();
            }
        }
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            //do something
            return START_STICKY;
        }



        private void registerReceiver(){
            m_ScreenOffReceiver = new BroadcastReceiver(){
                @Override
                public void onReceive(final Context context, Intent intent){
                    //Log.d(TAG,"onReceive of Wifi_State_Change called");
                    if(intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION))
                    {
                        int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
                        if(wifiState != WifiManager.WIFI_STATE_ENABLED)
                            return;

                        final WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                                String ssid = wifiInfo.getSSID();

                                Toast.makeText(context, "active wifi:" + ssid, Toast.LENGTH_SHORT).show();

                                //You can connect to the your mqtt broker again:
                                connectMQTT();
                            }
                        }, 10000);
                    }
                }
            };

            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
            registerReceiver(m_ScreenOffReceiver, intentFilter);
        }
        @Override
        public void onDestroy() {
            if(clientPhone!=null) {
            /*unregisterResources is needed,otherwise receive this error:
              has leaked ServiceConnection org.eclipse.paho.android.service.MqttAndroidClient*/
                try {
                    clientPhone.unregisterResources();
                    clientPhone.close();
                    clientPhone.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            unregisterReceiver(m_ScreenOffReceiver);
            m_ScreenOffReceiver = null;

            super.onDestroy();
        }
    }

And I am calling it in my main Activity like so:

  Intent intent = new Intent(MainActivity.this, MQTTService.class);
        startService(intent);

Like I said it only loses connection when my app is closed and I thought this would fix it but I cant see where I am going wrong. Any suggestions?

ADM
  • 20,406
  • 11
  • 52
  • 83

0 Answers0