OddSockets Kotlin SDK
Official Kotlin SDK for OddSockets real-time messaging platform
Overview & Features
The OddSockets Kotlin SDK provides a powerful, coroutine-based interface for real-time messaging in Android applications and JVM environments.
Android Native
Built specifically for Android with lifecycle-aware components and modern architecture patterns.
Kotlin Coroutines
Fully async with Kotlin coroutines and Flow for reactive programming patterns.
Type Safety
Complete type safety with Kotlin's null safety and comprehensive error handling.
High Performance
Optimized for mobile with efficient WebSocket connections and smart resource management.
Cost Effective
No per-message pricing, industry-standard 32KB message limits, transparent pricing.
Session Stickiness
Built-in session management for consistent worker assignment and optimal performance.
Installation
dependencies {
implementation("com.oddsockets:kotlin-sdk:1.0.0")
}
dependencies {
implementation 'com.oddsockets:kotlin-sdk:1.0.0'
}
<dependency>
<groupId>com.oddsockets</groupId>
<artifactId>kotlin-sdk</artifactId>
<version>1.0.0</version>
</dependency>
Quick Start
Basic Usage
import com.oddsockets.OddSocketsClient
import com.oddsockets.config.OddSocketsConfig
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val client = OddSocketsClient(
OddSocketsConfig.default("ak_live_1234567890abcdef")
)
val channel = client.channel("my-channel")
// Subscribe to messages
channel.subscribe { message ->
println("Received: ${message.message}")
}
// Publish a message
channel.publish("Hello, World!")
}
Android Usage
class MainActivity : AppCompatActivity() {
private lateinit var client: OddSocketsClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
client = OddSocketsClient(
OddSocketsConfig.default("ak_live_1234567890abcdef")
)
val channel = client.channel("chat-room")
// Subscribe with lifecycle awareness
lifecycleScope.launch {
channel.messageFlow.collect { message ->
// Update UI with new message
updateChatUI(message)
}
}
// Publish message
lifecycleScope.launch {
channel.publish("Hello from Android!")
}
}
override fun onDestroy() {
super.onDestroy()
client.close()
}
}
Coroutines & Flow
// Using Flow for reactive programming
channel.messageFlow
.filter { it.metadata?.get("priority") == "high" }
.map { it.message.toString() }
.collect { highPriorityMessage ->
handleUrgentMessage(highPriorityMessage)
}
// Connection state monitoring
client.connectionState
.collect { state ->
when (state) {
ConnectionState.CONNECTED -> showConnectedUI()
ConnectionState.DISCONNECTED -> showDisconnectedUI()
ConnectionState.RECONNECTING -> showReconnectingUI()
}
}
Configuration
Client Configuration
val client = OddSocketsClient.create("ak_live_1234567890abcdef") {
userId = "user-123" // Optional: User identifier
autoConnect = true // Optional: Auto-connect on creation
reconnectAttempts = 5 // Optional: Max reconnection attempts
heartbeatInterval = 30.seconds // Optional: Heartbeat interval
timeout = 10.seconds // Optional: Operation timeout
}
Channel Configuration
// Subscribe with options
channel.subscribe(messageHandler) {
enablePresence = true // Enable presence tracking
retainHistory = true // Retain message history
filterExpression = "user.premium == true" // Message filter
}
// Publish with options
channel.publish("Hello World!") {
ttl = 3600 // Time to live (seconds)
metadata = mapOf("priority" to "high") // Additional metadata
storeInHistory = true // Store in message history
}
Examples
Explore comprehensive examples demonstrating the OddSockets Kotlin SDK in action:
Performance & Compatibility
OddSockets Kotlin SDK delivers superior performance with broad compatibility:
Platform Support
- Android API 21+ (5.0 Lollipop)
- JVM 8+ (Server-side)
- Kotlin 1.8+
- Kotlin Multiplatform
Dependencies
- Kotlin Coroutines
- Ktor Client
- Kotlinx Serialization
- Kotlin Flow
Framework Integrations
The OddSockets Kotlin SDK works seamlessly with modern Android architecture patterns and frameworks:
Jetpack Compose
@Composable
fun ChatScreen(client: OddSocketsClient) {
val messages by client.channel("chat")
.messageFlow
.collectAsState(initial = emptyList())
val connectionState by client.connectionState
.collectAsState()
Column {
// Connection status
when (connectionState) {
ConnectionState.CONNECTED -> {
Text("Connected", color = Color.Green)
}
ConnectionState.RECONNECTING -> {
Text("Reconnecting...", color = Color.Orange)
}
else -> {
Text("Disconnected", color = Color.Red)
}
}
// Messages list
LazyColumn {
items(messages) { message ->
MessageItem(message = message)
}
}
// Send message
var inputText by remember { mutableStateOf("") }
Row {
TextField(
value = inputText,
onValueChange = { inputText = it }
)
Button(
onClick = {
client.channel("chat").publish(inputText)
inputText = ""
}
) {
Text("Send")
}
}
}
}
MVVM with ViewModel
class ChatViewModel : ViewModel() {
private val client = OddSocketsClient(
OddSocketsConfig.default("ak_live_1234567890abcdef")
)
private val channel = client.channel("chat-room")
private val _messages = MutableLiveData<List<Message>>()
val messages: LiveData<List<Message>> = _messages
private val _connectionState = MutableLiveData<ConnectionState>()
val connectionState: LiveData<ConnectionState> = _connectionState
init {
// Observe connection state
viewModelScope.launch {
client.connectionState.collect { state ->
_connectionState.value = state
}
}
// Subscribe to messages
viewModelScope.launch {
channel.subscribe { message ->
val currentMessages = _messages.value ?: emptyList()
_messages.value = currentMessages + message
}
}
}
fun sendMessage(text: String) {
viewModelScope.launch {
try {
channel.publish(text)
} catch (e: OddSocketsException) {
// Handle error
Log.e("ChatViewModel", "Failed to send message", e)
}
}
}
override fun onCleared() {
super.onCleared()
client.close()
}
}
Dagger Hilt Integration
@Module
@InstallIn(SingletonComponent::class)
object OddSocketsModule {
@Provides
@Singleton
fun provideOddSocketsClient(): OddSocketsClient {
return OddSocketsClient(
OddSocketsConfig.default("ak_live_1234567890abcdef")
)
}
}
@HiltViewModel
class ChatViewModel @Inject constructor(
private val oddSocketsClient: OddSocketsClient
) : ViewModel() {
private val channel = oddSocketsClient.channel("chat")
val messages = channel.messageFlow
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = emptyList()
)
fun sendMessage(text: String) {
viewModelScope.launch {
channel.publish(text)
}
}
}
Room Database Integration
@Entity(tableName = "messages")
data class MessageEntity(
@PrimaryKey val id: String,
val channel: String,
val content: String,
val timestamp: Long,
val userId: String
)
@Dao
interface MessageDao {
@Query("SELECT * FROM messages WHERE channel = :channel ORDER BY timestamp ASC")
fun getMessagesForChannel(channel: String): Flow<List<MessageEntity>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertMessage(message: MessageEntity)
}
class ChatRepository @Inject constructor(
private val messageDao: MessageDao,
private val oddSocketsClient: OddSocketsClient
) {
fun getMessages(channelName: String): Flow<List<MessageEntity>> {
return messageDao.getMessagesForChannel(channelName)
}
suspend fun subscribeToChannel(channelName: String) {
val channel = oddSocketsClient.channel(channelName)
channel.subscribe { message ->
// Store message in local database
val entity = MessageEntity(
id = message.id,
channel = channelName,
content = message.message.toString(),
timestamp = message.timestamp.toEpochMilli(),
userId = message.userId
)
messageDao.insertMessage(entity)
}
}
suspend fun sendMessage(channelName: String, content: String) {
oddSocketsClient.channel(channelName).publish(content)
}
}