eclipse / paho.mqtt.android

MQTT Android
Other
2.89k stars 865 forks source link

AlarmPingSender is delayed in Android foreground service #449

Open slortz opened 3 years ago

slortz commented 3 years ago

Please fill out the form below before submitting, thank you!

Android API Version Bug Seen on: 29 Android Version Bug Seen on: 10

Please also check that if you have found the bug in the Release version (1.1.1) that you check that it also exists in the Snapshot (1.1.2-SNAPSHOT) before raising a bug.

Description of Bug:

We use MQTT for receiving messages in an Android foreground service, i.e., network and cpu are not cut off by doze or idle modes. Nevertheless, we experienced periodic disconnects every 100 seconds when the device was in doze mode. Immediately following the disconnect, the library automatically reconnected, creating the log pattern below.

It turned out that albeit running in a foreground service, scheduling the ping with

alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextAlarmInMilliseconds, pendingIntent);

caused the intent to be deferred for several minutes. Meanwhile, the server quit our connection after 100 seconds because it expected a ping (default every 60 seconds) that never came due to the delayed intent. However, since our service was running in foreground, the closed connection was detected immediately and it reconnected within seconds.

We were able to solve the problem for us by completely deactivating the keepalive messages.

mqttConnectOptions.setKeepAliveInterval(0);

Thus, the server doesn't expect pings and keeps the connection open forever. However, we cannot use the last-will feature this way. Probably it would also be possible to set a very long keep alive interval (> 20 min), that setExactAndAllowWhileIdle is guaranteed to fire its intent, but that would be hardly helpful to quickly detect connection losses.

In our experience, an alternative to setExactAndAllowWhileIdle that is still working exactly, even in doze mode, is to use the AlarmManager.AlarmClock to schedule an intent.

Console Log output (if available):

02-11 13:55:01.083 28998 30412 D AlarmPingSender: Unregister alarmreceiver to MqttService175b0190-44d9-4f45-86a5-a958d085c132
02-11 13:55:01.102 28998 30412 D AlarmPingSender: Schedule next alarm at 1613048101202
02-11 13:55:01.102 28998 30412 D AlarmPingSender: Alarm scheule using setExactAndAllowWhileIdle, next: 100
02-11 13:55:06.868 28998 30475 D AlarmPingSender: Register alarmreceiver to MqttServiceMqttService.pingSender.175b0190-44d9-4f45-86a5-a958d085c132
02-11 13:55:06.877 28998 30475 D AlarmPingSender: Schedule next alarm at 1613048166877
02-11 13:55:06.878 28998 30475 D AlarmPingSender: Alarm scheule using setExactAndAllowWhileIdle, next: 60000
02-11 13:56:41.088 28998 30475 D AlarmPingSender: Unregister alarmreceiver to MqttService175b0190-44d9-4f45-86a5-a958d085c132
02-11 13:56:41.109 28998 30475 D AlarmPingSender: Schedule next alarm at 1613048201208
02-11 13:56:41.109 28998 30475 D AlarmPingSender: Alarm scheule using setExactAndAllowWhileIdle, next: 100
02-11 13:56:46.833 28998 30496 D AlarmPingSender: Register alarmreceiver to MqttServiceMqttService.pingSender.175b0190-44d9-4f45-86a5-a958d085c132
02-11 13:56:46.843 28998 30496 D AlarmPingSender: Schedule next alarm at 1613048266843
02-11 13:56:46.844 28998 30496 D AlarmPingSender: Alarm scheule using setExactAndAllowWhileIdle, next: 60000
02-11 13:58:21.094 28998 30496 D AlarmPingSender: Unregister alarmreceiver to MqttService175b0190-44d9-4f45-86a5-a958d085c132
02-11 13:58:21.120 28998 30496 D AlarmPingSender: Schedule next alarm at 1613048301220
02-11 13:58:21.121 28998 30496 D AlarmPingSender: Alarm scheule using setExactAndAllowWhileIdle, next: 100
02-11 13:58:26.869 28998 30522 D AlarmPingSender: Register alarmreceiver to MqttServiceMqttService.pingSender.175b0190-44d9-4f45-86a5-a958d085c132
02-11 13:58:26.878 28998 30522 D AlarmPingSender: Schedule next alarm at 1613048366878
02-11 13:58:26.879 28998 30522 D AlarmPingSender: Alarm scheule using setExactAndAllowWhileIdle, next: 60000