# 屏幕流监控功能实现方案 ## 一、功能概述 基于 UniApp 开发的安卓 App,实现局域网内后台按需调取学习端屏幕画面的功能。 ### 核心需求 1. **按需启动**:后台管理端点击特定学生账号后,触发该账号绑定的安卓 App 启动屏幕捕获 2. **实时传输**:将学习画面实时传输到后台 3. **资源节省**:不点击时 App 不进行任何捕获和传输操作 4. **局域网传输**:全程在局域网内传输,不依赖外网 5. **权限兼容**:适配安卓 10+ 版本,处理好屏幕捕获权限、后台保活 ## 二、技术方案 ### 2.1 架构设计 ``` ┌─────────────────┐ WebSocket ┌─────────────────┐ │ 学生端 App │ ◄─────────────────────────► │ 后台管理端 │ │ (UniApp) │ │ (RuoYi) │ │ │ │ │ │ - 屏幕捕获 │ │ - 指令控制 │ │ - WebSocket │ │ - 画面显示 │ │ - 按需启动 │ │ - 学生管理 │ └─────────────────┘ └─────────────────┘ ``` ### 2.2 技术选型 **前端(UniApp):** - 屏幕捕获:使用 `plus.screen.capture` API(安卓原生) - 通信协议:WebSocket(实时双向通信) - 图片编码:Base64(便于 WebSocket 传输) - 后台保活:使用 `FOREGROUND_SERVICE` 权限 **后端(RuoYi):** - WebSocket 服务器:Spring WebSocket - 控制接口:RESTful API - 画面转发:WebSocket 消息转发 ### 2.3 数据流程 1. **启动监控流程**: ``` 后台点击学生 → 调用控制接口 → 发送 WebSocket 指令 → 学生端接收指令 → 开始屏幕捕获 → 传输画面 ``` 2. **停止监控流程**: ``` 后台点击停止 → 调用控制接口 → 发送 WebSocket 指令 → 学生端接收指令 → 停止屏幕捕获 ``` 3. **画面传输流程**: ``` 学生端捕获屏幕 → Base64 编码 → WebSocket 发送 → 后台接收 → 解码显示 ``` ## 三、实现细节 ### 3.1 学生端实现(UniApp) #### 3.1.1 屏幕流捕获工具类 (`screenStream.js`) **核心功能:** - WebSocket 连接管理 - 接收后台指令(启动/停止) - 屏幕捕获和传输 - 自动重连机制 - 后台保活 **关键代码:** ```javascript // 连接 WebSocket connect() { const wsUrl = this.getWebSocketUrl() this.ws = uni.connectSocket({ url: wsUrl, header: { 'Authorization': `Bearer ${uni.getStorageSync('token') || ''}` } }) } // 开始捕获 startCapture(interval = 500) { this.isCapturing = true this.captureTimer = setInterval(() => { this.captureAndSend() }, interval) } // 捕获并发送 async captureAndSend() { const screenshotData = await this.captureScreen() this.sendMessage({ type: 'screen_frame', userId: this.userId, data: screenshotData, timestamp: Date.now() }) } ``` #### 3.1.2 权限配置 在 `manifest.json` 中添加必要权限: ```json { "android": { "permissions": [ "", "" ] } } ``` #### 3.1.3 应用初始化 在 `App.vue` 中初始化屏幕流服务: ```javascript onShow() { const token = uni.getStorageSync('token') if (token) { this.initScreenStream() } } ``` ### 3.2 后端实现(RuoYi) #### 3.2.1 WebSocket 处理器 (`ScreenStreamWebSocketHandler.java`) **核心功能:** - 管理学生端连接 - 管理监控端连接 - 转发屏幕帧数据 - 发送控制指令 **关键代码:** ```java @ServerEndpoint("/ws/screenStream/{userId}") @Component public class ScreenStreamWebSocketHandler { // 学生端连接映射 private static ConcurrentHashMap studentConnections; // 监控端连接映射 private static ConcurrentHashMap monitorConnections; // 发送指令给学生端 public static void sendCommandToStudent(String studentUserId, String command, Integer interval) { ScreenStreamWebSocketHandler handler = studentConnections.get(studentUserId); if (handler != null) { handler.sendMessage(JSON.toJSONString(cmd)); } } } ``` #### 3.2.2 控制接口 (`ScreenStreamController.java`) **接口列表:** - `POST /study/screenStream/start` - 启动屏幕流捕获 - `POST /study/screenStream/stop` - 停止屏幕流捕获 - `POST /study/screenStream/checkOnline` - 检查学生是否在线 - `POST /study/screenStream/onlineCount` - 获取在线学生数 #### 3.2.3 安全配置 在 `SecurityConfig.java` 中添加 WebSocket 路径免认证: ```java .antMatchers("/ws/**").permitAll() ``` ### 3.3 后台管理端实现 #### 3.3.1 屏幕流监控页面 (`screenStream/index.vue`) **功能特性:** - 学生列表展示(带在线状态) - 点击学生开始/停止监控 - 实时显示屏幕画面 - WebSocket 接收画面数据 **关键代码:** ```javascript // 连接 WebSocket 接收画面 connectWebSocket(studentId) { const wsUrl = `ws://${host}/ws/screenStream/${studentId}` this.ws = new WebSocket(wsUrl) this.ws.onmessage = (event) => { const message = JSON.parse(event.data) if (message.type === "screen_frame") { this.currentScreenFrame = `data:image/jpeg;base64,${message.data}` } } } // 启动监控 async startMonitor() { await startScreenStream(this.currentStudent.userId, 500) this.currentStudent.isMonitoring = true this.connectWebSocket(this.currentStudent.userId) } ``` ## 四、部署说明 ### 4.1 前端部署 1. **配置服务器地址**: - 修改 `frontend-uniapp/src/utils/config.js` 中的 `SERVER_HOST` - 确保 WebSocket 地址正确 2. **编译打包**: ```bash cd frontend-uniapp npm run build:app ``` 3. **权限说明**: - 安卓 10+ 需要用户手动授予屏幕捕获权限 - 首次启动时会请求相关权限 ### 4.2 后端部署 1. **确保 WebSocket 支持**: - 检查 `pom.xml` 中已包含 `spring-boot-starter-websocket` 依赖 2. **配置安全策略**: - WebSocket 路径 `/ws/**` 已配置为免认证 - 实际认证在 WebSocket 处理器中处理 3. **启动服务**: ```bash cd RuoYi-Vue-redis mvn clean install java -jar ry-news-admin/target/ry-news-admin.jar ``` ## 五、性能优化 ### 5.1 传输优化 1. **图片质量调整**: - 默认质量 0.7(可调整) - 根据网络情况动态调整 2. **捕获频率**: - 默认 500ms(约 2 帧/秒) - 可根据需求调整 3. **数据压缩**: - 使用 JPEG 格式(比 PNG 小) - Base64 编码传输 ### 5.2 资源管理 1. **按需启动**: - 只有后台点击时才启动捕获 - 不监控时完全停止,节省资源 2. **连接管理**: - 自动重连机制 - 连接断开时停止捕获 3. **后台保活**: - 使用前台服务权限 - 确保应用在后台时也能运行 ## 六、注意事项 ### 6.1 权限问题 1. **屏幕捕获权限**: - 安卓 10+ 需要 `MediaProjection` 权限 - 需要用户手动授权 2. **后台运行权限**: - 需要 `FOREGROUND_SERVICE` 权限 - 在 `manifest.json` 中已配置 ### 6.2 兼容性 1. **安卓版本**: - 最低支持:Android 5.0 (API 21) - 推荐:Android 10+ (API 29+) 2. **网络要求**: - 必须在同一局域网内 - 确保防火墙允许 WebSocket 连接 ### 6.3 安全性 1. **认证机制**: - WebSocket 连接时携带 Token - 后端验证用户身份 2. **数据加密**: - 建议在生产环境使用 WSS(WebSocket Secure) - 局域网环境可考虑使用 HTTP ## 七、测试建议 ### 7.1 功能测试 1. **连接测试**: - 测试学生端 WebSocket 连接 - 测试后台管理端连接 2. **指令测试**: - 测试启动/停止指令 - 测试指令响应时间 3. **画面传输测试**: - 测试画面清晰度 - 测试传输延迟 - 测试多学生同时监控 ### 7.2 性能测试 1. **资源占用**: - 监控 CPU 和内存占用 - 监控网络带宽占用 2. **稳定性测试**: - 长时间运行测试 - 网络中断恢复测试 ## 八、后续优化方向 1. **WebRTC 方案**: - 如果 WebSocket 方案性能不足,可考虑 WebRTC - 需要开发原生插件支持 2. **流媒体服务器**: - 使用 RTMP/RTSP 协议 - 需要部署流媒体服务器(如 SRS) 3. **画面录制**: - 支持录制监控画面 - 保存为视频文件 4. **多画面监控**: - 支持同时监控多个学生 - 画面分屏显示 ## 九、常见问题 ### Q1: 屏幕捕获失败? **A:** 检查是否授予屏幕捕获权限,安卓 10+ 需要用户手动授权。 ### Q2: WebSocket 连接失败? **A:** 检查网络连接、防火墙设置,确保在同一局域网内。 ### Q3: 画面延迟高? **A:** 可以调整捕获间隔(默认 500ms),或降低图片质量。 ### Q4: 应用后台时停止捕获? **A:** 检查是否授予后台运行权限,确保 `FOREGROUND_SERVICE` 权限已配置。 ### Q5: 多学生同时监控性能问题? **A:** 可以限制同时监控的学生数量,或使用流媒体服务器方案。