guoyu/Test/备份/_已清理文件备份_周六 22512/md/屏幕流监控功能实现方案.md

368 lines
9.6 KiB
Markdown
Raw Normal View History

# 屏幕流监控功能实现方案
## 一、功能概述
基于 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": [
"<uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>"
]
}
}
```
#### 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<String, ScreenStreamWebSocketHandler> studentConnections;
// 监控端连接映射
private static ConcurrentHashMap<String, ScreenStreamWebSocketHandler> 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. **数据加密**
- 建议在生产环境使用 WSSWebSocket 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:** 可以限制同时监控的学生数量,或使用流媒体服务器方案。