This is how I have implemented explicit forced ping as of now.
public class EnhancedMqttClient extends MqttClient {
protected static final String TAG_CLASS_NAME = EnhancedMqttClient.class
.getName();
private ExecutorService executor;
private Object lock = new Object();
public EnhancedMqttClient(Context context, String serverURI,
String clientId, MqttClientPersistence persistence)
throws MqttException {
super(serverURI, clientId, persistence);
aClient = new MyMqttAsyncClient(serverURI, clientId, persistence);
}
public void ping() throws MqttException {
try {
executor = Executors.newSingleThreadExecutor();
executor.submit(new PingExecutor()).get(10, TimeUnit.SECONDS);
} catch (TimeoutException e) {
Log.e(TAG_CLASS_NAME, "Ping Failure - Timeout");
disconnectForcibly(1000, 1000);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdownNow();
}
}
private class PingExecutor implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
MqttDeliveryToken token = new MqttDeliveryToken(getClientId());
token.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
System.out.println("Ping Success");
synchronized (lock) {
lock.notify();
}
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
System.out.println("Ping Failed");
try {
if (isConnected()) {
disconnectForcibly(1000, 1000);
}
} catch (MqttException e) {
e.printStackTrace();
}
}
});
MqttPingReq pingMsg = new MqttPingReq();
((MyMqttAsyncClient) aClient).getClientComms().sendNoWait(pingMsg, token);
synchronized (lock) {
lock.wait();
}
return true;
}
}
}
There are two issues with this implementation.
1) onFailure callback MqttDeliveryToken does not gets called every time ping fails. That's why I had to implement timer here with the help of ExecutorService.
2) On failure I call disconnectForcibly. It terminates all the mqtt callback threads and disconnect client as expected, but it does not make a call to mqtt callback connectionLost as there is no cause for shutdown here.
Please let me know if there is any better way to implement the same.