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
@@ -40,7 +41,8 @@ import javax.net.ssl.TrustManagerFactory
40
41
*/
41
42
class MqttAndroidClient @JvmOverloads constructor(
42
43
val context : Context , private val serverURI : String , private val clientId : String , ackType : Ack = Ack .AUTO_ACK ,
43
- private var persistence : MqttClientPersistence ? = null ) :
44
+ private var persistence : MqttClientPersistence ? = null
45
+ ) :
44
46
BroadcastReceiver (), IMqttAsyncClient {
45
47
46
48
// Listener for when the service is connected or disconnected
@@ -195,7 +197,13 @@ class MqttAndroidClient @JvmOverloads constructor(
195
197
* The actual connection depends on the service, which we start and bind to here, but which we can't actually use until the serviceConnection
196
198
* onServiceConnected() method has run (asynchronously), so the connection itself takes place in the onServiceConnected() method
197
199
*/
198
- if (mqttService == null ) { // First time - must bind to the service
200
+ val isRunning = isMqServiceRunning()
201
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
202
+ Timber .d(" isRunning=$isRunning ${mqttService?.connections?.size} foregroundServiceType=${mqttService?.foregroundServiceType} " )
203
+ } else
204
+ Timber .d(" isRunning=$isRunning ${mqttService?.connections?.size} " )
205
+
206
+ if (mqttService == null || mqttService?.connections?.size == 0 ) { // First time - must bind to the service
199
207
val serviceStartIntent = Intent ()
200
208
serviceStartIntent.setClassName(context, SERVICE_NAME )
201
209
var service: Any? = null
@@ -235,6 +243,12 @@ class MqttAndroidClient @JvmOverloads constructor(
235
243
return token
236
244
}
237
245
246
+ private fun isMqServiceRunning (): Boolean {
247
+ val manager = context.getSystemService(Context .ACTIVITY_SERVICE ) as ActivityManager
248
+ return manager.getRunningServices(Integer .MAX_VALUE )
249
+ .any { it.service.className == SERVICE_NAME }
250
+ }
251
+
238
252
private fun registerReceiver (receiver : BroadcastReceiver ) {
239
253
val filter = IntentFilter ()
240
254
filter.addAction(MqttServiceConstants .CALLBACK_TO_ACTIVITY )
@@ -247,13 +261,13 @@ class MqttAndroidClient @JvmOverloads constructor(
247
261
*/
248
262
private fun doConnect () {
249
263
if (clientHandle == null ) {
250
- clientHandle = mqttService!! .getClient(serverURI, clientId, context.applicationInfo.packageName, persistence)
264
+ clientHandle = mqttService? .getClient(serverURI, clientId, context.applicationInfo.packageName, persistence)
251
265
}
252
- mqttService!! .isTraceEnabled = traceEnabled
253
- mqttService!! .setTraceCallbackId(clientHandle)
266
+ mqttService? .isTraceEnabled = traceEnabled
267
+ mqttService? .setTraceCallbackId(clientHandle)
254
268
val activityToken = storeToken(connectToken)
255
269
try {
256
- mqttService!! .connect(clientHandle!! , clientConnectOptions, activityToken)
270
+ mqttService? .connect(clientHandle!! , clientConnectOptions, activityToken)
257
271
} catch (e: Exception ) {
258
272
val listener = connectToken!! .actionCallback
259
273
listener?.onFailure(connectToken, e)
@@ -271,9 +285,26 @@ class MqttAndroidClient @JvmOverloads constructor(
271
285
* @see .disconnect
272
286
*/
273
287
override fun disconnect (): IMqttToken {
288
+ val isRunning = isMqServiceRunning()
289
+ Timber .d(" isRunning=$isRunning ${mqttService?.connections?.size} " )
290
+
274
291
val token: IMqttToken = MqttTokenAndroid (this , null , null )
275
292
val activityToken = storeToken(token)
276
- mqttService!! .disconnect(clientHandle!! , null , activityToken)
293
+ clientHandle?.let {
294
+ mqttService?.disconnect(it, null , activityToken)
295
+ }
296
+
297
+ // if there are no more connections, we can shutdown the service
298
+ if (mqttService?.connections?.isEmpty() == true ) {
299
+ Timber .d(" Shutdown service" )
300
+ // For < Android O this should work (untested)
301
+ val myService = Intent (context, MqttService ::class .java)
302
+ context.stopService(myService)
303
+ // For Android O it's probably enough
304
+ mqttService!! .stopForeground(true )
305
+
306
+ // unregisterResources()
307
+ }
277
308
return token
278
309
}
279
310
@@ -293,7 +324,7 @@ class MqttAndroidClient @JvmOverloads constructor(
293
324
override fun disconnect (quiesceTimeout : Long ): IMqttToken {
294
325
val token: IMqttToken = MqttTokenAndroid (this , null , null )
295
326
val activityToken = storeToken(token)
296
- mqttService!! .disconnect(clientHandle!! , quiesceTimeout, null , activityToken)
327
+ mqttService? .disconnect(clientHandle!! , quiesceTimeout, null , activityToken)
297
328
return token
298
329
}
299
330
@@ -311,7 +342,7 @@ class MqttAndroidClient @JvmOverloads constructor(
311
342
override fun disconnect (userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
312
343
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback)
313
344
val activityToken = storeToken(token)
314
- mqttService!! .disconnect(clientHandle!! , null , activityToken)
345
+ mqttService? .disconnect(clientHandle!! , null , activityToken)
315
346
return token
316
347
}
317
348
@@ -345,7 +376,7 @@ class MqttAndroidClient @JvmOverloads constructor(
345
376
override fun disconnect (quiesceTimeout : Long , userContext : Any? , callback : IMqttActionListener ): IMqttToken {
346
377
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback)
347
378
val activityToken = storeToken(token)
348
- mqttService!! .disconnect(clientHandle!! , quiesceTimeout, null , activityToken)
379
+ mqttService? .disconnect(clientHandle!! , quiesceTimeout, null , activityToken)
349
380
return token
350
381
}
351
382
@@ -406,7 +437,7 @@ class MqttAndroidClient @JvmOverloads constructor(
406
437
message.isRetained = retained
407
438
val token = MqttDeliveryTokenAndroid (this , userContext, callback, message)
408
439
val activityToken = storeToken(token)
409
- val internalToken = mqttService!! .publish(clientHandle!! , topic, payload, QoS .valueOf(qos), retained, null , activityToken)
440
+ val internalToken = mqttService? .publish(clientHandle!! , topic, payload, QoS .valueOf(qos), retained, null , activityToken)
410
441
token.setDelegate(internalToken)
411
442
return token
412
443
}
@@ -468,7 +499,7 @@ class MqttAndroidClient @JvmOverloads constructor(
468
499
override fun publish (topic : String , message : MqttMessage , userContext : Any? , callback : IMqttActionListener ? ): IMqttDeliveryToken {
469
500
val token = MqttDeliveryTokenAndroid (this , userContext, callback, message)
470
501
val activityToken = storeToken(token)
471
- val internalToken = mqttService!! .publish(clientHandle!! , topic, message, null , activityToken)
502
+ val internalToken = mqttService? .publish(clientHandle!! , topic, message, null , activityToken)
472
503
token.setDelegate(internalToken)
473
504
return token
474
505
}
@@ -520,7 +551,7 @@ class MqttAndroidClient @JvmOverloads constructor(
520
551
override fun subscribe (topic : String , qos : Int , userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
521
552
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback, arrayOf(topic))
522
553
val activityToken = storeToken(token)
523
- mqttService!! .subscribe(clientHandle!! , topic, QoS .valueOf(qos), null , activityToken)
554
+ mqttService? .subscribe(clientHandle!! , topic, QoS .valueOf(qos), null , activityToken)
524
555
return token
525
556
}
526
557
@@ -624,7 +655,7 @@ class MqttAndroidClient @JvmOverloads constructor(
624
655
override fun subscribe (topic : Array <String >, qos : IntArray , userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
625
656
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback, topic)
626
657
val activityToken = storeToken(token)
627
- mqttService!! .subscribe(clientHandle!! , topic, qos, null , activityToken)
658
+ mqttService? .subscribe(clientHandle!! , topic, qos, null , activityToken)
628
659
return token
629
660
}
630
661
@@ -703,7 +734,7 @@ class MqttAndroidClient @JvmOverloads constructor(
703
734
): IMqttToken {
704
735
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback, topicFilters)
705
736
val activityToken = storeToken(token)
706
- mqttService!! .subscribe(clientHandle!! , topicFilters, qos.map { QoS .valueOf(it) }.toTypedArray(), null , activityToken, messageListeners)
737
+ mqttService? .subscribe(clientHandle!! , topicFilters, qos.map { QoS .valueOf(it) }.toTypedArray(), null , activityToken, messageListeners)
707
738
return token
708
739
}
709
740
@@ -741,7 +772,7 @@ class MqttAndroidClient @JvmOverloads constructor(
741
772
override fun unsubscribe (topic : String , userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
742
773
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback)
743
774
val activityToken = storeToken(token)
744
- mqttService!! .unsubscribe(clientHandle!! , topic, null , activityToken)
775
+ mqttService? .unsubscribe(clientHandle!! , topic, null , activityToken)
745
776
return token
746
777
}
747
778
@@ -772,7 +803,7 @@ class MqttAndroidClient @JvmOverloads constructor(
772
803
override fun unsubscribe (topic : Array <String >, userContext : Any? , callback : IMqttActionListener ? ): IMqttToken {
773
804
val token: IMqttToken = MqttTokenAndroid (this , userContext, callback)
774
805
val activityToken = storeToken(token)
775
- mqttService!! .unsubscribe(clientHandle!! , topic, null , activityToken)
806
+ mqttService? .unsubscribe(clientHandle!! , topic, null , activityToken)
776
807
return token
777
808
}
778
809
@@ -903,7 +934,7 @@ class MqttAndroidClient @JvmOverloads constructor(
903
934
} else if (MqttServiceConstants .TRACE_ACTION == action) {
904
935
traceAction(data)
905
936
} else {
906
- mqttService!! .traceError(" Callback action doesn't exist." )
937
+ mqttService? .traceError(" Callback action doesn't exist." )
907
938
}
908
939
}
909
940
@@ -918,7 +949,7 @@ class MqttAndroidClient @JvmOverloads constructor(
918
949
*/
919
950
fun acknowledgeMessage (messageId : String ): Boolean {
920
951
if (messageAck == Ack .MANUAL_ACK ) {
921
- val status = mqttService!! .acknowledgeMessageArrival(clientHandle!! , messageId)
952
+ val status = mqttService? .acknowledgeMessageArrival(clientHandle!! , messageId)
922
953
return status == Status .OK
923
954
}
924
955
return false
@@ -1008,7 +1039,7 @@ class MqttAndroidClient @JvmOverloads constructor(
1008
1039
(token as MqttTokenAndroid ).notifyFailure(exceptionThrown)
1009
1040
}
1010
1041
} else {
1011
- mqttService!! .traceError(" simpleAction : token is null" )
1042
+ mqttService? .traceError(" simpleAction : token is null" )
1012
1043
}
1013
1044
}
1014
1045
@@ -1066,15 +1097,15 @@ class MqttAndroidClient @JvmOverloads constructor(
1066
1097
callbacksList.forEach { callback ->
1067
1098
callback.messageArrived(destinationName, message)
1068
1099
}
1069
- mqttService!! .acknowledgeMessageArrival(clientHandle!! , messageId)
1100
+ mqttService? .acknowledgeMessageArrival(clientHandle!! , messageId)
1070
1101
} else {
1071
1102
message.messageId = messageId
1072
1103
callbacksList.forEach { callback ->
1073
1104
callback.messageArrived(destinationName, message)
1074
1105
}
1075
1106
}
1076
1107
} catch (e: Exception ) {
1077
- mqttService!! .traceError(" messageArrivedAction failed: $e " )
1108
+ mqttService? .traceError(" messageArrivedAction failed: $e " )
1078
1109
}
1079
1110
}
1080
1111
@@ -1157,7 +1188,7 @@ class MqttAndroidClient @JvmOverloads constructor(
1157
1188
* @param bufferOpts the DisconnectedBufferOptions
1158
1189
*/
1159
1190
override fun setBufferOpts (bufferOpts : DisconnectedBufferOptions ) {
1160
- mqttService!! .setBufferOpts(clientHandle!! , bufferOpts)
1191
+ mqttService? .setBufferOpts(clientHandle!! , bufferOpts)
1161
1192
}
1162
1193
1163
1194
override fun getBufferedMessageCount (): Int {
@@ -1169,7 +1200,7 @@ class MqttAndroidClient @JvmOverloads constructor(
1169
1200
}
1170
1201
1171
1202
override fun deleteBufferedMessage (bufferIndex : Int ) {
1172
- mqttService!! .deleteBufferedMessage(clientHandle!! , bufferIndex)
1203
+ mqttService? .deleteBufferedMessage(clientHandle!! , bufferIndex)
1173
1204
}
1174
1205
1175
1206
override fun getInFlightMessageCount () = 0
0 commit comments