WebSocket in Android

WebSocket in Android


In modern mobile apps, real-time data transfer is no longer a luxury — it’s a necessity. Whether you’re building a chat app, live sports updates, stock market feeds, or collaborative tools, you need something faster and more persistent than REST APIs.

What are WebSockets?

WebSocket is a communication protocol that provides full-duplex (two-way) communication channels over a single TCP connection.

Unlike REST APIs, which work on request-response, WebSocket provides persistent connections. This means both client and server can send data anytime — without waiting for a request.

Why Use WebSocket in Android?

Here are some use-cases where WebSocket is a perfect fit:

  • Chat messaging apps (like WhatsApp, Messenger)
  • Real-time stock updates
  • Live sports scores or match commentary
  • Collaborative editing (like Google Docs)
  • Notification systems

How WebSocket Works 

  1. Client sends a WebSocket handshake request to the server.
  2. If accepted, the server upgrades the connection from HTTP to WebSocket.
  3. Now, both sides can send messages anytime, without re-establishing connection.
  4. The connection stays open unless one party closes it or a network error occurs.

WebSocket in Android — Using okHttp 

We will use OkHttp by Square — a popular library for HTTP and WebSocket in Android.

Step 1: Add Dependencies

// In app/build.gradle
implementation("com.squareup.okhttp3:okhttp:4.12.0")        

Step 2: Create WebSocket Listener

class EchoWebSocketListener : WebSocketListener() {

    override fun onOpen(webSocket: WebSocket, response: Response) {
        Log.d("WebSocket", "Connected")
        webSocket.send("Hello from Android!")
    }

    override fun onMessage(webSocket: WebSocket, text: String) {
        Log.d("WebSocket", "Message Received: $text")
    }

    override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
        webSocket.close(1000, null)
        Log.d("WebSocket", "Closing: $code $reason")
    }

    override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
        Log.e("WebSocket", "Error: ${t.message}")
    }
}        

Step 3: Connect to WebSocket Server

fun startWebSocket() {
    val client = OkHttpClient()

    val request = Request.Builder()
        .url("wss://echo.websocket.org") // Replace with your server
        .build()

    val listener = EchoWebSocketListener()
    val ws = client.newWebSocket(request, listener)

    client.dispatcher.executorService.shutdown()
}        

Real-World Example: Live Chat App

Let’s simulate a real-time chat system. In a real app, you’ll have a backend like Node.js, Spring Boot, or Firebase handling the WebSocket server.

Features:

  • Persistent connection with the server
  • Real-time sending and receiving of messages
  • Automatic reconnection on failure

Reconnection Strategy (Advanced)

class ReconnectingWebSocket(
    private val url: String,
    private val listener: WebSocketListener
) {
    private var webSocket: WebSocket? = null
    private val client = OkHttpClient()
    private var retryCount = 0

    fun connect() {
        val request = Request.Builder().url(url).build()
        webSocket = client.newWebSocket(request, object : WebSocketListener() {

            override fun onOpen(ws: WebSocket, response: Response) {
                retryCount = 0
                listener.onOpen(ws, response)
            }

            override fun onFailure(ws: WebSocket, t: Throwable, response: Response?) {
                listener.onFailure(ws, t, response)
                retryCount++
                Handler(Looper.getMainLooper()).postDelayed({
                    connect()
                }, (1000L * retryCount).coerceAtMost(10000L))
            }

            override fun onMessage(ws: WebSocket, text: String) {
                listener.onMessage(ws, text)
            }

            override fun onClosing(ws: WebSocket, code: Int, reason: String) {
                listener.onClosing(ws, code, reason)
            }
        })
    }

    fun send(message: String) {
        webSocket?.send(message)
    }

    fun close() {
        webSocket?.close(1000, null)
    }
}        

Handling WebSocket in ViewModel with LiveData (MVVM)

class ChatViewModel : ViewModel() {

    private val _chatMessages = MutableLiveData<String>()
    val chatMessages: LiveData<String> = _chatMessages

    private lateinit var webSocket: WebSocket

    fun initWebSocket() {
        val client = OkHttpClient()
        val request = Request.Builder().url("wss://echo.websocket.org").build()

        webSocket = client.newWebSocket(request, object : WebSocketListener() {
            override fun onMessage(webSocket: WebSocket, text: String) {
                _chatMessages.postValue(text)
            }
        })
    }

    fun sendMessage(msg: String) {
        webSocket.send(msg)
    }

    override fun onCleared() {
        webSocket.close(1000, null)
        super.onCleared()
    }
}        

What Happens Internally When You Connect via WebSocket?

  1. You open a URL like wss://score.server.com/live
  2. The server responds with a special HTTP 101 Switching Protocols
  3. Now the channel becomes bi-directional (like a phone call).
  4. Data is transferred in small, lightweight frames instead of full HTTP packets.
  5. This connection stays alive until:

  • You close it manually
  • Network drops
  • Server closes it

Security Considerations

  • Always use wss:// (WebSocket Secure)
  • Authenticate using tokens (JWT) during handshake
  • Implement server-side validation

Testing Tools for WebSocket

Common Errors & Fixes

Article content

How Server and Android Work Together

Real-World Example:

Imagine a chat app — Anand sends a message on his Android phone, and instantly, the message appears on his friend’s device.

That’s WebSocket at work.

Server Responsibilities in WebSocket

1. Accept the Connection

When the Android app connects to ws://yourserver.com, the WebSocket server:

  • Accepts the handshake request
  • Keeps the socket connection open
  • Assigns a temporary identity to the connection

2. Authenticate the User

Since WebSockets don’t have built-in login, we do manual authentication:

  • The Android app sends a JWT token as a message
  • The server checks this token to verify the user
  • If verified, the server saves:  userId → WebSocket connection

Example:  Android → { "type": "auth", "token": "abc.jwt.token" }  Server → verifies → adds user to map

3. Handle Messages (Send / Receive)

Once authenticated:

  • Android can send a chat message: { "type": "chat", "text": "Hello" }
  • Server checks the type and processes it
  • For group chat: broadcast to all users
  • For private chat: send to a specific user

Key Idea: WebSocket message = small JSON string with a “type”

4. Disconnect Handling

When a user leaves the app or disconnects:

  • WebSocket server detects it
  • It removes the user from its active list
  • Frees up memory, avoids leaking connections

WebSocket Server Architecture (Concept)

Map of Connected Users

The server keeps a list like this in memory:

{
  "anand123": WebSocketConnectionObject,
  "john456": WebSocketConnectionObject
}        

This way, it knows:

  • Who is online
  • Where to send messages

Heartbeat / Ping-Pong (In Production)

To ensure users are still connected:

  • The server sends a ping every 30 seconds
  • If no pong reply comes back → disconnect user

This prevents memory waste from dead connections.

Authentication with JWT

Why JWT?

  • It’s a secure token given after login
  • You don’t need sessions or cookies
  • Server just needs to verify the token once

Flow:

  1. Android logs in → gets JWT token
  2. WebSocket sends: { type: "auth", token: "..." }
  3. Server verifies using secret key
  4. If valid → user is authenticated

Full Flow Diagram (Android to Server)

Article content

Why “WebSocket Connection Timeout” Happens in Android

1. Server is not reachable

  • Your WebSocket server (wss:// or ws://) is not running or temporarily offline
  • Android can’t connect → waits → times out

Solution: Make sure server is up, correct IP/port, and firewall is not blocking it

2. Wrong URL / DNS not resolving

  • Using wrong ws:// or wss:// address
  • If you’re using domain, DNS might not resolve
  • If you’re on localhost or 127.0.0.1, it won’t work on real device (use IP)

 Try opening the URL in WebSocket testing tools like WebSocket King to confirm it’s reachable.

3. SSL (wss) issues

  • If you’re using wss:// (secure WebSocket) and:
  • SSL certificate is invalid or expired
  • Using self-signed cert without trusting it in Android

 Solution:  Use a valid HTTPS SSL certificate (e.g., from Let’s Encrypt)  Or test with ws:// on development (not production)

4. Port Blocked by Firewall / Network

  • Android device can’t reach the server port
  • Example: port 8080 blocked on public Wi-Fi or office network
  • Mobile data might block WebSocket ports

 Try using common ports like 443 or 80

5. Client Timeout (Android SDK/WebSocket Lib)

  • WebSocket client like okhttp has a default connection timeout
  • If the server is slow to accept the connection, Android cancels it

Solution: Increase timeout in your code:
val client = OkHttpClient.Builder()
    .connectTimeout(15, TimeUnit.SECONDS) // Increase timeout
    .build()        

6. Poor or Lost Network

  • Internet connection on device is slow, unstable, or temporarily lost during connection attempt

Check network status before attempting connection:
fun isNetworkAvailable(context: Context): Boolean {
    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val network = cm.activeNetwork
    val capabilities = cm.getNetworkCapabilities(network)
    return capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true
}        

7. Trying to connect from emulator with localhost

  • Emulator’s localhost = emulator itself, not your PC
  • Use 10.0.2.2 to refer to your local PC server from Android emulator

Avoid WebSocket Timeout

  1. Use try/catch and proper callbacks to show user-friendly error
  2. Retry on failure with exponential backoff
  3. Use stable internet check before connecting
  4. Log actual failure reason (timeout vs. host unreachable vs. SSL fail)
  5. Use production-grade ports and SSL

Summary

WebSocket opens a world of real-time features in Android that REST APIs can’t match. With proper architecture (like MVVM), reconnection logic, and secure authentication — you can build blazing fast, interactive apps.


Thank you for reading. 🙌🙏✌.

Found this helpful? Don’t forgot to clap 👏 and follow me for more such useful articles about Android development and Kotlin or buy us a coffee here

If you need any help related to Android, Kotlin. I’m always happy to help you.

Follow me on:

Medium, Github, Instagram , YouTube & WhatsApp

To view or add a comment, sign in

More articles by Anand Gaur

  • Build Android Apps 3x Faster with CLI and AI Agents

    If you are an Android developer, you already know the pain. You open Android Studio, wait for Gradle to sync, click…

    2 Comments
  • These 7 AI Concepts Will Put You Ahead of 90% of People

    Everyone is talking about AI right now. From tools like ChatGPT, Claude, Gemini to coding assistants and image…

    2 Comments
  • On-Device AI in Android: Build Smart Apps Without Internet

    On-device AI is changing the way we build mobile apps. Instead of relying on cloud APIs for every intelligent feature…

  • How LiveData Works Internally in Android

    In Android development, one problem kept showing up again and again — managing UI lifecycle and data synchronization…

  • Android 17- Everything You Need to Know

    Have you ever woken up one morning, picked up your phone, and thought — “I wish my phone could just do this one thing…

    3 Comments
  • How ViewModel Works Internally in Android

    Have you ever filled a long form in an app, rotated your phone by mistake… and watched everything disappear? The screen…

    8 Comments
  • Top MVVM Android Interview Questions and Answers

    Whether you’re preparing for your Android interview or brushing up on architecture patterns, this comprehensive guide…

  • AI and Machine Learning Roadmap

    Are you fascinated by how Netflix recommends shows, how ChatGPT writes, or how self-driving cars work? Welcome to the…

  • Offline-First System in Android

    Imagine you’re reading a newspaper on a train that goes through several tunnels. In the old days, you’d have the entire…

    3 Comments
  • Jetpack Navigation 3 in Android

    Jetpack Navigation 3 is a new, Compose‑first navigation library that gives you full control over the back stack, better…

Others also viewed

Explore content categories