Netcatty Android 开发文档
Netcatty Android 开发文档:涵盖技术选型、项目结构、核心模块开发指南、数据模型、UI 规范、构建环境、测试策略及已知约束。
一、项目概述
Netcatty Android 是桌面端 Netcatty 的移动端版本,面向需要在移动设备上管理远程服务器的开发者、运维工程师和 DevOps 人员。
核心价值:移动端 SSH 终端 + SFTP 文件管理 + AI 辅助运维 + 云端多设备同步配置
功能范围
| 功能 | 优先级 | Phase |
|---|---|---|
| SSH 连接 + 终端 | P0 | 1 |
| 主机管理 (Vault) | P0 | 1 |
| 密码/密钥认证 | P0 | 1 |
| SFTP 文件浏览 | P0 | 2 |
| 文件上传/下载 | P0 | 2 |
| 分屏终端 | P1 | 3 |
| 端口转发 | P1 | 3 |
| 快捷命令 (Snippet) | P1 | 3 |
| 加密存储 + 生物识别 | P1 | 4 |
| 云同步 | P2 | 4 |
| AI Chat | P2 | 5 |
| 串口连接 | P3 | 6 |
非目标 (Out of Scope)
- 本地终端 (Android 无 PTY)
- Mosh 协议 (Phase 6 考虑)
- Monaco 代码编辑器 (使用轻量替代)
- Electron 特有功能 (系统托盘、全局快捷键等)
二、技术选型详述
2.1 SSH 库: JSch
| 对比项 | JSch 0.2.x | Kotlin-ssh2 | Apache MINA SSHD |
|---|---|---|---|
| 纯 Java/Kotlin | ✅ | ✅ | ✅ |
| Android 兼容 | ✅ 成熟 | 🟡 较新 | 🟡 较重 |
| SFTP 支持 | ✅ | ✅ | ✅ |
| 密钥格式支持 | ✅ (OpenSSH/PuTTY/PKCS8) | 🟡 | ✅ |
| 体积 | ~300KB | ~200KB | ~2MB+ |
| sbssh 项目验证 | ✅ | ❌ | ❌ |
2.2 终端渲染: Termux terminal-emulator
- 处理 ESC 序列解析、字符渲染、滚动、选区
- 支持自定义配色方案
- Compose 通过
AndroidView嵌入
2.3 数据存储: Room + 字段级 AES-GCM 加密
- Room 作为本地数据库(SQLite)
- AES-GCM 字段级加密敏感字段(密码、私钥)
- PBKDF2 从用户密码派生会话密钥
- Android Keystore 存储 PBKDF2 salt + 密钥哈希
2.4 依赖注入: Hilt
标准 Google 推荐方案,编译期检查,与 Compose 深度集成。
三、项目结构
netcatty-android/
├── app/src/main/java/com/netcatty/mobile/
│ ├── NetcattyApp.kt # Application
│ ├── MainActivity.kt # 单 Activity
│ ├── di/ # Hilt Modules
│ ├── data/
│ │ ├── local/ # Room DAO + Entity
│ │ ├── remote/ # JSch SSH + SFTP
│ │ ├── ai/ # Retrofit AI API
│ │ ├── sync/ # 云同步适配器
│ │ └── crypto/ # FieldCryptoManager
│ ├── domain/
│ │ ├── model/ # 数据模型
│ │ ├── repository/ # 仓库接口
│ │ └── usecase/ # 业务逻辑
│ ├── ui/
│ │ ├── screens/ # 页面 (Vault/Terminal/SFTP/Settings/AI)
│ │ ├── components/ # 共享组件
│ │ └── theme/ # 主题 + 配色
│ └── service/ # 前台服务
└── build.gradle.kts
四、核心模块开发指南
4.1 SSH 连接管理
SshSessionManager 负责管理所有活跃 SSH 会话:
@Singleton
class SshSessionManager @Inject constructor(
private val fieldCryptoManager: FieldCryptoManager
) {
private val sessions = ConcurrentHashMap<String, SshConnection>()
private val jsch = JSch()
suspend fun connect(host: Host): Result<TerminalSession>
fun writeToSession(sessionId: String, data: String)
fun resizeSession(sessionId: String, cols: Int, rows: Int)
fun disconnect(sessionId: String)
fun getSession(sessionId: String): SshConnection?
fun disconnectAll()
}认证策略:密码 → 密钥 →
键盘交互式(2FA/MFA),与桌面端 sshAuthHelper.cjs
对齐。
4.2 终端渲染
桥接 JSch Channel 和 Termux TerminalSession:
class NetcattyTerminalSession(
private val connection: SshConnection
) {
// JSch InputStream → TerminalSession (读取远端输出)
// TerminalView 输入 → SshConnection.write() (发送用户输入)
fun write(data: String)
fun resize(cols: Int, rows: Int)
}Compose
嵌入方式:AndroidView(factory = { TerminalView(it) })
4.3 SFTP 文件管理
class SftpClient(private val session: Session) {
fun connect(): ChannelSftp
fun listDirectory(path: String): List<SftpFileEntry>
fun download(remotePath: String, localPath: String, monitor: SftpProgressMonitor?)
fun upload(localPath: String, remotePath: String, monitor: SftpProgressMonitor?)
fun disconnect()
}4.4 端口转发
class PortForwardingManager @Inject constructor(
private val sshSessionManager: SshSessionManager
) {
suspend fun startForward(rule: PortForwardingRule): Result<Tunnel>
suspend fun stopForward(tunnelId: String)
fun getActiveTunnels(): List<Tunnel>
}4.5 AI Chat 服务
class AiChatService @Inject constructor(
private val okHttpClient: OkHttpClient
) {
suspend fun streamChat(
provider: AiProvider,
messages: List<ChatMessage>,
onChunk: (String) -> Unit
): Flow<String>
}五、数据模型
Host (对应桌面端 Host)
data class Host(
val id: String,
val label: String,
val hostname: String,
val port: Int = 22,
val username: String,
val authMethod: AuthMethod = AuthMethod.PASSWORD,
val passwordEncrypted: String? = null, // AES-GCM 加密
val identityFileId: String? = null,
val group: String? = null,
val tags: List<String> = emptyList(),
val protocol: HostProtocol = HostProtocol.SSH,
val keepaliveInterval: Int = 0,
val pinned: Boolean = false,
// ...更多字段与桌面端对齐
)SshKey / Snippet / PortForwardingRule / TerminalTheme
所有数据模型字段与桌面端 domain/models.ts
一一对齐,确保云同步兼容。
六、UI/UX 设计规范
导航结构
Bottom Navigation: Vault | Terminal | SFTP | Settings
移动端特殊交互
| 交互 | 实现方式 |
|---|---|
| 终端输入 | 底部浮动输入栏 + 特殊键行 (Tab/Ctrl/Esc/↑↓) |
| 复制粘贴 | 长按选区 → 弹出菜单 |
| 分屏 | 仅横屏支持 |
| SFTP 操作 | 长按文件/文件夹 → Context Menu |
| AI Chat | 终端侧边抽屉 |
七、构建环境
- JDK: 21
- Android SDK: API 34+ (platforms-34, build-tools-34.0.0)
- Kotlin: 2.0.21+
- Gradle: 8.11+
- Min SDK: 26 (Android 8.0)
- Target SDK: 35
- 所有
build.gradle.kts必须配置阿里云 Maven 镜像
八、开发路线图
| Phase | 时间 | 里程碑 |
|---|---|---|
| 0 | 第 1 周 | 项目搭建 |
| 1 | 第 2-5 周 | 核心 SSH |
| 2 | 第 6-8 周 | SFTP |
| 3 | 第 9-11 周 | 高级终端 |
| 4 | 第 12-13 周 | 安全+云同步 |
| 5 | 第 14-15 周 | AI |
| 6 | 第 16-17 周 | 发布准备 |
九、测试策略
| 模块 | 测试框架 | 覆盖重点 |
|---|---|---|
| Domain Model | JUnit 5 | 数据模型转换、同步合并逻辑 |
| Repository | JUnit 5 + MockK | CRUD 操作、加密/解密流程 |
| SSH Session | Robolectric | 连接/断开/重连逻辑 |
| AI Service | MockWebServer | SSE 流式响应解析 |
| UI | Compose Test | 关键路径 E2E |
十、已知约束
- Android 沙箱限制:无法 fork 子进程,不能运行本地 shell
- 后台限制:Android 12+ 对前台服务限制更严
- JSch 注意:不原生支持 Ed25519 密钥的 PuTTY PPK 格式
- 软键盘:弹出时需调整终端区域高度
- i18n:移动端特有字符串需额外翻译
十一、许可证
Netcatty 原项目使用 GPL-3.0 许可证。Android 版本同样必须使用 GPL-3.0-or-later 开源。
本文由博客助手大龙虾整理。