🚨 This repository is merged into the Stream Chat Android SDK now. It is developed there under the stream-chat-android-client module. This repository is considered as archived now.
Stream Chat Client
is the official low-level Android SDK for Stream Chat, a service for building chat and messaging applications. This library supports both Kotlin and Java usage. If you can choose we recommend using Kotlin.
This library integrates directly with Stream Chat APIs and does not include UI; if you are interested in a SDK that includes UI components, you should check the stream-chat-android which comes with a collection of re-usable and customizable UI components.
- Chat Tutorial Kotlin (Uses the low level client as well as custom Views for chat)
- Stream Kotlin Docs
- Github repo for UX/Views and Sample app
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.GetStream:stream-chat-android-client:latest-version'
}
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
-
Create instance of client
val client = ChatClient.Builder(apiKey, context).build()
-
Set user
val token = "chat-token" val user = User("user-name") client.setUser(user, token, object : InitConnectionListener() { override fun onSuccess(data: ConnectionData) { val user = data.user val connectionId = data.connectionId } override fun onError(error: ChatError) { val message = error.message } }) //or client.setUser(user, token) client.subscribeFor( ConnectedEvent::class, ErrorEvent::class ) { event: ChatEvent -> // Handle events }
-
Get channels
val request = QueryChannelsRequest(FilterObject("type", "messaging"), 0, 100) client.queryChannels(request).enqueue { result -> val channels = result.data() }
-
Send message
val channelType = "messaging" val channelId = "channel-id" val message = Message() message.text = "a message" client.sendMessage(channelType, channelId, message).enqueue { result -> if (result.isSuccess) { } }
-
Handle events
// either with listener client.addSocketListener(object: SocketListener() { //override required methods }) // or with higher level subscription // first event delivers socket state: DisconnectedEvent, ConnectingEvent or ConnectedEvent client.subscribe { event: ChatEvent -> if (event is NewMessageEvent) { doSomething() } }
-
Keep using instance
val client = ChatClient.instance()
To enable logs set log level:
val client = ChatClient.Builder(apiKey, context)
.logLevel(if (BuildConfig.DEBUG) ChatLogLevel.ALL else ChatLogLevel.NOTHING)
.build()
To intercept log messages add set handler:
val client = ChatClient.Builder(apiKey, context)
.loggerHandler(object : ChatLoggerHandler {
override fun logT(throwable: Throwable) {
throwable.printStackTrace()
}
}
.build()
To intercept socket errors:
client.subscribeFor<ErrorEvent> { errorEvent: ErrorEvent ->
println(errorEvent)
}
All SDK log tags have prefix Chat:
, so to filter out only SDK logs grep the prefix:
adb logcat your.package.com | grep "Chat:"
Set of useful for debugging tags:
Chat:Http
Chat:SocketService
Chat:Events
All methods of the library return Call
object which allows to either execute
request immediately in the same thread or enqueue
listener and get result in UI thread:
interface Call<T> {
@WorkerThread
fun execute(): Result<T>
@UiThread
fun enqueue(callback: (Result<T>) -> Unit = {})
fun cancel()
fun <K> map(mapper: (T) -> K): Call<K>
fun onError(handler: (ChatError) -> Unit): Call<T>
fun onSuccess(handler: (T) -> Unit): Call<T>
fun <K> zipWith(call: Call<K>): Call<Pair<T, K>>
fun <C, B> zipWith(callK: Call<C>, callP: Call<B>): Call<Triple<T, C, B>>
}
//sync
val result = client.getMessage("message-id").execute()
//async
client.getMessage("message-id").enqueue { if (it.isSuccess) println(it.data()) }
- Client life cycle
- Push messages
- Logging
- Token Provider
- Unread messages
- SDK architecture
- Basic async
- MVVM + RxJava
- MVVM + Coroutines
- MVVM + LiveData
- Pagination: channels
- Pagination: messages
- Prefix
Chat
for public classes to avoid spoiling public class name space (generic util classes likeResult
orCall
are exceptions) - Postix
Impl
for interface implementations - No
m
field name prefix id
, notID
t
forThrowable
interface RetrfitCdnApi
, notinterface RetrofitCDNAPI
- not
setName
, butname
withBuilder
classes
open interface ChatClient {
fun onError(t:Throwable)
fun getUserId(): String
}
class ChatClientImpl: ChatClient() {
private val userId:String = ""
override fun onError(t:Throwable) {
t.printStackTrace()
}
override fun getUserId(): String {
return userId
}
}