MQTT Creates Multiple connections when onCreate is

2019-07-27 03:45发布

I am creating an instant messaging system using Paho Android MQTT Client. Its implementation works as expected, however I am facing these errors.

I call the Connection Class ( This also calls for the creation of the connection to the broker) in the onCreate of the MainActivity Class.

Now the problem is that, assuming I am on the MainActivity Class and I press back to move from the MainActivity Class to another activity, and I later come back to the MainActivity Class, another broker connection will be created. This will mean that anytime a single message is published, the client will receive the message twice.

MainActivity.java:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.chat_intera);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    dbHelper = DatabaseManager.getInstance(context);
    //mRecyclerView = (RecyclerView) findViewById(R.id.history_recycler_view);

    connections = new Connections();
    connections.createConnectionForPublishing(context);

}


@Override
public void onDestroy() {
    super.onDestroy();
    System.out.println("LOG: Service destroyed");
}

}

Connection.java

public class Connection {

    public void createConnectionForPublishing (final Context context) {

        //Instantiate the mqtt android client class
        mqttAndroidClient = new MqttAndroidClient (context.getApplicationContext (), serverUri, clientId);


        mqttAndroidClient.setCallback (new MqttCallbackExtended () {

            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                if (reconnect) {
                    System.out.println ("Reconnected to : " + serverURI);
                } else {
                    System.out.println ("Connected to: " + serverURI);
                }
            }

            @Override
            public void connectionLost (Throwable cause) {
                System.out.println ("The Connection was lost.");
            }

            @Override
            public void messageArrived (String topic, final MqttMessage message) throws Exception {
                System.out.println ("Message received and Arrived");
            }

            @Override
            public void deliveryComplete (IMqttDeliveryToken token) {
                System.out.println("Message Delivered");
            }
        });

        final MqttConnectOptions mqttConnectOptions = new MqttConnectOptions (); 
        mqttConnectOptions.setMqttVersion (MqttConnectOptions.MQTT_VERSION_3_1_1);
        mqttConnectOptions.setAutomaticReconnect (true);
        mqttConnectOptions.setCleanSession (false);

        try {
            mqttAndroidClient.connect (mqttConnectOptions, null, new IMqttActionListener () {

                @Override
                public void onSuccess (IMqttToken asyncActionToken) {
                    System.out.println ("BROKER CONNECTED");

                    DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions ();
                    disconnectedBufferOptions.setBufferEnabled (true);
                    disconnectedBufferOptions.setBufferSize (100);
                    disconnectedBufferOptions.setPersistBuffer (false);
                    disconnectedBufferOptions.setDeleteOldestMessages (false);

                    //mqttAndroidClient.setBufferOpts (disconnectedBufferOptions);

                }

                @Override
                public void onFailure (IMqttToken asyncActionToken, Throwable exception) {
                    System.out.println ("Failed to connect to: " + serverUri);
                }
            });

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

    // ...
}

I am new to MQTT, I would be glad if somebody can help. Thanks in advance

3条回答
Evening l夕情丶
2楼-- · 2019-07-27 04:26

Then if you don't want to establish the connection multiple times you'll have to make it as singleton to have only 1 instance of the connection class and one time connection established.

So your code will become:

MainActivity.java:

public class MainActivity extends Activity {

    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
        setContentView (R.layout.chat_intera);

        Connection connection = Connection.getInstance (getApplicationContext ());
    }

    // ....
}

Connection.java

public class Connection {

    private       static Connection          connInst;
    private       static boolean             connected;

    private       static MqttAndroidClient   mqttAndroidClient;
    private       static IMqttActionListener mqttActionListener;
    private final static MqttConnectOptions  mqttConnectOptions = new MqttConnectOptions (); 
    static {
        mqttConnectOptions.setMqttVersion (MqttConnectOptions.MQTT_VERSION_3_1_1);
        mqttConnectOptions.setAutomaticReconnect (true);
        mqttConnectOptions.setCleanSession (false);
    }

    private Connection (Context context) {
        //Instantiate the mqtt android client class
        mqttAndroidClient = new MqttAndroidClient (context.getApplicationContext (), serverUri, clientId);

        mqttAndroidClient.setCallback (new MqttCallbackExtended () {

            @Override
            public void connectComplete (boolean reconnect, String serverURI) {
                connected = true;
                if (reconnect) {
                    System.out.println ("Reconnected to : " + serverURI);
                } else {
                    System.out.println ("Connected to: " + serverURI);
                }
            }

            @Override
            public void connectionLost (Throwable cause) {
                connected = false;
                System.out.println ("The Connection was lost.");
            }

            @Override
            public void messageArrived (String topic, final MqttMessage message) throws Exception {
                System.out.println ("Message received and Arrived");
            }

            @Override
            public void deliveryComplete (IMqttDeliveryToken token) {
                System.out.println("Message Delivered");
            }
        });

        mqttActionListener = new IMqttActionListener () {

            @Override
            public void onSuccess (IMqttToken asyncActionToken) {
                System.out.println ("BROKER CONNECTED");

                DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions ();
                disconnectedBufferOptions.setBufferEnabled (true);
                disconnectedBufferOptions.setBufferSize (100);
                disconnectedBufferOptions.setPersistBuffer (false);
                disconnectedBufferOptions.setDeleteOldestMessages (false);

                //mqttAndroidClient.setBufferOpts (disconnectedBufferOptions);

            }

            @Override
            public void onFailure (IMqttToken asyncActionToken, Throwable exception) {
                System.out.println ("Failed to connect to: " + serverUri);
            }
        });
    }

    public static Connection getInstance (Context context) {
        if (connInst == null) {
            connInst = new Connection (context);
        }
        createConnectionIfNeeded (context);

        return connInst;
    }

    private static void createConnectionIfNeeded () {
        if (connected) {
            return;
        }

        try {
            mqttAndroidClient.connect (mqttConnectOptions, null, mqttActionListener);

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

    // ...
}
查看更多
The star\"
3楼-- · 2019-07-27 04:27

I'm not sure but I think maybe a null check can help that

if (connection == null){
   connections = new Connections();
   connections.createConnectionForPublishing(context);
}
查看更多
Explosion°爆炸
4楼-- · 2019-07-27 04:32

I suggest that you set a flag using Android onPause()

https://developer.android.com/reference/android/app/Activity.html#onPause()

And then instead of using onCreate(), use onResume() to initiate your MQTT connection but check onPause() flag first.

You may also need to close the connection in onPause() or onDestroy(). Look at lifetime of an Android application/activity for more info.

查看更多
登录 后发表回答