Documentation
Sign inGet started

Kotlin SDK

com.messagebird:bird-realtime is the official Kotlin client for Bird Realtime: it holds a WebSocket to the Bird edge, subscribes to channels, and delivers events as they are published. It is hand-written rather than generated, because Realtime is a WebSocket data plane rather than a REST surface, and it speaks the same wire dialect as the browser and Swift clients.
It is a plain JVM library, so the same artifact serves an Android app and a server. Callbacks land on the Android main looper when one exists and run inline otherwise, so you do not need a separate build for each.
This client is the receiving side. Publishing events, authorizing channels, and terminating connections are server-side operations on the Bird API; see publishing events.

Install

代码示例
dependencies {
    implementation("com.messagebird:bird-realtime:0.1.0")
}
On Android, add the internet permission to your manifest. A library no longer contributes one:
代码示例
<uses-permission android:name="android.permission.INTERNET" />

Construct a client

代码示例
import com.messagebird.realtime.BirdRealtime
import com.messagebird.realtime.BirdRealtimeOptions

val bird = BirdRealtime(
    BirdRealtimeOptions(
        appKey = "your-app-key",
        region = "us1",
    )
)
bird.connect()
Only appKey is required, plus either region (us1 or eu1, which resolves the edge host) or an explicit wsHost. The app key is public and ships in client code: it identifies the app, it does not authorize anything.

Subscribe to a channel

代码示例
val orders = bird.subscribe("orders")
orders.bind("order-updated") { data ->
    println("order changed: $data")
}
Payloads arrive as kotlinx.serialization.json.JsonElement, so read them with the serialization API rather than casting.
A channel whose name has no private- or presence- prefix is public: any client with the app key can subscribe, so treat its contents as readable by anyone who can open your app.

Private and presence channels

Private and presence channels are authorized by your backend, which holds the app secret. Point the client at your endpoint: it POSTs {"connection_id", "channel_name"} and expects {"auth", "member_data"?} back.
代码示例
val bird = BirdRealtime(
    BirdRealtimeOptions(
        appKey = "your-app-key",
        region = "us1",
        authEndpoint = "https://your-backend.example.com/bird/auth",
        authHeaders = mapOf("authorization" to "Bearer <session token>"),
    )
)

val room = bird.subscribe("presence-room-42")
if (room is PresenceChannel) {
    room.bind(BirdProtocol.Event.SUBSCRIPTION_SUCCEEDED) {
        println("me: ${room.myId}, members: ${room.members.keys}")
    }
    room.bind(BirdProtocol.Event.MEMBER_ADDED) { member -> println("joined: $member") }
}
Pass an authorizer instead to sign through your own networking stack.
A rejection from the server (a bad signature, an app over capacity) arrives on the connection rather than the channel, because the wire carries no channel attribution. Observe those with onError. A failure inside your authorizer does emit bird:subscription_error on the channel.

Sign in a member

signin() tells the edge which member this connection belongs to. That identity is what lets the API address a member or terminate their connections, and it is what satisfies an app configured to require authorized connections.
代码示例
val bird = BirdRealtime(
    BirdRealtimeOptions(
        appKey = "your-app-key",
        region = "us1",
        memberAuthEndpoint = "https://your-backend.example.com/bird/auth/member",
    )
)

val me = bird.signin() // suspending
println("signed in as ${me.memberId}")

bird.member.bind("order.shipped") { data ->
    println("addressed to me: $data")
}
Call signin() once. The identity lives on the connection, so the client signs in again automatically after a reconnect; a failed re-signin has nothing to throw to and surfaces on onSigninError instead, which keeps a failing member endpoint from disturbing channel subscriptions.

Connection lifecycle

代码示例
bird.onConnectionStateChange { previous, current ->
    println("connection: $previous -> $current")
}
bird.onError { error ->
    if (error.code == 4009) println("session ended elsewhere")
}
Reconnection is automatic, with full-jitter exponential backoff from 1s to a 30s cap. Close codes in 4000-4099 are refusals and terminal: the client stops and reports the code, because a refusal is a decision rather than a transient failure. Codes in 4200-4299 reconnect immediately; anything else backs off. Channels re-subscribe with fresh authorization on every reconnect. See connection lifecycle.
Transport is TLS for every non-loopback host. allowInsecure permits ws:// only for localhost, 127.0.0.1 and [::1], so a config copied from a development target cannot silently downgrade production traffic.

Client events

With the app's client-events setting enabled, a client subscribed to a private or presence channel can publish to its peers directly:
代码示例
room.trigger("client-typing", buildJsonObject { put("on", true) })

Source

github.com/messagebird/bird-sdk-kotlin, MIT licensed. Report issues there.