Kotlin SDK
com.messagebird:bird-realtime é o cliente Kotlin oficial para o Bird Realtime: ele mantém um WebSocket com o edge Bird, inscreve-se em canais e entrega eventos conforme são publicados. Ele é escrito manualmente, não gerado, porque o Realtime é um data plane WebSocket em vez de uma superfície REST, e fala o mesmo dialeto de protocolo que os clientes de navegador e Swift.
É uma biblioteca JVM pura, então o mesmo artefato serve tanto para um app Android quanto para um servidor. Callbacks são despachados no main looper do Android quando ele existe e executados inline caso contrário, então você não precisa de um build separado para cada um.
Este cliente é o lado de recebimento. Publicar eventos, autorizar canais e encerrar conexões são operações do lado do servidor na Bird API; veja publicação de eventos.
Instalação
dependencies {
implementation("com.messagebird:bird-realtime:0.1.0")
}No Android, adicione a permissão de internet ao seu manifesto. Uma biblioteca não contribui mais uma:
<uses-permission android:name="android.permission.INTERNET" />Construir um cliente
import com.messagebird.realtime.BirdRealtime
import com.messagebird.realtime.BirdRealtimeOptions
val bird = BirdRealtime(
BirdRealtimeOptions(
appKey = "your-app-key",
region = "us1",
)
)Apenas appKey é obrigatório, mais region (us1 ou eu1, que resolve o host do edge) ou um wsHost explícito. A app key é pública e é enviada no código do cliente: ela identifica o app, não autoriza nada.
O socket abre quando o cliente é construído, então você não precisa chamar connect() primeiro. connect() e disconnect() são para o ciclo de vida do app: feche o socket quando sua activity sai e reabra quando ela volta, e os canais nos quais você se inscreveu são reinscritos automaticamente.
disconnect() deixa o cliente reutilizável, então mantém deliberadamente a thread de trabalho à qual o cliente confina seu estado. Quando você terminar definitivamente com um cliente, faça close() nele, ou essa thread e o socket vivem enquanto o processo existir. A classe é AutoCloseable, então um bloco use { } faz isso por você. O cliente Swift não precisa de equivalente: ele libera ambos quando a última referência desaparece.
Inscrever-se em um canal
val orders = bird.subscribe("orders")
orders.bind("order-updated") { data ->
println("order changed: $data")
}Payloads chegam como kotlinx.serialization.json.JsonElement, então leia-os com a API de serialização em vez de fazer casting.
Um canal cujo nome não tem o prefixo private- ou presence- é público: qualquer cliente com a app key pode se inscrever, então trate seu conteúdo como legível por qualquer pessoa que consiga abrir seu app.
Canais privados e de presença
Canais privados e de presença são autorizados pelo seu backend, que possui o app secret. Aponte o cliente para o seu endpoint: ele faz POST de {"connection_id", "channel_name"} e espera {"auth", "member_data"?} de volta.
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") }
}Passe um authorizer em vez disso para autenticar pela sua própria stack de rede.
Uma rejeição do servidor (assinatura inválida, app acima da capacidade) chega na conexão e não no canal, porque o protocolo não inclui atribuição de canal. Observe essas rejeições com onError. Uma falha dentro do seu autorizador emite bird:subscription_error no canal.
Autenticar um membro
signin() informa ao edge a qual membro esta conexão pertence. Essa identidade é o que permite ao API endereçar um membro ou encerrar suas conexões, e é o que satisfaz um app configurado para exigir conexões autorizadas.
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")
}Chame signin() uma vez. A identidade permanece na conexão, então o cliente se autentica novamente de forma automática após uma reconexão. Uma autenticação automática que falha não tem uma chamada ativa de onde lançar exceção, então aparece em onSigninError. Isso impede que um endpoint de membro com falha interfira nas inscrições de canal.
Ciclo de vida da conexão
bird.onConnectionStateChange { previous, current ->
println("connection: $previous -> $current")
}
bird.onError { error ->
if (error.code == 4009) println("session ended elsewhere")
}A reconexão é automática, com backoff exponencial com full-jitter de 1 s até um limite de 30 s. Códigos de fechamento entre 4000 e 4099 são recusas e terminais: o cliente para e reporta o código, porque uma recusa é uma decisão, não uma falha transitória. Códigos entre 4200 e 4299 reconectam imediatamente; qualquer outro aplica backoff. Os canais são reinscritos com autorização nova a cada reconexão. Veja ciclo de vida da conexão.
O transporte é TLS para todo host que não seja loopback. allowInsecure permite ws:// apenas para localhost, 127.0.0.1 e [::1], então uma configuração copiada de um alvo de desenvolvimento não pode rebaixar silenciosamente o tráfego de produção.
Eventos de cliente
Com a configuração de eventos de cliente do app habilitada, um cliente inscrito em um canal privado ou de presença pode publicar diretamente para seus pares:
room.trigger("client-typing", buildJsonObject { put("on", true) })Veja eventos de cliente.
Código-fonte
github.com/messagebird/bird-sdk-kotlin, licença MIT. Reporte problemas lá.
Recursos relacionados
Continue com a documentação, guias e exemplos sobre este tópico.