Native Mobile SDKs
RTCstack ships native iOS (Swift) and Android (Kotlin) SDKs that mirror the @rtcstack/sdk contract — the same createCall → connect → events model as the web SDK, wrapping LiveKit's native clients the same way the web SDK wraps livekit-client. Native and web clients interoperate in the same room.
Each platform also ships a UI kit (SwiftUI / Jetpack Compose) built on LiveKit's official Components libraries, with a drop-in VideoConference view and the same design tokens as the web kits.
Status — preview, not yet published
Both SDKs compile against their pinned LiveKit dependencies and the cross-platform wire-format conformance tests pass (Android 7/7, iOS 6/6). The device-level features (CallKit/VoIP, screen share, audio routing, incoming-call push) are implemented but require a real-device pass with your own app/push credentials, and the packages are not yet published to CocoaPods trunk / Maven Central / a tagged release. Install today from source (SPM-from-git on iOS); registry coordinates land on first publish. Track Phase 6 for the release.
What you get
| iOS | Android | |
|---|---|---|
| Client SDK | RTCstackKit (Swift Package / CocoaPods) | com.rtcstack:sdk (AAR) |
| UI kit | RTCstackUI (SwiftUI) | com.rtcstack:ui-compose (Compose) |
| Built on | client-sdk-swift + components-swift | livekit-android + livekit-android-compose-components |
| Min target | iOS 15.0+ | Android API 24 (7.0)+ |
Pinned dependencies: iOS client-sdk-swift 2.14.1 + components-swift 0.1.7; Android livekit-android 2.24.1 + livekit-android-compose-components 2.3.0.
The same two-channel architecture as web
The connection model is identical to the web architecture:
- Signaling — WSS to your LiveKit endpoint (Caddy-proxied). Native SDK ↔ LiveKit server.
- Media — WebRTC/SRTP over UDP, direct to the LiveKit SFU (or a TURN relay on TLS:443).
- The RTCstack REST API is not involved during a call. It is called once, before the call, to mint a token.
1. Your app authenticates the user (your responsibility)
2. Your backend mints a token:
POST /v1/token { roomId, userId, name, role }
→ { token: "<JWT>", url: "wss://…/livekit", expiresAt }
3. Native client connects:
let call = RTCstack.createCall(.init(token: token, url: url)) // Swift
val call = RTCstack.createCall(context, CallOptions(token, url)) // Kotlin
try await call.connect()
4. Room state + media negotiated over WSS; media flows over UDPSecrets never ship in a mobile binary
Token issuance requires your API_KEY / API_SECRET for HMAC signing — these are trivially extractable from a mobile binary and must never be embedded. The native SDKs therefore:
- Take
{ token, url }exactly like the web SDK — your backend mints the token. - Accept a
tokenRefresherclosure / suspend function that calls your backend, never the RTCstack API directly. - Do not bundle the HMAC-signing REST client.
See Token Flow for the backend side.
Cross-platform wire-format interop
Native clients exchange chat, reactions, speaking indicators, and transcript segments with web clients in the same room over the LiveKit data channel. The payload format is a frozen cross-platform contract — UTF-8 JSON keyed on a type discriminator — enforced by conformance tests on all three platforms.
| Type | JSON |
|---|---|
| chat | {"type":"chat","text":"…","id":"…"} |
| reaction | {"type":"reaction","emoji":"…"} |
| speaking | {"type":"speaking","speakerId":"…","speaker":"…"} |
| transcript | {"type":"transcript","text":"…","speakerId":"…","speaker":"…","startMs":1234} |
Unknown type values are ignored for forward compatibility. LiveKit does not loop data back to the sender, so sending a message does not fire a local messageReceived — the UI kits echo the user's own outgoing messages. Any change to this format is a major version bump across all SDKs together.
API parity at a glance
The conceptual core (~80%) ports verbatim from the web SDK; the reactive primitive is the only thing that changes — Combine @Published / PassthroughSubject on iOS, Kotlin StateFlow / SharedFlow on Android.
Web (@rtcstack/sdk) | iOS (RTCstackKit) | Android (com.rtcstack:sdk) |
|---|---|---|
createCall({ token, url }) | RTCstack.createCall(_:) | RTCstack.createCall(context, …) |
call.connect() / disconnect() | connect() / disconnect() | connect() / disconnect() |
toggleMic / toggleCamera | same | same |
startScreenShare | ReplayKit broadcast | MediaProjection consent |
sendMessage / sendReaction | same | same |
call.on('event', …) | events (Combine) | events (SharedFlow) |
| reactive state | @Published props | StateFlow props |
The remaining ~20% is native-only platform integration — CallKit/VoIP and ConnectionService/FCM incoming calls, ReplayKit/MediaProjection screen share, audio session/focus management, and foreground-service lifecycle. These are first-class, opt-in modules documented per platform.
Next steps
- iOS (Swift) → — SPM install, the
CallAPI, CallKit/VoIP/ReplayKit, the SwiftUI kit - Android (Kotlin) → — Gradle install, the
CallAPI, foreground service / FCM / MediaProjection, the Compose kit

