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?