You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android客户端与Flask服务器实现长连接及主动推送方案咨询

实现Android客户端与Flask服务器的长连接主动推送功能

需求概述

  • Android客户端启动后仅建立一次长连接,保持连接状态等待服务器主动推送消息,无需重复发起请求
  • Python Flask服务器需跟踪客户端连接状态,在客户端在线时主动推送信息

Android客户端改写代码(基于OkHttp WebSocket)

替换原有短连接HTTP请求,改用WebSocket实现长连接:

package com.example.moex_robot_client;

import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

public class MainActivity extends AppCompatActivity {
    private WebSocket webSocket;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        // 初始化OkHttpClient
        OkHttpClient client = new OkHttpClient();
        // 建立WebSocket连接,路径对应服务器的SocketIO端点
        Request request = new Request.Builder().url("ws://10.0.2.2:5000/ws").build();
        
        // 设置WebSocket监听
        webSocket = client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(@NonNull WebSocket webSocket, @NonNull okhttp3.Response response) {
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "连接服务器成功", Toast.LENGTH_SHORT).show());
            }

            @Override
            public void onMessage(@NonNull WebSocket webSocket, @NonNull String text) {
                // 接收服务器推送的文本消息,更新UI
                runOnUiThread(() -> textView.setText(text));
            }

            @Override
            public void onMessage(@NonNull WebSocket webSocket, @NonNull ByteString bytes) {
                // 处理二进制消息(按需实现)
            }

            @Override
            public void onClosing(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                webSocket.close(1000, null);
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "连接即将关闭", Toast.LENGTH_SHORT).show());
            }

            @Override
            public void onClosed(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "连接已关闭", Toast.LENGTH_SHORT).show());
            }

            @Override
            public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, okhttp3.Response response) {
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "连接失败:" + t.getMessage(), Toast.LENGTH_SHORT).show());
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 页面销毁时关闭WebSocket连接
        if (webSocket != null) {
            webSocket.close(1000, "客户端退出");
        }
    }
}

关键说明

  • 改用WebSocket协议建立长连接,替代原有的单次HTTP请求
  • 在onCreate中仅初始化一次连接,持续监听服务器推送
  • 重写WebSocketListener的回调方法,处理连接状态变化和消息接收
  • 在onDestroy中关闭连接,避免资源泄漏

Flask服务器实现代码(基于Flask-SocketIO)

借助Flask-SocketIO实现双向通信,维护客户端连接状态并主动推送消息:

首先安装依赖:

pip install flask flask-socketio eventlet

服务器代码:

from flask import Flask, request
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
# 使用eventlet作为异步服务器,支持长连接
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet')

# 存储在线客户端的sid(会话ID)
online_clients = set()

@socketio.on('connect')
def handle_connect():
    # 客户端连接时记录sid
    client_sid = request.sid
    online_clients.add(client_sid)
    print(f"客户端 {client_sid} 已连接")
    emit('message', '欢迎连接服务器', room=client_sid)

@socketio.on('disconnect')
def handle_disconnect():
    # 客户端断开时移除sid
    client_sid = request.sid
    online_clients.remove(client_sid)
    print(f"客户端 {client_sid} 已断开")

def send_broadcast_message(message):
    # 向所有在线客户端推送消息
    if online_clients:
        socketio.emit('message', message, room=None)

# 示例:模拟定时推送任务(实际可根据业务触发)
import threading
import time

def periodic_push():
    while True:
        time.sleep(5)
        send_broadcast_message("服务器定时推送消息:" + time.strftime("%Y-%m-%d %H:%M:%S"))

if __name__ == '__main__':
    # 启动定时推送线程
    threading.Thread(target=periodic_push, daemon=True).start()
    # 启动服务器,监听5000端口
    socketio.run(app, host='0.0.0.0', port=5000, debug=True)

关键说明

  • 使用Flask-SocketIO实现长连接,支持服务器主动推送
  • 通过online_clients集合维护在线客户端的会话ID
  • handle_connect和handle_disconnect事件分别处理客户端的连接与断开,更新在线状态
  • send_broadcast_message方法可向所有在线客户端推送消息,也可指定单个客户端推送(通过room=client_sid)
  • 示例中加入定时推送任务,实际可根据业务逻辑触发推送

核心实现思路

  • Android端:用WebSocket替代普通HTTP请求,建立长连接后持续监听服务器消息,避免重复发起请求
  • 服务器端:基于SocketIO实现双向通信,通过连接事件维护客户端在线状态,主动触发消息推送逻辑

内容的提问来源于stack exchange,提问作者Oleg Kolosovsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 02:32:43