Whenever I encounter an error in the paho MQTT client, I attempt a reconnect 60 seconds later:
override fun connectionLost(cause: Throwable) {
LOG.e("Connection Lost :: $cause")
cleanupClient()
retry { connect() }
}
private fun cleanupClient(){
try {
for (i in topicList.indices) {
client!!.unsubscribe(topicList[i])
}
client!!.close()
client = null
} catch (e: Exception) {
LOG.e("Could not clean up!", e)
}
}
fun retry(cb: () -> Unit){
handler.removeCallbacksAndMessages(null)
handler.postDelayed({
cb()
}, 60000)
}
So if the app is sitting without internet, it will continuously attempt to reconnect until it finally does. The issue is that after a few hundred attempts (a couple hours), the app crashed with an Out of Memory Issue:
java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available
I only have 2 class-global variables, my handler and my MqttAndroidClient:
private var client: MqttAndroidClient? = null
// For retries
val handler = Handler()
And of those, only the client is ever re-assigned a value. My understanding is that in the clean up function, because I close and null out the client, the JVM should clean up my resources. The documentation for client.close():
Close the client. Releases all resource associated with the client. After the client has been closed it cannot be reused. For instance attempts to connect will fail.
There is also another function called unregisterResources()
Unregister receiver which receives intent from MqttService avoids IntentReceiver leaks.
It seems to me that only client.close() needs to be called, but I'm unsure if this will cause other issues.
And if there is anything else that you would suggest that I look at, I would love your advice!