SendBird Connection FAQ - External
Date: 2019-03-21
Prepared By: SendBird Solutions Engineering
Purpose
To provide details of SendBird’s SDK connection process and how SendBird’s SDK maintains a connection.
Questions
What is the difference between the connect() method and the SDK’s internal reconnection (reconnect()) functionality?
-
SendBird.connect() is a SDK method that should be called only when it is certain a manual connection is required and after the SDK has been initialized. For example:
-
When a user opens the application.
-
When a user clicks a button and enters the chat screen of the application.
-
When clicking on/touching a push notification.
-
Reconnect, in comparison, is an automatic internal function of the SendBird SDK which works to maintain a connection between the client and SendBird servers (further information regarding this is below):
-
In cases where the client app gets disconnected from the server and tries to reconnect at the SDK level, the SDK notifies the client app through the connection event handler.
-
The reconnect logic has event listeners which can be listened for in the implementation:
1. onReconnectStarted
1. On network failure the internet connected listener takes over.
2. Everytime the internet connects the reconnect logic restarts
2. onReconnectSucceeded
3. onReconnectFailed
1. All SDK operations are stopped.
2. In this case we recommend calling SendBird.reconnect(true) manually.
4. See the below diagram for how the logic works.
SendBird SDK internal reconnection logic
When should we call reconnect() manually?
- sb.reconnect() should be called only if the connection status is CLOSED , and if the user has successfully logged in at least once on the current SendBird Object.
- Connection status can be known by calling user.getConnectionStatus()
Why do I need to consider manually calling sb.disconnect() for Javascript only?
Both Android and iOS native applications provide straightforward indications of the application being in the foreground or background, and thus the SendBird SDK has a built in connect and disconnect processes. However, as JavaScript can exist in both browsers and as part of React Native it is not straight forward for the SDK to account for all of these environments. Therefore it is up to the implementation to decide when it is best to disconnect the user from SendBird.
Initialization
What happens when SendBird’s SDK is first initialized?
-
Before SendBird can connect, the SDK needs to be initialized.
-
Upon initialization, an object with core SendBird SDK methods is created in the memory of the client.
-
Initialization for each platform:
-
iOS
1. Swift → SBDMain.initWithApplicationId(APP_ID)
2. Objective-C → [SBDMain initWithApplicationId:APP_ID];
- Android
1. Java → SendBird.init(APP_ID, Context context);
- React Native and Javascript
1. JavaScript → const sb = new SendBird({appId: APP_ID});
- Unity
1. SendBirdClient.Init(APP_ID)
- After initialization is complete, connection to SendBird can be established by calling the SendBird.connect() method.
How many times should the SendBird SDK be initialized?
- Generally, only once during the lifetime of the app, as long as the core SDK object is maintained in application memory.
- Because the SDK’s instantiated object is a singleton, additional attempts to create a new instance will return a reference to the original instantiated object for Android and iOS.
- Once the JavaScript SDK is instantiated additional attempts to create a new instance with the same application Id will result in referencing the original instance. However, if one instance already exists then a second separate instance is created using a different app id, then both instances can exist at the same time. Note: This is not a recommended use of the JavaScript SDK.
Connecting
How does SendBird’s SDK maintain a connection to SendBird servers?
-
On calling sb.connect(), the SDK sends a WebSocket handshake request.
-
For Android and IOS native SDKs:
1. sb.connect() should be called whenever the app comes into the foreground and there is not yet a connected user.
2. For users' seamless chat experience, the iOS and Android SDK manages connections to SendBird servers at the application level.
3. The SDK’s connection and disconnection is called automatically when the application comes into the [foreground](https://docs.sendbird.com/ios/application#3_manage_connections_with_sendbird_server) or moves to the [background.](https://docs.sendbird.com/ios/application#3_manage_connections_with_sendbird_server)
- For the JavaScript SDK including React Native:
1. You should call the connect() or disconnect() methods explicitly depending on how you implement your use cases.
2. A user should be manually disconnected from SendBird server when the user no longer needs to receive messages from an online state.
3. sb.connect() should be called whenever the a React Native app comes into the foreground and there is not yet a connected user.
4. Additionally in React Native:
1. setBackground should be called if the app goes into the background.
2. setForeground should be called if the app come into the foreground.
5. Once connected, the SDK will stay connected as long as there is a browser tab/app using the SDK. sb.disconnect() can be called explicitly if needed. Disconnection only occurs automatically if the browser tab or app are closed completely.
-
On sb.connect() success, SendBird’s backend completes the handshake.
-
To maintain a connection, the SDK pings regularly if there is inactivity between the SDK and the SendBird server in order to keep the WebSocket open.
-
If a WebSocket connection is lost, the SDK automatically starts the reconnection process.
-
For iOS/Android and React Native applications that are in the foreground ( for React Native, after sb.connect() has been called), and for JS SDK applications that have browser tabs open and sb.connect() has been called.
1. As mentioned previously the SDK automatically listens to internet connectivity.
2. The SDK will automatically attempt to connect each time the internet reconnects.
- If a connection is lost, the SDK attempts reconnection 5 times before moving to a backoff period.
1. Reconnection is attempted at 0 secs (if connection is lost but the network is working), 3 secs, 6 secs, 12 secs, and 24 secs.
- The SDK provides event listeners for the reconnection process.
1. onReconnectStarted
2. onReconnectSucceeded
3. onReconnectFailed
-
The SDK also maintains connection.
-
When in the background for React Native applications.
1. It’s up to the implementation to call, setBackground manually.
2. When a browser tab is not visible. See “What are the best practices when implementing a browser based application?”, for more information.
-
Also, the SDK automatically listens to a devices actual internet connectivity not just the WebSocket connection. The SDK will automatically attempt to connect each time the device reconnects to the internet. The listening process starts right after the SendBird connection is lost.
-
For native applications:
-
The SDK’s disconnect parameter is updated automatically when the app goes into the background.
-
The disconnect state here will change the state of the WebSocket condition.
-
Regardless of the application changing to background state some features will continue to completion.
1. For example if the application moves to the background while a file is being transmitted, the transmission will still complete.
- The reconnect process is triggered automatically when the app comes into the foreground and the connection status is set to connected.
Disconnected
What happens to SDK method callbacks if the connection is lost just as they are being called?
-
SDK method callbacks return a failure warning if there is no SDK connection
-
SDK connection and internet connection are different things.
-
It is possible for there to be an internet connection without the SDK being connected.
-
If the SDK is not connected, the server side changes will not show to the user.
-
Need to use reconnect listeners.
-
The SDK has reconnect listeners to help indicate when the SDK is trying to reconnect.
-
After 45 seconds if there is no reconnection, the SDK will fire the re-connect failed listener.
What happens to messages sent to a channel where one member’s device is disconnected?
-
After a loss of internet the client will open a new WebSocket on reconnect.
-
If a user was in a channel and the internet was unstable and the internet comes back on:
-
There is a need to fetch new messages for the channel manually.
-
This should be followed by loading messages from the timestamp of the last read message.
What happens to messages sent out from the client during reconnect process?
- If there is no WebSocket connection the sendMessage callback will return a failed connection error.
What happens when sending messages while disconnected?
- The sendMessage callback will warn of a disconnect
- Is up to the implementation developers to handle this case.
Is there a way for the implementation to check if a message is successfully written to the SendBird server?
- Yes. The SDK holds a temporary message request id locally.
- The temporary message id remains available until a write success callback is received from SendBird.
- It is possible to implement a handler to resend failed messages.
- In the sync-manager SDK the failed messages are handled automatically (coming soon…).
When are SendBird push notifications sent in relation to app connection?
-
By default, for a user to receive push notifications they need to be disconnected from SendBird server.
-
For the JavaScript React Native SDK and web applications
-
setForegroundState() or setBackgroundState() should be called explicitly depending on the application’s foreground or background state.
-
Setting these methods helps by informing the SendBird servers whether or not to send push notifications.
-
For the iOS and Android native application
-
For users’ seamless chat experience, our Android SDK manages connections to SendBird server at the application level.
-
Therefore, in normal cases, you don’t need to call the disconnect() method explicitly.
-
The table below shows how connections between a client app’s SendBird instance and our server are managed. This is according to the states of Android/iOS devices where your native app is working on.
App state | Connection | SDK behavior when going to another state |
---|---|---|
Foreground | Keep connected | Disconnects the current user from SendBird server when going to the background. |
(Tries to restore the connection and keeps the current user connected to SendBird server when the connection is lost due to unexpected network issues in the foreground. In this case, the attempts of restoration process and the result can be checked in the connection event handler if registered.)|
|Background|Disconnected|Tries to reconnect and establishes the current user’s new connection with SendBird server when going to the foreground.|
Implementation
What happens when the client calls for the latest data multiple times rapidly, as in the user repeatedly refreshes the page or app?
- The same WebSocket connection is maintained.
- The implementation should handle this case and queue/throttle the requests.
- The SendBird servers will return a RATE_LIMIT_EXCEEDED error if the call rate limit is exceeded.
What happens if sb.connect() is called manually in the middle of reconnect cycle?
Manually calling connect() in the middle of the internal reconnection cycle causes the following:
- The automatic connection manager stops.
- Any previously applied reconnection event handlers will not get called.
Therefore, we recommend allowing SendBirds internal connection manager to handle the connection status automatically. However, there are two key points when you might need to call connect manually:
-
When the connection manager event listener fires the connection failed event.
-
ConnectionHandler.onReconnectFailed
-
If an SDK method call returns a connection failed callback.
If you need to check the state of current connection, you can check it using getConnectionState().
-
OPEN means the SDK is connected.
-
CLOSED means the SDK is not connected.
-
CONNECTING means the reconnect cycle is in progress.
-
Do not call sb.connect() in this state as it will stop the connection manager.
Once the SDK is connected is all data sent via the WebSocket protocol?
-
No. Some SDK methods use HTTP protocols not WebSocket protocols.
-
From a high level view it is real time actions that are sent via WebSocket.
1. Individual messages
2. Typing indicators
3. Other event listeners
- With SendBird’s core SDK, data is not synced from the database to the client automatically when the onReconnectSucceeded event listener is fired. This means that manual fetching of new messages and other data for the duration of the disconnect is required. For example, on iOS, the client should refresh messages when the reconnection is completed in didSucceedReconnection delegate by calling the getPreviousMessagesByTimestamp:inclusiveTimestamp:limit:reverse:messageType:customType:senderUserIds:includeMetaArray:includeReactions:completionHandler: method. This method is implemented in the iOS sample application available on GitHub.
- SendBird’s Sync Manager SDK provides a solution to address the current need for data to be manually fetched for the duration of each disconnect.
What are the best practices when implementing a browser based application?
Here we outline some key points for consideration when implementing the JavaScript SDK for browsers:
-
For each tab that is opened and sb.connect() is called.
-
Each tab counts as a connection.
-
Each tab holds a separate SendBird SDK instance.
-
Each tab will have its own WebSocket.
-
Though not officially supported, SendBird will send FCM push notification if a browser has registered an FCM token using either the SendBird SDK or SendBird platform API, and if setBackgroundState() has been called.
-
Browser based push notifications are a relatively new technology and as such are not 100% fully supported in all browsers (for example Safari), and require service workers.
Related JavaScript methods:
Browser visibility states to consider and their definition:
Best Practices:
-
Consider your implementation and how the user is going to be made aware of updated inform from SendBird.
-
How will they know, and is it important they know, when a new message arrived if the SendBird containing tab is not visible?
-
How will they know, and is it important they know, when a new message arrived if the SendBird containing tab window is closed?
-
Consider the impact of opening multiple tabs with your application as each tab will connect to SendBird as an additional connection.
-
Carefully consider the conditions under which you will disconnect the user from SendBird, or call setBackgroundState if you are using push notifications.
Here is cross browser snippet for detecting tab and browser conditions:
// check if current tab is focused or not var vis = (function(){ var stateKey, eventKey, keys = { hidden: "visibilitychange", webkitHidden: "webkitvisibilitychange", mozHidden: "mozvisibilitychange", msHidden: "msvisibilitychange" }; for (stateKey in keys) { if (stateKey in document) { eventKey = keys[stateKey]; break; } } return function(c) { if (c) document.addEventListener(eventKey, c); return !document[stateKey]; } })(); // check if current tab is focused or not vis(function(){ if(vis()){ console.log('tab focused') sb.connect(USER_ID, function(user, error){ // consider connecting to SendBird groupChannel.refresh() // consider updating channel(s) data }) } else { console.log('tab lost focus') sb.disconnect(function() { // consider disconnecting from SendBird // A current user is disconnected from SendBird server. }) } }); // check if the browser is focused or not window.addEventListener("focus", function (event) { console.log('browser window focused') sb.connect() // consider connecting to SendBird }, false); window.addEventListener("blur", function (event) { console.log('browser window lost focus') sb.disconnect(function() { // consider disconnecting from SendBird // A current user is disconnected from SendBird server. }) }, false);