Bootstrap

Android开发实战班 - 网络编程 - WebSocket 实时通信

在现代应用开发中,实时通信是许多应用的核心功能之一,例如聊天应用、实时通知、在线游戏等。WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,能够实现服务器与客户端之间的实时双向数据交换。相比于传统的 HTTP 请求,WebSocket 更加高效,适合实时数据传输。本章节将介绍 WebSocket 的基本概念、优势、在 Android 中的实现方式以及实战案例,帮助学员掌握 WebSocket 实时通信的实现。

20.1 WebSocket 简介

  • 什么是 WebSocket:

    • WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。
    • WebSocket 允许服务器主动向客户端推送数据,实现实时双向通信。
  • WebSocket 的特点:

    • 全双工通信: 服务器和客户端可以同时发送和接收数据。
    • 实时性: WebSocket 实现了真正的实时通信,适合实时数据传输。
    • 高效性: WebSocket 使用单个 TCP 连接,减少了 HTTP 请求的开销。
    • 支持跨域: WebSocket 支持跨域通信,可以在不同域名之间进行通信。
  • WebSocket 的使用场景:

    • 实时聊天应用
    • 实时通知
    • 在线游戏
    • 实时数据监控
    • 实时协作应用

20.2 WebSocket 与 HTTP 的比较

特性WebSocketHTTP
连接方式单个 TCP 连接,全双工通信短连接,每次请求都需要重新建立连接
实时性实时双向通信请求-响应模式,非实时
效率高效,减少连接开销每次请求都需要重新建立连接,效率较低
数据格式文本或二进制数据文本数据(通常是 JSON, XML 等)
支持协议WebSocket 协议HTTP 协议
适用场景实时通信静态资源加载、数据查询等

20.3 WebSocket 在 Android 中的实现

在 Android 中,可以使用 OkHttp 提供的 WebSocket 支持来实现 WebSocket 通信。OkHttp 提供了简洁的 API,可以方便地创建 WebSocket 连接、发送消息、接收消息等。

20.3.1 添加 OkHttp 依赖

build.gradle 文件中添加 OkHttp 依赖:

dependencies {
    implementation "com.squareup.okhttp3:okhttp:4.9.3"
}
20.3.2 创建 WebSocket 连接

使用 OkHttp 创建 WebSocket 连接,并处理连接、消息、关闭和错误事件。

import okhttp3.*
import okio.ByteString

class WebSocketManager {

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

    private val listener = object : WebSocketListener() {
        override fun onOpen(webSocket: WebSocket, response: Response) {
            super.onOpen(webSocket, response)
            println("WebSocket 连接已打开")
            // 发送消息
            webSocket.send("Hello, WebSocket!")
        }

        override fun onMessage(webSocket: WebSocket, text: String) {
            super.onMessage(webSocket, text)
            println("收到消息: $text")
        }

        override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
            super.onMessage(webSocket, bytes)
            println("收到二进制消息: ${bytes.hex()}")
        }

        override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
            super.onClosing(webSocket, code, reason)
            println("WebSocket 连接正在关闭: $code, $reason")
            webSocket.close(1000, null)
        }

        override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
            super.onFailure(webSocket, t, response)
            println("WebSocket 连接失败: ${t.message}")
        }
    }

    fun connect() {
        client.newWebSocket(request, listener)
    }

    fun sendMessage(message: String) {
        client.dispatcher.executorService.execute {
            client.webSocket(request, listener).send(message)
        }
    }

    fun close() {
        client.dispatcher.executorService.execute {
            client.close(1000, "Goodbye")
        }
    }
}
20.3.3 使用 WebSocket

在 Activity 或 Fragment 中使用 WebSocketManager 进行 WebSocket 连接、发送消息和关闭连接。

class WebSocketActivity : AppCompatActivity() {

    private lateinit var webSocketManager: WebSocketManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_websocket)

        webSocketManager = WebSocketManager()
        webSocketManager.connect()

        findViewById<Button>(R.id.buttonSend).setOnClickListener {
            val message = findViewById<EditText>(R.id.editTextMessage).text.toString()
            webSocketManager.sendMessage(message)
        }

        findViewById<Button>(R.id.buttonClose).setOnClickListener {
            webSocketManager.close()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        webSocketManager.close()
    }
}

20.4 WebSocket 实战案例

  1. 案例一:使用 WebSocket 实现实时聊天应用

    • 使用 OkHttp 创建 WebSocket 连接。
    • 发送和接收消息。
    • 在 Activity 中显示聊天消息。
    class ChatActivity : AppCompatActivity() {
    
        private lateinit var webSocketManager: WebSocketManager
        private lateinit var chatAdapter: ChatAdapter
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_chat)
    
            chatAdapter = ChatAdapter()
            val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
            recyclerView.adapter = chatAdapter
            recyclerView.layoutManager = LinearLayoutManager(this)
    
            webSocketManager = WebSocketManager()
            webSocketManager.connect()
    
            webSocketManager.listener = object : WebSocketListener() {
                override fun onMessage(webSocket: WebSocket, text: String) {
                    super.onMessage(webSocket, text)
                    runOnUiThread {
                        chatAdapter.addMessage(text)
                        recyclerView.scrollToPosition(chatAdapter.itemCount - 1)
                    }
                }
            }
    
            findViewById<Button>(R.id.buttonSend).setOnClickListener {
                val message = findViewById<EditText>(R.id.editTextMessage).text.toString()
                webSocketManager.sendMessage(message)
                chatAdapter.addMessage(message)
                recyclerView.scrollToPosition(chatAdapter.itemCount - 1)
            }
        }
    
        override fun onDestroy() {
            super.onDestroy()
            webSocketManager.close()
        }
    }
    
  2. 案例二:使用 WebSocket 实现实时通知

    • 使用 OkHttp 创建 WebSocket 连接。
    • 接收服务器推送的实时通知。
    • 在通知栏显示通知。

20.5 课后作业

  1. 任务一:使用 WebSocket 实现实时聊天应用

    • 使用 OkHttp 创建 WebSocket 连接。
    • 发送和接收消息。
    • 在 Activity 中显示聊天消息。
  2. 任务二:使用 WebSocket 实现实时通知

    • 使用 OkHttp 创建 WebSocket 连接。
    • 接收服务器推送的实时通知。
    • 在通知栏显示通知。
;