4

I have an Android paho MQTT client that listens for sensor data and alerts the user in case of any threshold violation. I have the following in my app.gradle :

implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

I register it as a service in the manifest:

<service android:name="org.eclipse.paho.android.service.MqttService" />

The service receives MQTT messages even when the app is not in the foreground.

MqttConnectOptions options = new MqttConnectOptions();
options.setAutomaticReconnect(true);
options.setCleanSession(false);
client.connect(options);

My worry is, the phone battery will drain fast due to constant background syncing with the MQTT broker. So I want to unsubscribe, and disconnect from the server at the end of the day. I would prefer to discard all the messages that were received during the night.

Can someone please point me to a tutorial on how to do this correctly ? Just calling client.disconnect() results in multiple subscriptions and duplicate messages when I connect the next time. There must be a clean way to shut down and restart the service. Please suggest.

Raja
  • 994
  • 13
  • 15
  • Shutdown your service in `onPause()` – Alexander Farber Jul 17 '18 at 11:09
  • Tried that, and connected back in onResume(). I found two issues with this : Every time my mobile changes orientation, these are called repeatedly, and I end up with multiple callbacks for the same message. Secondly, it forces the application to remain in foreground. But I need to run the app in the background for several hours a day. – Raja Jul 18 '18 at 02:43
  • 1
    Don't use Paho Service then, instead write a custom [JobIntentService](https://developer.android.com/reference/android/support/v4/app/JobIntentService) and just use Paho client – Alexander Farber Jul 18 '18 at 08:47
  • Precisely ! JobIntentService is best suits to OneOff tasks but just case you have other requirements, for instance network and charger plugged JobScheduler is one possibility. Sometimes you cannot avoid to use foreground Services, and there is some to read about regarding Oreo Background Limits. – william gouvea Nov 27 '18 at 02:15
  • Likewise, you are able to shutdown your service with stopself() after some computation has been done or even in catch block if something goes wrong. – william gouvea Nov 27 '18 at 02:20

1 Answers1

2

Calling disconnect() should work as expected as far as your concerns about battery usage are concerned. You shouldn't need to micro-manage the service. I'm zeroing in on this part of your question because it seems you misunderstand how MQTT works:

Can someone please point me to a tutorial on how to do this correctly ? Just calling client.disconnect() results in multiple subscriptions and duplicate messages when I connect the next time. There must be a clean way to shut down and restart the service. Please suggest.

In short: I think what you are looking for is the "Clean Session Flag". You set this in the MqttConnectOptions object you pass to the MqttAndroidClient.connect() method. Once set, you will not get re-subscribed and a backlog of missed messages.

Example

MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);

mqttClient = new MqttAndroidClient(getApplicationContext(), brokerUrl, clientId)
mqttClient.connect(connOpts)

In detail: Having your subscriptions restored and receiving missed messages (of QOS > 0) when you re-connect a client is a feature of MQTT. Its not a result of the Android Paho client "staying connected" and caching the messages in the background, burning battery. It has to do with a feature of MQTT called Sessions. An MQTT Broker (or Server) will try to maintain and restore a session for you, identified by the Client ID when you re-establish a connection. This is the default behavior of MQTT. However, this can be disabled. The previous session can be purged if your connection request involves asking for a "Clean Session", that is, it will discard whatever topics you had previously and dump messages that have been held in the Broker, and start your connection off with a fresh, empty, "clean" session.

Bryan W
  • 163
  • 1
  • 7