# Handling User Connection

This guide explains how to connect, disconnect, and switch the user, when the SDK calls your `TokenProvider`, and how the SDK manages the WebSocket connection across the app lifecycle.

## Connecting a User

You need to connect a user before using the SDK. This requires a valid Stream Chat token. The token must be generated on your server, because it requires your `API_SECRET`.

<admonition type="note">

To learn about tokens and user types, see [Tokens & Authentication](/chat/docs/android/tokens-and-authentication/).

</admonition>

You can connect with a static token or with a `TokenProvider`. Use a `TokenProvider` in production so the SDK can fetch a fresh token when the current one expires.

```kotlin
val user = User(
    id = "bender",
    name = "Bender",
    image = "https://bit.ly/321RmWb",
)

// Option A: a static token
ChatClient.instance().connectUser(user = user, token = "userToken")
    .enqueue { result ->
        when (result) {
            is Result.Success -> { /* Handle success */ }
            is Result.Failure -> { /* Handle error */ }
        }
    }

// Option B: a TokenProvider
val tokenProvider = object : TokenProvider {
    // Called on the initial connection, and again when a fresh token is
    // needed. Keep it resilient to a missing or slow network.
    override fun loadToken(): String = yourTokenService.getToken(user)
}
ChatClient.instance().connectUser(user = user, tokenProvider = tokenProvider)
    .enqueue { result ->
        when (result) {
            is Result.Success -> { /* Handle success */ }
            is Result.Failure -> { /* Handle error */ }
        }
    }
```

Connect the user only once. Before connecting, you can check whether a user is already set:

```kotlin
if (ChatClient.instance().getCurrentUser() == null) {
    ChatClient.instance().connectUser(user = user, tokenProvider = tokenProvider).enqueue { /* ... */ }
}
```

## When the SDK Calls Your TokenProvider

`TokenProvider.loadToken()` is a blocking call. The SDK calls it on the initial connection, and after that only when the cached token can no longer be used:

- The server rejects the token (authentication error or token expiry).
- The connection is found to be unhealthy and is re-established (a missed WebSocket health check).
- An unrecoverable socket error occurs.
- You call `disconnect()` or `disconnectSocket()`.

Routine reconnects (returning to the foreground, network recovery, transient errors) reuse the cached token and do not call `loadToken()`.

When a fresh token is needed, `loadToken()` runs a network request, so it can throw `UnknownHostException` or similar when there is no usable network. The SDK treats this as a failed connection attempt and retries, so it is not a crash. Make sure your implementation handles a missing network without recording it as a fatal error in your crash reporter.

## Connection and the App Lifecycle

The SDK manages the WebSocket connection for you based on the application lifecycle and network state. You do not need to connect and disconnect on every screen.

- The SDK observes `ProcessLifecycleOwner`. When the app goes to the background it stops the socket, stops the health monitor, and stops listening for network changes.
- When the app returns to the foreground, the SDK reconnects automatically.
- While connected, the SDK monitors network availability and reconnects after a connection is lost.

Because the connection is paused in the background and resumed in the foreground, you usually do not need to add your own lifecycle handling.

## Manual Disconnect and Reconnect

If you need direct control over the socket, you can use the following methods.

```kotlin
// Closes the socket. Use this for a logout flow or to stop the connection.
ChatClient.instance().disconnectSocket().enqueue { /* ... */ }

// Reopens the socket for the already connected user.
ChatClient.instance().reconnectSocket().enqueue { /* ... */ }
```

<admonition type="warning">

Calling `disconnectSocket()` also removes the lifecycle observer, so the SDK will no longer reconnect automatically when the app returns to the foreground. If you call `disconnectSocket()` yourself, you are responsible for calling `reconnectSocket()` (or `connectUser()`) again when you want the connection back. For background and foreground handling, prefer the SDK's built-in behavior over calling `disconnectSocket()` on every background.

</admonition>

## Disconnecting the User

The user connection is kept as long as the application process is alive. You might still want to disconnect the user explicitly, for example as part of a logout flow.

```kotlin
ChatClient.instance().disconnect(flushPersistence = false).enqueue { result ->
    when (result) {
        is Result.Success -> { /* Handle success */ }
        is Result.Failure -> { /* Handle error */ }
    }
}
```

The `flushPersistence` parameter controls whether the local database is cleared. Set it to `true` to remove cached data on logout. For more about offline storage, see [Offline Support](/chat/docs/sdk/android/client/guides/offline-support/).

## Switching the User

To switch users, disconnect the current user and connect the new one. `switchUser` does both for you.

```kotlin
val user2 = User(
    id = "bender2",
    name = "Bender2",
    image = "https://bit.ly/321RmWb",
)

ChatClient.instance().switchUser(user = user2, token = "userToken").enqueue { result ->
    when (result) {
        is Result.Success -> { /* Handle success */ }
        is Result.Failure -> { /* Handle error */ }
    }
}
```

## Observing the Connection State

You can observe the current connection state to update your UI:

```kotlin
ChatClient.instance().clientState.connectionState
    .onEach { state ->
        when (state) {
            is ConnectionState.Connected -> { /* Online */ }
            is ConnectionState.Connecting -> { /* Connecting or reconnecting */ }
            is ConnectionState.Offline -> { /* Offline */ }
        }
    }
    .launchIn(scope)
```


---

This page was last updated at 2026-06-15T15:48:50.719Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/android/client/guides/handling-user-connection/](https://getstream.io/chat/docs/sdk/android/client/guides/handling-user-connection/).