Kotlin SDK
com.messagebird:bird-realtime to oficjalny klient Kotlin dla Bird Realtime: utrzymuje WebSocket do krawędzi Bird, subskrybuje kanały i dostarcza zdarzenia w momencie ich publikacji. Jest napisany ręcznie, a nie generowany, ponieważ Realtime to warstwa danych WebSocket, a nie powierzchnia REST, i posługuje się tym samym protokołem co klienty przeglądarkowy i Swift.
To zwykła biblioteka JVM, więc ten sam artefakt obsługuje aplikację Android i serwer. Callbacki trafiają na główny looper Androida, gdy jest dostępny, a w przeciwnym razie wykonują się inline, więc nie potrzebujesz osobnego buildu dla każdego środowiska.
Ten klient to strona odbierająca. Publikowanie zdarzeń, autoryzacja kanałów i kończenie połączeń to operacje po stronie serwera na Bird API; zobacz publikowanie zdarzeń.
Instalacja
dependencies {
implementation("com.messagebird:bird-realtime:0.1.0")
}Na Androidzie dodaj uprawnienie do internetu w manifeście. Biblioteka już go nie wnosi samodzielnie:
<uses-permission android:name="android.permission.INTERNET" />Tworzenie klienta
import com.messagebird.realtime.BirdRealtime
import com.messagebird.realtime.BirdRealtimeOptions
val bird = BirdRealtime(
BirdRealtimeOptions(
appKey = "your-app-key",
region = "us1",
)
)Wymagany jest tylko appKey oraz region (us1 lub eu1, który rozwiązuje hosta krawędzi) albo jawny wsHost. Klucz aplikacji jest publiczny i trafia do kodu klienta: identyfikuje aplikację, niczego nie autoryzuje.
Gniazdo otwiera się w momencie tworzenia klienta, więc nie wywołujesz najpierw connect(). connect() i disconnect() służą do cyklu życia aplikacji: zamknij gniazdo, gdy aktywność znika, i otwórz je ponownie, gdy wraca. Kanały, które zasubskrybowałeś, zostaną ponownie zasubskrybowane automatycznie.
disconnect() pozostawia klienta w stanie wielokrotnego użytku, więc celowo zachowuje wątek roboczy, do którego klient ogranicza swój stan. Gdy skończysz z klientem na dobre, wywołaj close(), w przeciwnym razie ten wątek i gniazdo żyją tak długo jak proces. Klasa jest AutoCloseable, więc blok use { } zrobi to za ciebie. Klient Swift nie potrzebuje odpowiednika: zwalnia oba zasoby, gdy zniknie ostatnia referencja.
Subskrypcja kanału
val orders = bird.subscribe("orders")
orders.bind("order-updated") { data ->
println("order changed: $data")
}Dane przychodzą jako kotlinx.serialization.json.JsonElement, więc odczytuj je za pomocą API do serializacji, zamiast rzutować.
Kanał, którego nazwa nie ma prefiksu private- ani presence-, jest publiczny: każdy klient z kluczem aplikacji może go subskrybować, więc traktuj jego zawartość jako czytelną dla każdego, kto może otworzyć twoją aplikację.
Kanały prywatne i obecności
Kanały prywatne i obecności są autoryzowane przez twój backend, który przechowuje sekret aplikacji. Skieruj klienta na swój endpoint: wysyła on POST z {"connection_id", "channel_name"} i oczekuje w odpowiedzi {"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") }
}Przekaż authorizer, aby podpisywać przez własny stos sieciowy.
Odrzucenie z serwera (nieprawidłowa sygnatura, aplikacja przekraczająca pojemność) trafia na połączenie, a nie na kanał, ponieważ protokół nie przenosi atrybucji kanału. Obserwuj te zdarzenia za pomocą onError. Błąd wewnątrz twojego autoryzatora emituje bird:subscription_error na kanale.
Logowanie członka
signin() informuje krawędź, do którego członka należy to połączenie. Ta tożsamość pozwala API zaadresować członka lub zakończyć jego połączenia i spełnia wymagania aplikacji skonfigurowanej do wymagania autoryzowanych połączeń.
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")
}Wywołaj signin() raz. Tożsamość pozostaje na połączeniu, więc klient loguje się ponownie automatycznie po ponownym połączeniu. Nieudane automatyczne logowanie nie ma aktywnego wywołania, z którego mogłoby rzucić wyjątek, więc pojawia się na onSigninError. Dzięki temu uszkodzony endpoint członka nie zakłóca subskrypcji kanałów.
Cykl życia połączenia
bird.onConnectionStateChange { previous, current ->
println("connection: $previous -> $current")
}
bird.onError { error ->
if (error.code == 4009) println("session ended elsewhere")
}Ponowne łączenie jest automatyczne, z wykładniczym wycofaniem z pełnym jitterem od 1 s do limitu 30 s. Kody zamknięcia 4000–4099 to odmowy i są terminalne: klient się zatrzymuje i zgłasza kod, ponieważ odmowa to decyzja, a nie przejściowy błąd. Kody 4200–4299 powodują natychmiastowe ponowne połączenie; wszystko inne stosuje wycofanie. Kanały subskrybują się ponownie ze świeżą autoryzacją przy każdym ponownym połączeniu. Zobacz cykl życia połączenia.
Transport to TLS dla każdego hosta innego niż loopback. allowInsecure dopuszcza ws:// tylko dla localhost, 127.0.0.1 i [::1], więc konfiguracja skopiowana ze środowiska deweloperskiego nie może cicho obniżyć bezpieczeństwa ruchu produkcyjnego.
Zdarzenia klienta
Gdy ustawienie client-events aplikacji jest włączone, klient subskrybujący kanał prywatny lub obecności może publikować bezpośrednio do swoich peerów:
room.trigger("client-typing", buildJsonObject { put("on", true) })Zobacz zdarzenia klienta.
Źródło
github.com/messagebird/bird-sdk-kotlin, licencja MIT. Zgłaszaj problemy tam.
Powiązane zasoby
Przejdź do dokumentacji, przewodników i przykładów dotyczących tego tematu.