> ## Documentation Index
> Fetch the complete documentation index at: https://learn.social.plus/llms.txt
> Use this file to discover all available pages before exploring further.

# Room Presence

> Track live room viewer heartbeat, viewer count, and online room users with room presence APIs.

Room presence tracks who is currently watching a live room. Use it for viewer counts, "who is watching" panels, and host tools that need to know which users are present in a room right now.

<Info>
  Room presence is available on iOS, Android, and TypeScript. It is not available in the current Flutter SDK checkout.
</Info>

## Platform Surface

| Platform   | Repository                                                   | Main APIs                                                                                                                        |
| ---------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| TypeScript | `RoomPresenceRepository`                                     | `startHeartbeat(roomId)`, `stopHeartbeat(roomId)`, `getRoomUserCount(roomId)`, `getRoomOnlineUsers(roomId)`                      |
| iOS        | `AmityRoomPresenceRepository(roomId:)`                       | `startHeartbeat()`, `stopHeartbeat()`, `getRoomUserCount()`, `getRoomOnlineUsers()`                                              |
| Android    | `AmityCoreClient.newRoomPresenceRepository().roomId(roomId)` | `startHeartbeat()`, `stopHeartbeat()`, `getOnlineUsersCount()`, `observeOnlineUsersCount(interval:)`, `getOnlineUsersSnapshot()` |
| Flutter    | Not available                                                | Not available                                                                                                                    |

## Parameters

| Operation                                       | Platform                | Parameter        | Required           | Description                                                                                                 |
| ----------------------------------------------- | ----------------------- | ---------------- | ------------------ | ----------------------------------------------------------------------------------------------------------- |
| Repository creation                             | iOS, Android            | `roomId`         | Yes                | Room ID whose presence should be tracked.                                                                   |
| `startHeartbeat`                                | TypeScript              | `roomId`         | Yes                | Room ID where the current user should be counted as present.                                                |
| `startHeartbeat`                                | iOS, Android            | None             | No                 | Uses the `roomId` already bound to the repository.                                                          |
| `stopHeartbeat`                                 | TypeScript              | `roomId`         | Yes                | Room ID whose heartbeat should stop.                                                                        |
| `stopHeartbeat`                                 | iOS, Android            | None             | No                 | Stops the active room heartbeat managed by the repository or presence service.                              |
| `getRoomUserCount` / `getOnlineUsersCount`      | All supported platforms | None or `roomId` | Platform-dependent | Reads the current online viewer count for the room.                                                         |
| `observeOnlineUsersCount`                       | Android                 | `interval`       | No                 | Poll interval in seconds. Defaults to 15 seconds.                                                           |
| `getRoomOnlineUsers` / `getOnlineUsersSnapshot` | All supported platforms | None or `roomId` | Platform-dependent | Reads a point-in-time list or snapshot of online room users. Android snapshots paginate 20 users at a time. |

## Start Room Heartbeat

Start the room heartbeat when the user enters the room, and stop it when they leave. The SDK sends the first heartbeat immediately and continues at the server-configured interval.

<CodeGroup>
  ```swift iOS theme={null}
  let roomPresence = AmityRoomPresenceRepository(roomId: roomId)

  try await roomPresence.startHeartbeat()

  // Call when the viewer leaves the room.
  roomPresence.stopHeartbeat()
  ```

  ```kotlin Android theme={null}
  val roomPresence = AmityCoreClient.newRoomPresenceRepository().roomId(roomId)

  roomPresence.startHeartbeat()
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe({
          showSuccessMessage("Room heartbeat started")
      }, { error ->
          showErrorMessage(error = error)
      })

  // Call when the viewer leaves the room.
  roomPresence.stopHeartbeat()
  ```

  ```typescript TypeScript theme={null}
  import { RoomPresenceRepository } from '@amityco/ts-sdk';

  RoomPresenceRepository.startHeartbeat(roomId);

  // Call when the viewer leaves the room.
  RoomPresenceRepository.stopHeartbeat(roomId);
  ```
</CodeGroup>

## Read Room User Count

Use the count as the source of truth for how many users are currently present in the room.

<CodeGroup>
  ```swift iOS theme={null}
  let roomPresence = AmityRoomPresenceRepository(roomId: roomId)

  let count = try await roomPresence.getRoomUserCount()
  showSuccessMessage(count)
  ```

  ```kotlin Android theme={null}
  val roomPresence = AmityCoreClient.newRoomPresenceRepository().roomId(roomId)

  roomPresence.getOnlineUsersCount()
      .subscribe({ count ->
          showSuccessMessage(count)
      }, { error ->
          showErrorMessage(error = error)
      })
  ```

  ```typescript TypeScript theme={null}
  import { RoomPresenceRepository } from '@amityco/ts-sdk';

  const { count } = await RoomPresenceRepository.getRoomUserCount(roomId);
  updateUI(count);
  ```
</CodeGroup>

## Keep the Count Live

The count is a point-in-time read. Android provides a built-in polling stream. On iOS and TypeScript, use your own timer and choose an interval that fits the UI.

<CodeGroup>
  ```swift iOS theme={null}
  let roomPresence = AmityRoomPresenceRepository(roomId: roomId)

  let timer = Timer.scheduledTimer(withTimeInterval: 30, repeats: true) { _ in
      Task { @MainActor in
          if let count = try? await roomPresence.getRoomUserCount() {
              showSuccessMessage(count)
          }
      }
  }

  timer.invalidate()
  ```

  ```kotlin Android theme={null}
  val roomPresence = AmityCoreClient.newRoomPresenceRepository().roomId(roomId)

  roomPresence.observeOnlineUsersCount(interval = 30)
      .subscribe({ count ->
          showSuccessMessage(count)
      }, { error ->
          showErrorMessage(error = error)
      })
  ```

  ```typescript TypeScript theme={null}
  import { RoomPresenceRepository } from '@amityco/ts-sdk';

  const timer = setInterval(async () => {
    const { count } = await RoomPresenceRepository.getRoomUserCount(roomId);
    updateUI(count);
  }, 30_000);

  clearInterval(timer);
  ```
</CodeGroup>

## Read Room Online Users

Use the online-user list when the app needs actual user objects, such as avatars in a "who is watching" panel. For large rooms, display the count as the total and treat the list as a snapshot.

<CodeGroup>
  ```swift iOS theme={null}
  let roomPresence = AmityRoomPresenceRepository(roomId: roomId)

  let users = try await roomPresence.getRoomOnlineUsers()
  displayUserList(users)
  ```

  ```kotlin Android theme={null}
  val roomPresence = AmityCoreClient.newRoomPresenceRepository().roomId(roomId)

  roomPresence.getOnlineUsersSnapshot()
      .subscribe({ snapshot ->
          val users = snapshot.getUsers()
          if (snapshot.canLoadMore()) {
              snapshot.loadMore().subscribe()
          }
      }, { error ->
          showErrorMessage(error = error)
      })
  ```

  ```typescript TypeScript theme={null}
  import { RoomPresenceRepository } from '@amityco/ts-sdk';

  const { data: users } = await RoomPresenceRepository.getRoomOnlineUsers(roomId);
  renderResults(users);
  ```
</CodeGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Heartbeat only for active viewing" icon="heart-pulse">
    Start room heartbeat when the viewer enters the live room screen. Stop it when the viewer leaves, switches rooms, backgrounds the screen, or the view model is torn down.
  </Accordion>

  <Accordion title="Count for totals, list for faces" icon="users">
    The count is the total active viewer number. The online-user list is best for UI that needs actual user objects, such as avatars or invite-to-cohost flows.
  </Accordion>

  <Accordion title="Poll count thoughtfully" icon="clock">
    Android defaults `observeOnlineUsersCount` to 15 seconds. On iOS and TypeScript, avoid very aggressive polling unless the count is central to the experience.
  </Accordion>
</AccordionGroup>

## Related Topics

<CardGroup cols={2}>
  <Card title="Heartbeat Sync" icon="heart-pulse" href="/social-plus-sdk/core-concepts/realtime-communication/presence-state/heartbeat-sync">
    Learn when to start and stop current user and room heartbeats.
  </Card>

  <Card title="Room Posts" icon="radio" href="/social-plus-sdk/social/content-management/posts/creation/room-post">
    Create social posts that reference live rooms.
  </Card>
</CardGroup>
