1
1
package info.mqtt.android.service
2
2
3
+ import android.app.ActivityManager
3
4
import android.app.Notification
4
5
import android.content.*
5
6
import android.os.Build
@@ -202,7 +203,13 @@ class MqttAndroidClient @JvmOverloads constructor(
202
203
* The actual connection depends on the service, which we start and bind to here, but which we can't actually use until the serviceConnection
203
204
* onServiceConnected() method has run (asynchronously), so the connection itself takes place in the onServiceConnected() method
204
205
*/
205
- if (mqttService == null ) { // First time - must bind to the service
206
+ val isRunning = isMqServiceRunning()
207
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
208
+ Timber .d(" isRunning=$isRunning ${mqttService?.connections?.size} foregroundServiceType=${mqttService?.foregroundServiceType} " )
209
+ } else
210
+ Timber .d(" isRunning=$isRunning ${mqttService?.connections?.size} " )
211
+
212
+ if (mqttService == null || mqttService?.connections?.size == 0 ) { // First time - must bind to the service
206
213
val serviceStartIntent = Intent ()
207
214
serviceStartIntent.setClassName(context, SERVICE_NAME )
208
215
var service: Any? = null
@@ -239,6 +246,12 @@ class MqttAndroidClient @JvmOverloads constructor(
239
246
return token
240
247
}
241
248
249
+ private fun isMqServiceRunning (): Boolean {
250
+ val manager = context.getSystemService(Context .ACTIVITY_SERVICE ) as ActivityManager
251
+ return manager.getRunningServices(Integer .MAX_VALUE )
252
+ .any { it.service.className == SERVICE_NAME }
253
+ }
254
+
242
255
private fun collect () {
243
256
if (mqttService == null ) {
244
257
return
@@ -257,13 +270,13 @@ class MqttAndroidClient @JvmOverloads constructor(
257
270
*/
258
271
private fun doConnect () {
259
272
if (clientHandle == null ) {
260
- clientHandle = mqttService!! .getClient(serverURI, clientId, context.applicationInfo.packageName, persistence)
273
+ clientHandle = mqttService? .getClient(serverURI, clientId, context.applicationInfo.packageName, persistence)
261
274
}
262
- mqttService!! .isTraceEnabled = traceEnabled
263
- mqttService!! .setTraceCallbackId(clientHandle)
275
+ mqttService? .isTraceEnabled = traceEnabled
276
+ mqttService? .setTraceCallbackId(clientHandle)
264
277
val activityToken = storeToken(connectToken)
265
278
try {
266
- mqttService!! .connect(clientHandle!! , clientConnectOptions, activityToken)
279
+ mqttService? .connect(clientHandle!! , clientConnectOptions, activityToken)
267
280
} catch (e: Exception ) {
268
281
val listener = connectToken!! .actionCallback
269
282
listener?.onFailure(connectToken, e)
@@ -281,9 +294,26 @@ class MqttAndroidClient @JvmOverloads constructor(
281
294
* @see .disconnect
282
295
*/
283
296
override fun disconnect (): IMqttToken {
297
+ val isRunning = isMqServiceRunning()
298
+ Timber .d(" isRunning=$isRunning ${mqttService?.connections?.size} " )
299
+
284
300
val token: IMqttToken = MqttTokenAndroid (this , null , null )
285
301
val activityToken = storeToken(token)
286
- mqttService!! .disconnect(clientHandle!! , null , activityToken)
302
+ clientHandle?.let {
303
+ mqttService?.disconnect(it, null , activityToken)
304
+ }
305
+
306
+ // if there are no more connections, we can shutdown the service
307
+ if (mqttService?.connections?.isEmpty() == true ) {
308
+ Timber .d(" Shutdown service" )
309
+ // For < Android O this should work (untested)
310
+ val myService = Intent (context, MqttService ::class .java)
311
+ context.stopService(myService)
312
+ // For Android O it's probably enough
313
+ mqttService!! .stopForeground(true )
314
+
315
+ // unregisterResources()
316
+ }
287
317
return token
288
318
}
289
319
@@ -303,7 +333,7 @@ class MqttAndroidClient @JvmOverloads constructor(
303
333
override fun disconnect (quiesceTimeout : Long ): IMqttToken {
304
334
val token: IMqttToken = MqttTokenAndroid (this , null , null )
305
335
val activityToken = storeToken(token)
306
- mqttService!! .disconnect(clientHandle!! , quiesceTimeout, null , activityToken)
336
+ mqttService? .disconnect(clientHandle!! , quiesceTimeout, null , activityToken)
307
337
return token
308
338
}
309
339
@@ -321,7 +351,7 @@ class MqttAndroidClient @JvmOverloads constructor(
321
351
override fun disconnect (userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
322
352
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback)
323
353
val activityToken = storeToken(token)
324
- mqttService!! .disconnect(clientHandle!! , null , activityToken)
354
+ mqttService? .disconnect(clientHandle!! , null , activityToken)
325
355
return token
326
356
}
327
357
@@ -355,7 +385,7 @@ class MqttAndroidClient @JvmOverloads constructor(
355
385
override fun disconnect (quiesceTimeout : Long , userContext : Any? , callback : IMqttActionListener ): IMqttToken {
356
386
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback)
357
387
val activityToken = storeToken(token)
358
- mqttService!! .disconnect(clientHandle!! , quiesceTimeout, null , activityToken)
388
+ mqttService? .disconnect(clientHandle!! , quiesceTimeout, null , activityToken)
359
389
return token
360
390
}
361
391
@@ -416,7 +446,7 @@ class MqttAndroidClient @JvmOverloads constructor(
416
446
message.isRetained = retained
417
447
val token = MqttDeliveryTokenAndroid (this , userContext, callback, message)
418
448
val activityToken = storeToken(token)
419
- val internalToken = mqttService!! .publish(clientHandle!! , topic, payload, QoS .valueOf(qos), retained, null , activityToken)
449
+ val internalToken = mqttService? .publish(clientHandle!! , topic, payload, QoS .valueOf(qos), retained, null , activityToken)
420
450
token.setDelegate(internalToken)
421
451
return token
422
452
}
@@ -478,7 +508,7 @@ class MqttAndroidClient @JvmOverloads constructor(
478
508
override fun publish (topic : String , message : MqttMessage , userContext : Any? , callback : IMqttActionListener ? ): IMqttDeliveryToken {
479
509
val token = MqttDeliveryTokenAndroid (this , userContext, callback, message)
480
510
val activityToken = storeToken(token)
481
- val internalToken = mqttService!! .publish(clientHandle!! , topic, message, null , activityToken)
511
+ val internalToken = mqttService? .publish(clientHandle!! , topic, message, null , activityToken)
482
512
token.setDelegate(internalToken)
483
513
return token
484
514
}
@@ -530,7 +560,7 @@ class MqttAndroidClient @JvmOverloads constructor(
530
560
override fun subscribe (topic : String , qos : Int , userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
531
561
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback, arrayOf(topic))
532
562
val activityToken = storeToken(token)
533
- mqttService!! .subscribe(clientHandle!! , topic, QoS .valueOf(qos), null , activityToken)
563
+ mqttService? .subscribe(clientHandle!! , topic, QoS .valueOf(qos), null , activityToken)
534
564
return token
535
565
}
536
566
@@ -634,7 +664,7 @@ class MqttAndroidClient @JvmOverloads constructor(
634
664
override fun subscribe (topic : Array <String >, qos : IntArray , userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
635
665
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback, topic)
636
666
val activityToken = storeToken(token)
637
- mqttService!! .subscribe(clientHandle!! , topic, qos, null , activityToken)
667
+ mqttService? .subscribe(clientHandle!! , topic, qos, null , activityToken)
638
668
return token
639
669
}
640
670
@@ -713,7 +743,7 @@ class MqttAndroidClient @JvmOverloads constructor(
713
743
): IMqttToken {
714
744
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback, topicFilters)
715
745
val activityToken = storeToken(token)
716
- mqttService!! .subscribe(clientHandle!! , topicFilters, qos.map { QoS .valueOf(it) }.toTypedArray(), null , activityToken, messageListeners)
746
+ mqttService? .subscribe(clientHandle!! , topicFilters, qos.map { QoS .valueOf(it) }.toTypedArray(), null , activityToken, messageListeners)
717
747
return token
718
748
}
719
749
@@ -751,7 +781,7 @@ class MqttAndroidClient @JvmOverloads constructor(
751
781
override fun unsubscribe (topic : String , userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
752
782
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback)
753
783
val activityToken = storeToken(token)
754
- mqttService!! .unsubscribe(clientHandle!! , topic, null , activityToken)
784
+ mqttService? .unsubscribe(clientHandle!! , topic, null , activityToken)
755
785
return token
756
786
}
757
787
@@ -782,7 +812,7 @@ class MqttAndroidClient @JvmOverloads constructor(
782
812
override fun unsubscribe (topic : Array <String >, userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
783
813
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback)
784
814
val activityToken = storeToken(token)
785
- mqttService!! .unsubscribe(clientHandle!! , topic, null , activityToken)
815
+ mqttService? .unsubscribe(clientHandle!! , topic, null , activityToken)
786
816
return token
787
817
}
788
818
@@ -913,7 +943,7 @@ class MqttAndroidClient @JvmOverloads constructor(
913
943
} else if (MqttServiceConstants .TRACE_ACTION == action) {
914
944
traceAction(data)
915
945
} else {
916
- mqttService!! .traceError(" Callback action doesn't exist." )
946
+ mqttService? .traceError(" Callback action doesn't exist." )
917
947
}
918
948
}
919
949
@@ -928,7 +958,7 @@ class MqttAndroidClient @JvmOverloads constructor(
928
958
*/
929
959
fun acknowledgeMessage (messageId : String ): Boolean {
930
960
if (messageAck == Ack .MANUAL_ACK ) {
931
- val status = mqttService!! .acknowledgeMessageArrival(clientHandle!! , messageId)
961
+ val status = mqttService? .acknowledgeMessageArrival(clientHandle!! , messageId)
932
962
return status == Status .OK
933
963
}
934
964
return false
@@ -1018,7 +1048,7 @@ class MqttAndroidClient @JvmOverloads constructor(
1018
1048
(token as MqttTokenAndroid ).notifyFailure(exceptionThrown)
1019
1049
}
1020
1050
} else {
1021
- mqttService!! .traceError(" simpleAction : token is null" )
1051
+ mqttService? .traceError(" simpleAction : token is null" )
1022
1052
}
1023
1053
}
1024
1054
@@ -1076,15 +1106,15 @@ class MqttAndroidClient @JvmOverloads constructor(
1076
1106
callbacksList.forEach { callback ->
1077
1107
callback.messageArrived(destinationName, message)
1078
1108
}
1079
- mqttService!! .acknowledgeMessageArrival(clientHandle!! , messageId)
1109
+ mqttService? .acknowledgeMessageArrival(clientHandle!! , messageId)
1080
1110
} else {
1081
1111
message.messageId = messageId
1082
1112
callbacksList.forEach { callback ->
1083
1113
callback.messageArrived(destinationName, message)
1084
1114
}
1085
1115
}
1086
1116
} catch (e: Exception ) {
1087
- mqttService!! .traceError(" messageArrivedAction failed: $e " )
1117
+ mqttService? .traceError(" messageArrivedAction failed: $e " )
1088
1118
}
1089
1119
}
1090
1120
@@ -1167,7 +1197,7 @@ class MqttAndroidClient @JvmOverloads constructor(
1167
1197
* @param bufferOpts the DisconnectedBufferOptions
1168
1198
*/
1169
1199
override fun setBufferOpts (bufferOpts : DisconnectedBufferOptions ) {
1170
- mqttService!! .setBufferOpts(clientHandle!! , bufferOpts)
1200
+ mqttService? .setBufferOpts(clientHandle!! , bufferOpts)
1171
1201
}
1172
1202
1173
1203
override fun getBufferedMessageCount (): Int {
@@ -1179,7 +1209,7 @@ class MqttAndroidClient @JvmOverloads constructor(
1179
1209
}
1180
1210
1181
1211
override fun deleteBufferedMessage (bufferIndex : Int ) {
1182
- mqttService!! .deleteBufferedMessage(clientHandle!! , bufferIndex)
1212
+ mqttService? .deleteBufferedMessage(clientHandle!! , bufferIndex)
1183
1213
}
1184
1214
1185
1215
override fun getInFlightMessageCount () = 0
0 commit comments