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 许可。请在该仓库提交问题。