Sign inGet Started

Kotlin SDK

com.messagebird:bird-realtime 是 Bird Realtime 的官方 Kotlin 客户端:它与 Bird 边缘节点保持一条 WebSocket 连接,订阅频道,并在事件发布时将其送达。该客户端是手写的而非自动生成,因为 Realtime 是 WebSocket 数据面而非 REST 接口,它使用的线路协议与浏览器和 Swift 客户端相同。

它是一个纯 JVM 库,同一产物既可用于 Android 应用也可用于服务端。当 Android 主 looper 存在时回调在其上执行,否则内联运行,因此无需为两端分别构建。

此客户端是接收端。发布事件、授权频道和终止连接是 Bird API 上的服务端操作;参见发布事件。

安装

代码示例
dependencies {
    implementation("com.messagebird:bird-realtime:0.1.0")
}

在 Android 上,需要在清单中添加网络权限。库本身不再自动贡献该权限:

代码示例
<uses-permission android:name="android.permission.INTERNET" />

构造客户端

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

val bird = BirdRealtime(
    BirdRealtimeOptions(
        appKey = "your-app-key",
        region = "us1",
    )
)

只有 appKey 是必需的,另外需要 region(us1 或 eu1,用于解析边缘主机)或显式的 wsHost。应用密钥是公开的,随客户端代码一起分发:它用于标识应用,不承担任何授权功能。

套接字在客户端构造时即打开,因此无需先调用 connect()。connect() 和 disconnect() 用于应用生命周期管理:当 activity 销毁时关闭套接字,返回时重新打开,已订阅的频道会自动重新订阅。

disconnect() 会保留客户端的可复用状态,因此会刻意保留客户端用于限制状态访问的工作线程。当你确定不再需要某个客户端时,请 close() 它,否则该线程和套接字将存活到进程结束。该类实现了 AutoCloseable,因此可以用 use { } 块自动完成。Swift 客户端不需要等价操作:当最后一个引用消失时,两者都会被释放。

订阅频道

代码示例
val orders = bird.subscribe("orders")
orders.bind("order-updated") { data ->
    println("order changed: $data")
}

载荷以 kotlinx.serialization.json.JsonElement 形式到达,请使用序列化 API 读取,而非直接类型转换。

名称中没有 private- 或 presence- 前缀的频道是公开频道:任何持有应用密钥的客户端都可以订阅,因此应将其内容视为对所有能打开你应用的人可读。

私有频道和 presence 频道

私有频道和 presence 频道由你的后端授权,后端持有应用密钥。将客户端指向你的端点:它会 POST {"connection_id", "channel_name"},并期望返回 {"auth", "member_data"?}。

代码示例
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") }
}

传入 authorizer 可通过你自己的网络栈完成签名。

服务端的拒绝(签名错误、应用超容量)到达的是连接而非频道,因为线路上不携带频道归属信息。使用 onError 来观察这些事件。身份验证器内部的失败则会在频道上触发 bird:subscription_error。

登录成员

signin() 告知边缘节点此连接属于哪个成员。该身份使 API 能够向成员发送消息或终止其连接,也是满足配置为要求已授权连接的应用的前提。

代码示例
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")
}

只需调用一次 signin()。身份会保留在连接上,因此客户端在重连后会自动重新登录。自动登录失败时没有活跃的调用可抛出异常,因此它会出现在 onSigninError 上。这样可以防止成员端点故障干扰频道订阅。

连接生命周期

代码示例
bird.onConnectionStateChange { previous, current ->
    println("connection: $previous -> $current")
}
bird.onError { error ->
    if (error.code == 4009) println("session ended elsewhere")
}

重连是自动的,采用全抖动指数退避策略,从 1 秒起步,上限 30 秒。4000–4099 范围的关闭码表示拒绝且不可恢复:客户端停止并报告该码,因为拒绝是一个决策而非瞬时故障。4200–4299 范围的码立即重连;其他码则执行退避。每次重连时频道都会使用新的授权重新订阅。参见连接生命周期。

对所有非回环主机,传输层使用 TLS。allowInsecure 仅允许 localhost、127.0.0.1 和 [::1] 使用 ws://,因此从开发环境复制的配置不会在生产环境中静默降级流量。

客户端事件

启用应用的客户端事件设置后,已订阅私有频道或 presence 频道的客户端可以直接向其对等端发布消息:

代码示例
room.trigger("client-typing", buildJsonObject { put("on", true) })

参见客户端事件。

源码

github.com/messagebird/bird-sdk-kotlin,MIT 许可。请在该仓库提交问题。