问题
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
回答1:
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 ();
}
}
// ...
}
回答2:
I'm not sure but I think maybe a null check can help that
if (connection == null){
connections = new Connections();
connections.createConnectionForPublishing(context);
}
回答3:
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.
来源:https://stackoverflow.com/questions/42101259/mqtt-creates-multiple-connections-when-oncreate-is-called-more-than-once