The code below creates a chat client instance for interacting with Stream APIs. A singleton client instance means the Chat client is created once and reused throughout your app, ensuring consistent state, avoiding duplicate connections, and simplifying resource management.
// Typically done in your Application class using your API Key on startupval client = ChatClient.Builder("{{ api_key }}", context).build()// Static reference to initialised clientval staticClientRef = ChatClient.instance()
import { StreamChat } from "stream-chat";// client-side you initialize the Chat client with your API keyconst chatClient = StreamChat.getInstance("{{ api_key }}", { timeout: 6000,});
// API key can be found on the dashboard: https://getstream.io/dashboard/let config = ChatClientConfig(apiKey: .init("<# Your API Key Here #>"))// Create an instance of ChatClientlet chatClient = ChatClient(config: config)// Recommendation is to store it as a shared instanceextension ChatClient { static var shared: ChatClient!}ChatClient.shared = chatClient
// client-side you initialize the Chat client with your API keyfinal client = StreamChatClient( "{{ api_key }}", logLevel: Level.INFO, connectTimeout: Duration(milliseconds: 6000), receiveTimeout: Duration(milliseconds: 6000),);
// Typically done in your Application class on startupChatClient client = new ChatClient.Builder("{{ api_key }}", context).build();// Client singleton is also available via static referenceChatClient staticClientRef = ChatClient.instance();
var client = StreamChatClient.CreateDefaultClient();
Once the client is initialized, your app authenticates the user and establishes a Websocket connection by calling connectUser. This function uses your token provider function to request a token from your server.
The connectUser function acts as an upsert for the user object and is a primary method for creating users client-side.
Before attempting subsequent API requests to Stream, it is important that the connectUser function fully resolves.
val user = User( id = "bender", extraData = mutableMapOf( "name" to "Bender", "image" to "https://bit.ly/321RmWb", ),)// You can setup a user token in two ways:// 1. Setup the current user with a JWT tokenval token = "{{ chat_user_token }}"client.connectUser(user, token).enqueue { result -> if (result is Result.Success) { // Logged in val user: User = result.value.user val connectionId: String = result.value.connectionId } else { // Handle Result.Failure }}// 2. Setup the current user with a TokenProviderval tokenProvider = object : TokenProvider { // Make a request to your backend to generate a valid token for the user override fun loadToken(): String = yourTokenService.getToken(user)}client.connectUser(user, tokenProvider).enqueue { /* ... */ }
// Option A: with expiring token// The `tokenProvider` closure will be called again when the token is expiredChatClient.shared.connectUser( userInfo: .init(id: userID), tokenProvider: { providerResult in loadChatToken(completion: providerResult) }, completion: { error in if let error = error { print("Connection failed with: \(error)") } else { // User successfully connected } })// or alternatively, using the async-await methodlet connectedUser = try await ChatClient.shared.connectUser( userInfo: .init(id: userID), tokenProvider: { providerResult in loadChatToken(completion: providerResult) })// An example of a token providerfunc loadChatToken(completion: @escaping (Result<Token, Error>) -> Void) { NetworkingLayer.getChatToken() { token in do { let token = try Token(rawValue: token) completion(.success(token)) } catch { completion(.failure(error)) } }}// Option B: with a non-expiring token// You can generate the token for this user from https://getstream.io/chat/docs/ios-swift/tokens_and_authentication/?language=swiftlet token: Token = "{{ chat_user_token }}"/// Connect the user using a closure based methodChatClient.shared.connectUser( userInfo: .init(id: userID), token: token) { error in if let error = error { print("Connection failed with: \(error)") } else { // User successfully connected }}// or alternatively, using the async-await methodlet connectedUser = try await ChatClient.shared.connectUser( userInfo: .init(id: userID), token: token)
final user = User(id: "john", extraData: { "name": "John Doe", "image": "https://i.imgur.com/fR9Jz14.png",});await client.connectUser(user, "{{ chat_user_token }}");
User user = new User();user.setId("bender");user.setName("Bender");user.setImage("https://bit.ly/321RmWb");// You can setup a user token in two ways:// 1. Setup the current user with a JWT tokenString token = "{{ chat_user_token }}"; client.connectUser(user, token).enqueue(result -> { if (result.isSuccess()) { // Logged in User userRes = result.data().getUser(); String connectionId = result.data().getConnectionId(); } else { // Handle result.error()}});// 2. Setup the current user with a TokenProviderTokenProvider tokenProvider = new TokenProvider() { @NotNull @Override public String loadToken() { return yourTokenService.getToken(user); }};client.connectUser(user, tokenProvider).enqueue(result -> {/* ... */});
var localUserData = await client.ConnectUserAsync("api_key", "chat_user", "chat_user_token");// After await is complete the user is connected// Alternatively, you subscribe to the IStreamChatClient.Connected eventclient.Connected += localUserData =>{ // User is connected};
The user object. Must have an id field. User Ids can only contain characters a-z, 0-9, and special characters @ _ and - It can have as many custom fields as you want, as long as the total size of the object is less than 5KB
userToken
string/function
The Token Provider function or authentication token. See Tokens & Authentication for details
The client-side SDKs handle WebSocket disconnection logic, but if a manual disconnect is required in your application, there are the following options:
Most browsers support WebSocket connections as an efficient mode of real-time data transfer. However, sometimes the connection cannot be established due to network or a corporate firewall. In such cases, the client will establish or switch to XHR fallback mechanisms and gently poll our service to keep the client up-to-date.
The fallback mechanism can be enabled with the flag enableWSFallback
if enabled is set to false , then typing.start and typing.stop events will be ignored for this user and these events will not be sent to others
enabled: true
✓
read_receipts
object
If enabled is set to false , then the read_state of this user will not be exposed to others. Additionally, read_state related events will not be delivered to others when this user reads messages.