Skip to content

SDKs

Android SDK reference: methods, events, options and errors

Every StreamClient method, property and event in the VoltKit RTC Android SDK, its options, RemoteTrack, and each error code with what to do about it.

The complete surface of in.voltkit:voltkit-rtc 0.9.4. For how to use it, start with the Android SDK page and the voice call and audio room guides.

Errors

Every call fails with RpcError (code, message, data). Decide on code, log message. The codes are the same in every VoltKit SDK; info (from the shared registry) says whether a code is terminal (retrying cannot help) or retryable.

try {
    client.publish(PublishOptions(video = false))
} catch (e: RpcError) {
    when (e.code) {
        "media-unavailable" -> askForPermission(e.data?.get("permission"))
        "forbidden" -> showListenerOnly()
        "media-disabled" -> showNotAllowed()
        "closed" -> startNewCall()
        else -> if (e.info?.retryable == true) retryLater() else showError(e.message)
    }
}
scope.launch { client.onError.collect { e -> log("voltkit ${e.code}: ${e.message}") } }

onError carries every problem that is not the answer to a call you made: quality warnings, a subscription or republish that failed, a microphone or camera failure, and the endings replaced and reconnect-gave-up. onPublishWarning repeats the quality warnings as text; onSubscribeError the failed subscriptions with their producer.

Codes this SDK raises itself:

CodeWhen
closedthe client was closed (or the session ended); create a new one
disconnectedthe connection dropped while the call waited; the SDK reconnects. A publish() cut off this way is kept and done again after the rejoin
timeoutthe server did not answer in 15 s
connect-failedthe WebSocket could not be opened (no network, wrong URL, a proxy); data["status"] for an HTTP answer
media-unavailableno permission (data["permission"]), a media call before connect(), a microphone that failed, no video codec on this room's media server
media-disabledthe project switched that kind of media off
forbiddenyour role cannot do that (a listener publishing)
force-muteda moderator holds that device off
unpublishedunpublish(), stopMusic(), unpublishScreen() or stop() ran while that start was under way
produce-failedthe media library did not deliver a producer (see logcat)
consume-faileda remote track could not be subscribed to (onSubscribeError); the rest of the room works
no-camerathe device reports no camera
camera-failedthe camera could not start, or could not switch
music-unavailablein-app music is not possible on this WebRTC build
audio-quality-not-allowedHD audio in a project limited to standard audio
unknown-producersetReceiveQuality named a video you do not receive
quality-unavailablethat publisher describes no video layers; use automatic
screen-share-activea screen share is already running
screen-share-failedscreen capture could not start
screen-share-service-requiredstart a foreground service of type mediaProjection first
bad-paramsan argument is not valid (an unknown device id, a frame rate other than 30 or 60)
internalthe server answered with something malformed
replaced(on onError) this identity connected elsewhere; the session is closed
reconnect-gave-up(on onError) every reconnect attempt failed; the session is closed

Warnings on onError (publishing goes on): codec-fallback, degradation-preference-failed, frame-rate-fallback, frame-rate-not-allowed, video-quality-not-allowed, audio-quality-not-allowed, video-subscription-limit.

Codes from the server you may meet: bad-token (expired or wrong token: mint a new one), no-room and room-ended, kicked, quota-exhausted, daily-limit-reached, monthly-limit-reached and tenant-suspended (the account), participant-quota / viewer-quota, slot-taken, slot-blocked, slot-occupied, chat-muted, rate-limited, source-already-published, token-mismatch (updateToken with a token for another room or identity). Every code: Errors.

API reference

StreamClient

StreamClient(context, wsUrl, token, options = StreamOptions()); also StreamClient(context, wsUrl, token, connection: ConnectionOptions).

Lifecycle
connect(metadata)join; returns JoinResult. Collect flows first
close()leave and release everything; idempotent
updateToken(token)a newer token from your backend; returns its expiry (ms)
preflight(context, wsUrl, token, audio, video, durationMillis)(companion) a pre-call check
Publishing
publish(options)microphone and/or camera (PublishOptions(audio, video, camera, encoding, audioQuality))
unpublish()stop and release microphone, camera, music and screen
setMicEnabled(on) / setCamEnabled(on)mute / camera off without releasing
switchCamera()front and back, same track
setAudioQuality(q) / setVideoQuality(q) / setVideoFrameRate(fps)change while live
prioritizePerformance(on) / setPublishFallback(on)lighten an overloaded or starved publisher
publishMusic(source, volume) / setMusicEnabled(on) / setMusicVolume(v) / stopMusic()in-app music
publishScreen(consent, options) / unpublishScreen()screen sharing
Receiving
attachVideo(track, renderer, cover)draw a remote video with adaptive stream; returns a VideoAttachment
setVideoView(producerId, VideoView) / clearVideoView(producerId)report a view yourself
setReceiveQuality(producerId, quality)a quality for one remote video; null is automatic
setPreferredLayers(consumerId, spatial, temporal)cap one subscription's layer
setAudioOnlyFallback(on)pause remote cameras when the audio breaks up (on by default)
Devices and audio
listDevices(kind)cameras, microphones, audio outputs
switchDevice(kind, deviceId)use one
setSpeakerphoneOn(on)loudspeaker or earpiece when no headset is connected
Statistics and support
getVideoStats() / getReceiveStats(producerId)numbers for the camera / one received video
getDiagnostics()a support snapshot (toJson())

Room and chat calls: raiseHand, lowerHand, claim, release, blockSlot, unblockSlot, setMetadata, setRoomMetadata, muteParticipant, requestMute, forceMute, promote, kick, endRoom, getRoomState, sendMessage, getMessages, deleteMessage, muteChat, setTyping, getChatState (see above).

Properties
connectionStateStateFlow<ConnectionState>
joinResult, role, identity, roomIdthe room as this client knows it, kept current
participantsStateFlow<List<ParticipantInfo>>, kept current
remoteTrackswhat is received now
localVideoTrack, localMediayour preview; what you send (LocalMediaState)
publishing, micEnabled, camEnabled, musicPublishing, musicEnabled, screenSharingthe same, as values
audioQuality, videoQuality, videoFrameRate, performancePrioritizedwhat is sent
mediaPermissions, billingModewhat the project allows; how it bills
audioOutputStateFlow<MediaDevice?>: where call audio plays
closedReason, tokenExpiresAtwhy it ended; when the token expires
Events (SharedFlow)
onTrack / onTrackEndeda remote track arrived or went
onTrackMuteda track was paused or resumed, your own included (identity)
onSubscribeErrorone remote track could not be received
onParticipantJoined / onParticipantLeft / onParticipantUpdatedthe roster; ParticipantLeft.reason is left, disconnected, kicked, room-ended or presence-lost
onParticipantMuteda moderator switched someone's device off or back on
onRoleChanged / onHandRaised / onForceMutedroles, hands, your own moderation
onClaimChanged / onRoomMetadataChangedseats and room metadata
onStreamInterrupteda publisher's media stopped while it reconnects
onConnectionStateChanged / onReconnected / onMediaReconnecting / onMustReconnectthe connection
onUsageLimit / onWalletLowthe account behind the room is running out (the session ends at endsAt unless topped up)
onTokenExpiringthe token lapses in a minute and was not refreshed
onKicked / onRoomClosed / onClosedthe endings
onError / onPublishWarningproblems and warnings
onNetworkQuality / onAudioLevels / onActiveSpeakers / onMediaWarning / onCpuConstrainedobservability (sampled while collected)
onStreamFallback / onPublishFallbackvideos held back for bandwidth
onDevicesChangedheadsets and devices came or went
onScreenShareStarted / onScreenShareEndedscreen sharing
onMessage / onMessageDeleted / onChatMuted / onTypingchat

RemoteTrack

identity, producerId, consumerId, kind (audio / video), source (mic, music, camera, screen), isAudio, isVideo, isMusic, isEnded, track; addSink(sink), removeSink(sink), setVolume(0.0..10.0) (this device only; 0 on a music track mutes the music and keeps the voice), setEnabled(on).

StreamOptions

OptionDefault
connectionConnectionOptions()timeouts, reconnect attempts and backoff, onWire (a token-free wire log for debugging)
manageAudiotruethe SDK runs call audio (mode, focus, routing)
speakerphonetrueloudspeaker (true) or earpiece when no headset
audioOnlyFallbacktruepause remote cameras when the audio breaks up
pauseCameraInBackgroundfalsecamera off while the app is in the background
pauseMicInBackgroundfalsemicrophone off while the app is in the background

Threads

Every suspend function is main-safe; media work runs on the client's own thread. Flows are hot SharedFlows: collect before connect() so nothing is missed (onClosed replays to a late collector). The same client may be used from any thread.

Last updated . Something unclear or wrong? Tell us.