0

I have an MQTT client that receives messages and should perform actions based on the message content. When the app is active - everything works as expected. However, when switched to a different app or the home screen, the actions do not happen, that is, the registered callback

mqtt.didReceiveMessage()

is not being executed. On the other hand, I can tell that the client stays connected and receives messages because (1) the broker's log does not show client disconnection and (2) once the app becomes active - the messages burst on the screen. Since the messages are qos0, they would have been dropped if the client was down. Another clue is from the CocoaMQTT source code, saying that the socket (I assume the one that maintains the connectivity) runs in background by default:

/// Enable backgounding socket if running on iOS platform. Default is true
///
/// - Note:
public var backgroundOnSocket: Bool

So, the messages seem to be stored somewhere in the system while the app is not active.

For this app, it is essential that the messages are parsed and the appropriate actions are taken at the time when the messages are received even if the app is not active.

What would be the (most optimal) approach to allow executing the didReceiveMessage() callback when the app is not active? It would be appreciated if someone could contrast different background app modes that could be appropriate in this case scenario.

XCode 12
Swift 5.6.1
Asperi
  • 228,894
  • 20
  • 464
  • 690
Nazar
  • 820
  • 5
  • 13
  • 36
  • You can't unless you abuse some other background mode such as audio playback or location updates. Network traffic isn't a supported case for background execution on iOS. Also, when you see that your connection is maintained, is this running under Xcode? Have you tried not running under Xcode? – Paulw11 Jun 21 '22 at 01:18
  • @Paulw11, so far I only tried in the simulator. How about the other messenger apps that trigger notifications when new message comes in? Aren't they running on the background? What would be the workaround for this limitation? – Nazar Jun 21 '22 at 01:25
  • They would be using push notifications. The operating system handles the display automatically. I think you will find that if you don't run under Xcode (Just tap the icon in the simulator) that your socket will disconnect when you background the app. Xcode changes the background behaviour of your app for debugging purposes. – Paulw11 Jun 21 '22 at 01:28
  • @Paulw11 you are right - when running on the device - the client disconnects. So, then how can I achieve my goal? Any ideas? I think this functionality is essential in many applications. – Nazar Jun 21 '22 at 01:35
  • You should use push notifications. That way the persistent network connection and the display of the notification is handled for you by the operating system. When the user opens your app, either from the icon or from the notification, you connect to your server to pull down any new messages. – Paulw11 Jun 21 '22 at 07:00
  • @Paulw11 How about Viber or WhatsApp? They are inactive, but they start "ringing" when someone is trying to reach you. Is this still carried via remote notifications mechanism? – Nazar Jun 21 '22 at 22:45
  • Yes. VoIP apps can use a special type of push called a VoIP Push or a PushKit push, but is is essentially the same thing – Paulw11 Jun 22 '22 at 03:26
  • @Paulw11 Since the MQTT connection is interrupted when the app enters background state, would it be reasonable to call disconnect() inside the willEnterBackground() ? But I cannot find this kind of function in app delegate. What would be the equivalent function that is called right before the app goes in the background state? – Nazar Jul 02 '22 at 00:16
  • There is `didEnterBackground`. You have a a second or so to execute some code in this method. – Paulw11 Jul 02 '22 at 13:49

0 Answers0