Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions .kiro/specs/webserver-fixes/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# 设计文档

## 概述

此设计解决VPN热点应用程序网页服务器功能中的两个关键问题:
1. 重复的剪贴板复制函数调用导致自动剪贴板修改
2. 网页服务器生命周期管理问题导致长时间运行后无法访问

解决方案涉及设置片段中的代码清理和为WebServer组件实现适当的生命周期管理。

## 架构

修复涉及三个主要组件:
1. **SettingsPreferenceFragment**:移除重复的函数调用
2. **MainActivity**:添加适当的WebServer生命周期管理
3. **WebServerManager**:增强错误处理和资源清理

## 组件和接口

### 1. SettingsPreferenceFragment修复

**问题**:`SettingsPreferenceFragment.kt`第248行包含对`copyWebBackendUrlToClipboard(currentApiKey)`的重复调用

**解决方案**:
- 移除重复的函数调用
- 确保函数只在用户选择"复制后台地址"选项时调用一次
- 保持现有的错误处理和回退行为

### 2. MainActivity生命周期管理

**当前状态**:WebServer在`onCreate()`中启动但从未停止

**增强设计**:
- 向MainActivity添加`onDestroy()`方法
- 在`onDestroy()`中调用`WebServerManager.stop()`
- 为WebServer启动失败添加错误处理
- 如果WebServer启动失败,实现优雅降级

### 3. WebServerManager增强

**当前问题**:
- 没有适当的资源清理
- 端口冲突未处理
- 启动失败没有恢复机制

**增强设计**:
- 改进`stop()`方法以确保完整的资源清理
- 添加端口冲突检测和解决
- 实现备用端口的重试机制
- 添加适当的异常处理和日志记录

### 4. OkHttpWebServer资源管理

**当前问题**:
- 套接字资源可能未正确关闭
- 线程池可能未正确关闭
- 协程作用域取消可能不完整

**增强设计**:
- 确保所有套接字在finally块中关闭
- 实现带超时的适当线程池关闭
- 在stop()方法中添加全面的资源清理
- 改进连接处理中的错误处理

## 数据模型

不需要新的数据模型。现有模型保持不变:
- `HttpRequest`
- `HttpResponse`
- `SystemStatus`

## 错误处理

### 1. 剪贴板复制错误
- 捕获剪贴板访问的`SecurityException`
- 为剪贴板失败提供用户反馈
- 如果URL生成失败,回退到API Key复制

### 2. WebServer启动错误
- 处理端口绑定失败的`IOException`
- 尝试备用端口(9999、10000、10001等)
- 记录详细的错误信息
- 提供WebServer状态的用户通知

### 3. 资源清理错误
- 处理套接字关闭期间的异常
- 即使发生错误也确保线程池关闭
- 记录清理失败而不崩溃应用

## 测试策略

### 1. 单元测试
- 使用模拟的ClipboardManager测试剪贴板复制函数
- 测试WebServer生命周期方法
- 测试错误处理场景
- 测试端口冲突解决

### 2. 集成测试
- 测试MainActivity与WebServer的生命周期
- 测试WebServer重启场景
- 测试应用终止后的资源清理

### 3. 手动测试
- 验证剪贴板复制只在用户操作时发生
- 测试长时间运行后WebServer的可访问性
- 测试应用重启场景
- 测试端口冲突场景

## 实现方法

### 阶段1:修复重复剪贴板复制
1. 移除SettingsPreferenceFragment中的重复函数调用
2. 为剪贴板功能添加单元测试
3. 通过手动测试验证修复

### 阶段2:实现MainActivity生命周期管理
1. 向MainActivity添加onDestroy()方法
2. 实现WebServer停止逻辑
3. 为启动失败添加错误处理
4. 测试生命周期管理

### 阶段3:增强WebServerManager
1. 改进stop()方法实现
2. 添加端口冲突解决
3. 实现重试机制
4. 添加全面的日志记录

### 阶段4:改进OkHttpWebServer资源管理
1. 增强套接字清理
2. 改进线程池管理
3. 添加全面的错误处理
4. 测试资源清理

## 安全考虑

- 维护现有的API Key认证
- 确保剪贴板操作不暴露敏感数据
- 适当的资源清理以防止信息泄露
- 维护现有的CORS和安全头

## 性能考虑

- 最小化对应用启动时间的影响
- 确保WebServer停止不阻塞UI线程
- 优化资源清理以快速应用终止
- 维护现有的WebServer性能特征
45 changes: 45 additions & 0 deletions .kiro/specs/webserver-fixes/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# 需求文档

## 介绍

此功能解决VPN热点应用程序网页服务器功能中的两个关键问题:
1. 剪贴板复制功能在没有用户交互的情况下被自动触发
2. 网页管理后台在应用运行一段时间后变得无法访问,即使重启应用也不行

## 需求

### 需求1:修复自动剪贴板复制问题

**用户故事:** 作为用户,我希望剪贴板复制功能只在我手动点击"复制后台地址"选项时执行,这样我的剪贴板就不会在未经我同意的情况下被修改。

#### 验收标准

1. 当用户打开API Key管理对话框时,系统不应自动修改剪贴板
2. 当用户选择"复制后台地址"选项时,系统应将网页后台URL复制到剪贴板且仅复制一次
3. 当剪贴板复制操作完成时,系统应显示确认操作的提示消息
4. 如果无法获取设备IP地址,系统应回退到仅复制API Key

### 需求2:修复网页后台可访问性问题

**用户故事:** 作为用户,我希望网页管理后台在应用的整个生命周期内以及应用重启后都能保持可访问,这样我就能持续远程管理我的热点。

#### 验收标准

1. 当MainActivity创建时,WebServer应在配置的端口上成功启动
2. 当MainActivity销毁时,WebServer应被正确停止以释放资源
3. 当应用重启时,WebServer应在干净的端口上启动,不会有冲突
4. 当WebServer遇到端口绑定错误时,系统应尝试使用备用端口
5. 当WebServer运行时,它应保持可访问直到被明确停止
6. 如果WebServer启动失败,系统应记录错误并提供用户反馈

### 需求3:改进WebServer生命周期管理

**用户故事:** 作为开发者,我希望WebServer组件有适当的生命周期管理,这样资源就能被正确分配和释放。

#### 验收标准

1. 当Application类创建时,WebServerManager应被初始化
2. 当MainActivity销毁时,WebServerManager应停止当前服务器实例
3. 当应用进程终止时,所有WebServer资源应被正确清理
4. 当WebServer停止时,所有相关的套接字和线程应被关闭
5. 当重启WebServer时,旧实例应在启动新实例之前完全停止
43 changes: 43 additions & 0 deletions .kiro/specs/webserver-fixes/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 实现计划

- [x] 1. 修复SettingsPreferenceFragment中的重复剪贴板复制函数调用
- 移除第248行的重复`copyWebBackendUrlToClipboard(currentApiKey)`调用
- 验证函数只在用户选择选项时调用一次
- 测试剪贴板功能以确保其正常工作
- _需求: 1.1, 1.2, 1.3_

- [x] 2. 为MainActivity添加适当的WebServer生命周期管理
- 在MainActivity类中实现`onDestroy()`方法
- 在onDestroy方法中添加`WebServerManager.stop()`调用
- 在onCreate中为WebServer启动失败添加错误处理
- 为WebServer生命周期事件添加日志记录
- _需求: 2.1, 2.2, 2.3, 2.6_

- [x] 3. 增强WebServerManager资源清理和错误处理
- 改进`stop()`方法以确保完整的资源清理
- 添加端口冲突检测和解决逻辑
- 实现备用端口的重试机制(9999、10000、10001)
- 添加全面的异常处理和日志记录
- _需求: 2.4, 2.5, 3.4, 3.5_

- [x] 4. 改进OkHttpWebServer资源管理和清理
- 在handleConnection方法中使用适当的try-finally块增强套接字清理
- 在stop()方法中改进带超时的线程池关闭
- 在stop()方法中添加全面的资源清理
- 确保协程作用域被正确取消和清理
- _需求: 3.1, 3.2, 3.3, 3.4_

- [x] 5. 为剪贴板操作添加全面的错误处理
- 为剪贴板访问添加SecurityException的try-catch块
- 实现无法获取IP地址时的回退行为
- 为剪贴板操作失败添加用户反馈
- 确保提示消息正确显示
- _需求: 1.3, 1.4_

- [x] 6. 测试并验证所有修复都能正常工作
- 手动测试剪贴板复制功能
- 测试长时间运行后WebServer的可访问性
- 测试应用重启场景以确保WebServer正确启动
- 验证应用终止时的适当资源清理
- 测试端口冲突场景和解决方案
- _需求: 2.1, 2.2, 2.3, 2.4, 2.5_
1 change: 1 addition & 0 deletions .trae/rules/project_rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
通过 build-macos.sh 脚本构建
106 changes: 106 additions & 0 deletions AUTO_CONNECT_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# VPNHotspot 自动连接功能指南

## 功能概述
自动连接功能允许用户在进入远程控制页面时,自动尝试连接上次保存的远程设备。

## 工作原理

### SharedPreferences 使用
- **设置存储**: SettingsPreferenceFragment 使用 `App.app.pref` (通过 SharedPreferenceDataStore)
- **设置读取**: RemoteControlFragment 使用 `App.app.pref` (统一使用 App 类中的默认 SharedPreferences)
- **设置键值**: `remote.control.auto.connect` (布尔值,默认 false)

### 数据流程
1. 用户在设置页面开启/关闭"远程控制自动连接"开关
2. 设置值保存在 App.app.pref 中
3. 当用户进入 RemoteControlFragment 时:
- 在 onResume() 中重新检查设置
- 读取 `remote.control.auto.connect` 值
- 如果为 true 且有保存的连接信息,则自动连接

## 测试步骤

### 1. 基本测试
```bash
# 运行测试脚本
./test_auto_connect_functionality.sh

# 或者手动检查
adb shell am start -n be.mygod.vpnhotspot/.MainActivity
```

### 2. 功能验证
1. **打开设置**: 进入 VPNHotspot 设置页面
2. **开启自动连接**: 找到"远程控制自动连接"开关并开启
3. **保存连接信息**: 在远程控制页面手动连接一次设备(保存IP、端口、API Key)
4. **重新进入**: 返回主页面,再次进入远程控制页面
5. **验证自动连接**: 观察是否自动开始连接

### 3. 日志检查
```bash
# 查看实时日志
adb logcat | grep -E "(RemoteControl|Settings|autoConnect)"

# 检查关键日志
# 设置变更: "Settings: 远程控制自动连接已设置为 true/false"
# 读取设置: "RemoteControl: autoConnectEnabled = true/false"
# 自动连接: "RemoteControl: 自动连接已启用,正在连接..."
```

## 常见问题排查

### 问题1: 设置不生效
**症状**: 开关开启后,进入远程控制页面不自动连接
**排查**:
1. 检查日志中的 `autoConnectEnabled` 值是否为 true
2. 确认是否有保存的连接信息(检查 `lastIp` 和 `lastApiKey`)
3. 验证 SharedPreferences 文件是否一致

### 问题2: 设置值丢失
**症状**: 重启应用后设置恢复为 false
**排查**:
1. 确认使用的是持久化存储(apply() 已调用)
2. 检查是否有其他代码重置了该值

### 问题3: 上下文不一致
**症状**: 设置页面和远程控制页面读取的值不同
**解决**: 确保都使用 `App.app.pref` 而不是不同的上下文

## 代码变更总结

### 主要修改
1. **RemoteControlFragment.kt**: 统一使用 `App.app.pref` 读取设置
2. **SettingsPreferenceFragment.kt**: 添加设置变更日志
3. **新增工具类**: AutoConnectTester 用于调试和测试

### 关键代码片段
```kotlin
// RemoteControlFragment.kt 中读取设置
val settingsPrefs = App.app.pref
val autoConnectEnabled = settingsPrefs.getBoolean("remote.control.auto.connect", false)

// SettingsPreferenceFragment.kt 中设置监听器
findPreference<TwoStatePreference>("remote.control.auto.connect")!!.setOnPreferenceChangeListener { _, newValue ->
Timber.d("Settings: 远程控制自动连接已设置为 $newValue")
true
}
```

## 验证完成标准
- [ ] 设置开关状态能正确保存
- [ ] 设置值能在 RemoteControlFragment 正确读取
- [ ] 开启自动连接后能自动连接保存的设备
- [ ] 关闭自动连接后不进行自动连接
- [ ] 重启应用后设置值保持不变
- [ ] 日志中能正确显示设置值的变化

## 调试工具使用
```bash
# 使用测试工具类(需要集成到应用中)
# 在开发者选项中添加测试按钮调用 AutoConnectTester.logAutoConnectStatus()

# 手动调试命令
adb shell am start -n be.mygod.vpnhotspot/.SettingsActivity
adb logcat -c # 清除日志
adb logcat | grep RemoteControl # 查看实时日志
```
Loading