# sky adb 项目文档 本文档基于当前源码实际状态整理,用于说明 sky adb 的功能范围、项目结构、开发规范、维护规范和性能要求。后续开发应在功能或工程结构变化后同步更新本文档。 ## 项目定位 sky adb 是一款运行在 Android 手机上的支持简体中文和英文的 ADB 管理工具。它通过 WiFi ADB / Wireless Debugging 或 USB OTG 连接并管理目标 Android 设备,适用于手机、平板、电视、盒子等设备的日常维护。 项目采用单 Android App 模块。 ## 当前功能 - 无线调试配对:输入配对 IP、配对端口、配对码后调用 Kadb Pairing。 - 手动连接设备:输入目标设备 IP 和 ADB 端口。 - USB OTG:识别 ADB / Fastboot 接口,授权后连接;Fastboot 命令页提供设备摘要、重启快捷按钮、手动查询和结果复制。 - 最近设备:保存 WiFi 设备记录,支持点击回填 IP 和端口;USB 总线地址仅用于当前插入,不持久化。 - 设备详情:读取品牌、型号、Android 版本、SDK、ABI、分辨率、电池信息。 - 应用管理:读取目标设备应用列表,支持用户应用、系统应用分类,支持搜索、启动、停止、卸载。 - APK 安装:选择本机 APK 并安装到已连接设备。 - 在线下载:从 HTTP / HTTPS 链接下载 APK 或普通文件,支持进度、取消、下载后安装或推送。 - 文件管理:支持本机与目标设备双栏目录浏览、上传、下载、新建文件夹、重命名和删除文件。 - 本机应用安装到目标设备:列出本机用户应用,支持单 APK 应用导出并安装到目标设备。 - 截图:调用目标设备 `screencap`,拉取截图到本机缓存并预览,需要时再由用户选择保存位置。 - 系统日志:读取目标设备最近系统日志,支持复制日志内容,便于排查目标设备问题。 - 虚拟遥控器:采用实体遥控器式布局,提供电源、唤醒、息屏、方向与确认、返回、主页、菜单、音量、静音和媒体控制共 17 个按键。默认字号下紧凑手机也可一屏操作;横屏自动切换双区布局,所有按键触控区域至少 48dp。状态提示固定占位,错误提示可点击查看完整原因,反馈不会推移按键。 - 屏幕镜像:基于官方 `scrcpy-server-v5.0.1`、Kadb `localabstract` 流、`SurfaceView` 和 `MediaCodec` 实现画面预览与远程触控;支持音频转发与中文输入;镜像页支持控制区显示/隐藏,输入键盘默认关闭,可独立显示和关闭;关闭输入区时收起软键盘并释放焦点。画面按远端视频比例居中显示。 - 命令页:ADB 模式执行 Shell 命令,Fastboot 模式发送协议命令;支持粘贴带 `adb` / `adb shell` / `fastboot` 前缀的输入,展示输出和执行状态。 - 局域网发现:优先通过 Android NSD / mDNS 自动发现 ADB 服务,支持 `_adb._tcp.`、`_adb-tls-pairing._tcp.`、`_adb-tls-connect._tcp.`;自动发现无结果时,保留 TCP 网段扫描和 ADB 协议轻握手确认作为兜底。 - 诊断日志:仅记录错误和异常信息,覆盖 WiFi ADB、配对、应用、文件、截图、系统日志、遥控器、屏幕镜像等功能,支持复制排查。 - 设置:支持默认端口、连接超时、命令超时、扫描网段、屏幕镜像画质、主题模式配置。 ## 技术栈 依赖版本统一维护在 `gradle/libs.versions.toml`,Gradle 版本和校验值维护在 `gradle/wrapper/gradle-wrapper.properties`。 | 组件 | 当前版本 | | --- | --- | | Gradle Wrapper / Android Gradle Plugin | 9.8.1 / 9.4.1 | | Kotlin | 2.4.21 | | Compose BOM / Material 3 | 2026.09.00 / 由 BOM 管理 | | Activity / AppCompat | 1.13.0 / 1.8.0 | | Lifecycle / Navigation Compose | 2.11.0 / 2.10.2 | | Coroutines / DataStore Preferences | 1.11.0 / 1.2.1 | | Kadb / kadb-mdns | 2.1.5 / 2.1.4 | | scrcpy-server | 5.0.1 | | OkHttp / Okio | 5.5.0 / 3.18.2 | | fastboot-java / Timber | 1.2.0 / 5.0.1 | | JUnit / AndroidX Test Runner / AndroidX Test JUnit | 4.13.2 / 1.7.0 / 1.3.0 | `kadb-mdns` 独立于核心库指定版本,以各模块实际发布的制品为准。 ## 运行范围 - 运行 sky adb 的设备:最低 Android 7.0,API 24。 - 编译目标:compileSdk 37,targetSdk 37。 - Android 17 局域网:targetSdk 37 需声明并运行时申请 `ACCESS_LOCAL_NETWORK`,用于 mDNS 发现、网段扫描和 WiFi ADB 连接。 - 被连接设备:支持 ADB over TCP / Wireless Debugging,或已开启 USB 调试并完成授权。Android 11+ 推荐使用无线调试配对;传统 WiFi ADB 设备通常使用 `5555` 端口。 - 屏幕镜像目标设备:以目标设备是否支持 scrcpy server、视频编码和 ADB socket 转发为准;默认画质使用均衡模式,高负载设备可在设置中切换为流畅模式。 ## 项目结构 ```text skyadb/ ├── .github/workflows/ │ ├── android-checks.yml # push / PR:单元测试、Lint、Debug 构建 │ └── android-ci.yml # 手动正式发布:测试、Lint、签名构建、Release ├── app/ │ ├── build.gradle.kts # SDK、版本、签名、依赖和资源收缩 │ ├── proguard-rules.pro # Release 混淆配置 │ └── src/ │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── assets/scrcpy/ # 官方 scrcpy server │ │ ├── java/com/sky22333/skyadb/ │ │ │ ├── adb/ # Kadb 身份、连接、命令、传输和 Fastboot │ │ │ ├── apps/ # 目标设备应用名称、图标与分类信息 │ │ │ ├── data/ # DataStore 设置和最近 WiFi 设备 │ │ │ ├── diagnostics/ # 有界进程内错误日志 │ │ │ ├── discovery/ # kadb-mdns 适配、网段扫描和协议探测 │ │ │ ├── download/ # OkHttp 下载与取消 │ │ │ ├── files/ # 本机文件、缓存和 SAF 复制 │ │ │ ├── i18n/ # 应用语言与资源访问 │ │ │ ├── localapps/ # 本机应用读取、图标和 APK 导出 │ │ │ ├── model/ # 数据、结果与操作状态模型 │ │ │ ├── repository/ # ADB 仓库接口与连接状态整合 │ │ │ ├── scrcpy/ # 会话、协议、异步音视频解码和触控 │ │ │ ├── ui/ # Compose 页面、ViewModel、组件与主题 │ │ │ ├── usb/ # OTG 发现、授权和插拔事件 │ │ │ └── validation/ # 网络、URL、路径和文件名校验 │ │ └── res/ # 中英文资源、图标、主题与平台配置 │ ├── test/ # JVM 单元测试 │ └── androidTest/ # USB、镜像、解码和键盘真机测试 ├── docs/README.md # 当前实现与开发维护规范 ├── docs/img/ # README 使用的预览图片 ├── gradle/libs.versions.toml # 依赖版本 ├── gradle/wrapper/ # 固定版本与 SHA-256 的 Gradle Wrapper ├── build.gradle.kts ├── settings.gradle.kts └── README.md # 产品介绍和使用方式 ``` ## 架构说明 当前架构采用单 Android App 模块,保持实现直接、边界清晰。 - UI 层:Compose 页面只负责展示状态和派发用户事件。 - ViewModel 层:持有页面状态,调用仓库、下载、文件、扫描等服务。 - Repository 层:面向 UI 提供稳定的 ADB 操作接口,隐藏 Kadb 细节。 - KadbManager:集中封装真实 ADB 能力,避免页面层直接拼接和调用底层 API。 - DataStore:保存设置和最近设备,所有读取以 Flow 形式向上游暴露。 - Discovery:自动发现和扫描逻辑独立于 UI。mDNS 由 `kadb-mdns` 管理 Android NSD 发现、解析和关闭,发现页离开时停止;配对查找连接端口使用独立短时会话。TCP 扫描支持并发限制、超时、取消和进度节流。 - Download:下载逻辑独立于页面,取消时关闭 OkHttp Call;文件名经过校验,下载落入独立缓存子目录,进度更新节流。 - Diagnostics:错误日志仅保存在进程内,最多 500 条;Debug 构建同时将失败原因写入 logcat,不做永久存储。 - Scrcpy:屏幕镜像逻辑独立于页面,复用当前 WiFi / USB Kadb 连接的独立 ADB 流、官方 server、MediaCodec 硬解码和控制协议封装。 - Validation:输入校验集中维护,避免每个页面重复实现 IP、端口、URL、路径判断。 ## 连接、传输与镜像实现 - USB ADB 由 `KadbUsb.isAdbDevice()` 识别、`KadbUsb.create()` 建立连接。每个设备持有一个 Kadb 实例,视频、音频、控制和其他操作使用该连接上的独立流。 - 连接、断开、设备信息刷新和最近设备状态合并由仓库串行管理;授权等待受超时与取消控制,失败或取消会关闭待连接实例。 - ADB 身份由 `AdbIdentityManager` 配置持久化存储,密钥在 IO 操作时按需加载。 - 远端目录使用 `openSync().list()`,由 Kadb 协商 Sync v1/v2。文件下载写入目标同目录临时文件,成功后原子替换;失败保留已有文件。 - Fastboot 连接、命令、摘要读取和释放在 IO 线程串行执行。`fastboot-java` 复用命令构造能力;其传输接口不返回实际读写长度,应用通过 `FastbootUsbChannel` 校验 USB 接口声明、bulk 端点和完整写入,使用 `FastbootProtocol` 接收响应。 - Fastboot 按实际包长读取最多 256 字节的响应,持续接收 `INFO` / `TEXT`,直到 `OKAY` / `FAIL`,不重发命令。普通命令总超时 10 秒,连接探测和单个摘要查询总超时 3 秒;接收按最多 250 ms 的等待片段检查取消。协议异常、超时、取消或未支持的 `DATA` 阶段关闭连接并清理会话;正常 `FAIL` 保留连接和错误输出。 - Fastboot 输出缓存上限为 64 KiB,超出时标记截断并继续排空响应,保留终态。UI 在命令结束后一次更新输出,显示区域限制高度并支持双向滚动;命令结果和设备摘要均可复制。 - 进入 Fastboot 命令页时读取产品型号、序列号、Bootloader 版本、当前槽位和 `is-userspace`,并支持手动刷新;不轮询或持久化摘要。不支持的变量显示“设备未提供”,不根据 `secure` 猜测解锁状态。 - Fastboot 快捷按钮支持重启到系统、Bootloader、Recovery 和 fastbootd,实际可用性取决于设备。仅收到成功终态后显示指令已确认并清理当前连接;设备重新枚举后由用户在首页连接,不自动重放指令。 - 单 Activity 应用入口使用 `singleTask`,USB 重新接入通过 `onNewIntent` 刷新设备列表,保留当前命令页和导航状态,避免模式切换堆叠 Activity。 - 命令输入由 `CommandInputParser` 统一解析,只去除开头完整的客户端名称(支持 `.exe`),ADB Shell 正文的参数、引号和操作符保留。前缀与当前连接模式不一致时拒绝执行,不自动切换设备。 - Fastboot 命令页使用对应标题和示例。`fastboot getvar product`、`fastboot erase cache`、`fastboot set_active b` 分别通过库构造为 `getvar:product`、`erase:cache`、`set_active:b`;支持 `fastboot reboot` 及带重启目标的写法,原始协议和 OEM 命令可直接输入。 - `devices` 属于主机枚举操作,提示用户到首页查看设备;桌面选设备参数、交互式 Shell 参数和未实现的客户端文件传输流程在发送前提示。命令页不提供完整桌面 adb / fastboot 客户端兼容层,不支持镜像上传和刷写。 - `ScrcpySession` 管理官方 server 及视频、音频、控制流;镜像退出只关闭自己的流,不关闭共享的 Kadb 连接。 - `MediaCodecPump` 在独立 HandlerThread 上串行管理解码器,输出不依赖下一次网络输入。输入采用反压,支持设备声明的低延迟解码;音频按实际输出格式创建 AudioTrack,解码 PCM 直接通过 ByteBuffer 写入。 - Surface 重建时保留 scrcpy 会话,重建视频解码器并发送 `RESET_VIDEO`,等待关键帧恢复画面;旧 Surface 的迟到回调与新解码器隔离。 - 镜像启停串行化,延迟清理不关闭后续启动的新会话。触摸 MOVE 按指针合并,保留按下、抬起和其他控制指令的顺序。 - scrcpy 资产为 `app/src/main/assets/scrcpy/scrcpy-server-v5.0.1`,SHA-256 为 `764eb6f79811d5211fe9df341120882ba9994c7a61b897d7bf3fb662e53bc536`;更换资产时同步更新 `ScrcpyConstants` 并核验协议。 ## UI 与交互规范 - App 内可见文案通过资源提供简体中文和英文,品牌名统一写作 `sky adb`。 - 使用 Material 3 作为基础,但要保持现代、扁平、克制、工具型产品风格。 - 页面不能有粗糙默认感,按钮、卡片、输入框、状态徽章、列表间距必须统一。 - 首页、设置页、设备页、Shell 页等长内容页面使用 `LazyColumn`,避免滚动不跟手。 - 页面切换使用淡入淡出,底部导航与工具卡片使用共享过渡;动画参数统一由 `SharedMotion` 管理。 - 列表项要尽量轻量,避免在列表滚动时做阻塞 IO、ADB 调用或大图加载。 - 耗时操作必须展示状态,失败必须给出中文原因和下一步建议。 - 危险操作,例如卸载应用,应保留确认流程。 - 设置页面需要紧凑、对齐、统一,不使用明显大于其他页面的输入控件。 - 屏幕镜像页以画面为主,不显示常驻设备信息;顶部提供关闭镜像、控制区开关和输入键盘开关,底部控制区可隐藏。 - 屏幕镜像画质配置放在设置页,不放在镜像页,避免遮挡画面。 ## 性能要求 - 所有 ADB、下载、文件、扫描、本机应用读取等阻塞任务必须放到 `Dispatchers.IO` 执行;仅使用 ViewModel 协程不代表已离开主线程。 - 下载进度和扫描进度必须节流,避免高频状态更新造成 Compose 频繁重组。 - 局域网扫描默认并发为 48,上限为 64,默认超时为 600 ms。 - mDNS 自动发现只在用户进入局域网发现页时启动,离开发现页必须停止,不做后台常驻监听。 - 默认扫描 `/24` 网段,最多手动配置 6 个网段,避免过大范围导致耗电、卡顿和误扫。 - 扫描只在用户主动触发时执行,不做后台常驻扫描。 - 下载文件和导出的 APK 放在缓存目录,导出前清理旧 APK,避免缓存无限膨胀。 - 大列表必须优先使用 `LazyColumn`,列表项保持稳定 key。 - ViewModel 中的 Flow 收集和协程任务要跟随 ViewModel 生命周期释放,避免 Activity 泄漏。 - 不在 Compose 页面中直接持有 `Context` 长生命周期引用;需要上下文的服务使用 `applicationContext`。 - 状态模型要小而稳定,避免把大文件内容、图片 Bitmap 或长输出反复塞入全局状态。 - 屏幕镜像默认使用均衡画质,用户可切换流畅、均衡、高清三档;高清模式不作为默认值。 - 屏幕镜像使用 `SurfaceView` 按远端视频比例居中显示,触摸坐标必须与实际画面区域一致。 - 屏幕镜像的触摸、按键、文本发送和 socket 释放必须在 IO 线程执行,不能阻塞主线程。 - 屏幕镜像不因短暂切后台或 Surface 重建而拆除会话;回前台通过重建解码器并发送 `RESET_VIDEO` 恢复画面。用户关闭页面、离开镜像页或视频流异常时释放会话。 ## 开发规范 - 开发前先阅读当前源码、已有 docs、相关依赖实际 API 和官方文档。 - 不凭经验猜测 Kadb、Compose、DataStore、OkHttp、Android 平台 API 行为。 - 每次改动保持小范围、可解释、可验证,不做无关重构。 - 所有新增页面和功能必须有加载、空状态、错误态、执行中、成功态的处理。 - 业务逻辑优先放在 ViewModel、Repository、Manager 或 Validator 中,不塞进 Composable。 - 不重复造同类输入校验、状态展示、结果封装。 - 新增 ADB 命令时必须封装在 KadbManager 或 Repository 层,页面只调用语义化方法。 - 新增设置项必须进入 `AppSettingsStore`,并在设置页保持布局紧凑统一。 - 新增持久化数据要考虑字段升级、默认值和读取失败兜底。 - 新增网络能力必须考虑超时、取消、错误提示、缓存清理和进度节流。 - 新增 UI 要遵循现有 `AppDimens`、主题颜色、圆角和 Material Icons 风格。 - 新增镜像参数必须通过 `MirrorQualityPreset` 或 `ScrcpyOptions` 集中管理,不能在 UI 或启动命令中散落硬编码。 ## 验收标准 - 功能必须生产可用,不以实验、演示或临时代码为交付目标。 - 实现必须直击需求根因,优先复用现有项目结构和已有组件,不堆砌兜底逻辑。 - 代码量保持必要且最少,不新增重复抽象、重复状态、重复入口或重复校验。 - 引入新实现时必须同步删除被替代的旧实现、旧文案、旧状态和无用代码,不保留死代码。 - 业务逻辑必须闭环:有入口、有执行中状态、有成功反馈、有失败原因、有释放资源或取消路径。 - 失败信息必须尽量反映真实原因,并进入诊断日志;不能只给泛化错误。 - 所有耗时、网络、ADB、文件、解码、扫描和 socket 操作不得阻塞主线程。 - 资源必须按生命周期释放,避免后台常驻、协程泄漏、流未关闭、缓存无限增长和重复扫描。 - 默认行为必须兼顾省电、低占用和兼容性;高性能或高画质能力必须由用户主动选择。 - UI 必须与现有风格一致,布局紧凑、对齐、少遮挡,不增加无必要的弹窗、按钮和层级。 - 交互必须形成闭环:用户知道当前状态、能取消或返回、失败后知道下一步。 - 新增设置项必须保存默认值、异常值回退和读取失败兜底,并保持设置页整齐统一。 - 新增功能必须覆盖关键路径测试;测试要少而准确,优先覆盖解析、映射、参数、错误回退等纯逻辑。 - 不使用已知即将弃用或已弃用的 API;遇到平台、依赖或第三方协议不确定时必须查阅最新官方文档或当前源码。 - 不提交临时计划文档、缓存文件、构建产物、签名证书、APK、AAB 或仅用于本地分析的第三方源码。 - 改动完成后至少执行静态检查,确认 `git diff --check` 通过;本地无法编译时必须说明,并由 CI 验证构建、测试和 lint。 ## 维护规范 - 每次改动保持小范围、可审查、可验证,不新增临时计划文档。 - 文档只描述当前实现和维护要求,不保留日期式迭代记录、历史修复清单或单次测试成绩。依赖、CI、协议和功能行为变化时直接更新对应章节。 - 用户明确暂停的功能不要在计划里写成待立即开发项。 - GitHub Actions 构建失败时,先根据日志定位具体任务,再修复 workflow 或源码。 - Release 构建需要仓库 Secrets:`SIGNING_KEY_BASE64`、`KEY_ALIAS`、`KEY_STORE_PASSWORD`、`KEY_PASSWORD`。 - 签名证书必须使用 PKCS#12 格式,不允许提交到仓库。 - 提交前执行静态检查,至少确认 `git diff --check` 通过。 - 本地支持构建、单元测试和 Lint;PR / push 自动执行检查,正式发布使用手动工作流。 ## 编码与换行规范 - 文本文件默认 UTF-8。 - 默认 LF 换行。 - Markdown、YAML、JSON、XML 使用 2 空格缩进。 - Kotlin 使用 4 空格缩进。 - Windows 脚本文件允许 CRLF。 - 二进制文件、图片、APK、签名证书按 `.gitattributes` 标记处理。 - 签名证书、构建产物、APK、AAB 不提交到仓库。 ## 构建与验证 - 使用项目 Gradle Wrapper,安装 Android SDK Platform 37 和 Build Tools 37.0.0;CI 使用 JDK 17,本地可使用 JDK 21。 - `local.properties` 配置本机 `sdk.dir`,或通过 `ANDROID_HOME` 指向 Android SDK。 - Windows 执行以下命令;Linux / macOS 改用 `./gradlew` 调用相同任务。 ```powershell .\gradlew.bat testDebugUnitTest lintRelease assembleDebug assembleRelease .\gradlew.bat connectedDebugAndroidTest git diff --check ``` 单元测试覆盖输入校验、错误处理、协议编码、状态模型,以及 Fastboot 多包响应、总超时、取消、输出上限和异常关闭。真机测试覆盖单帧解码输出、镜像键盘开关、USB ADB 并发与文件往返、镜像 Surface 重建,以及 Fastboot 摘要、多行响应、失败后的查询和界面复制。USB 测试要求本机作为 OTG 主机连接对应模式下已授权的目标;缺少目标时跳过对应测试。 `FastbootUiTest` 默认只查询和复制结果。显式传入 instrumentation 参数 `fastbootReboot=bootloader` 或 `fastbootReboot=system` 时额外验证对应重启按钮及会话清理,测试结束后目标设备停留在所选模式。额外传入 `fastbootPrepare=true` 可从已授权的 USB ADB 目标重启到 Bootloader,再执行本轮测试;未显式指定时不会切换目标模式。 Debug 使用本地调试签名;未配置发布签名时,本地 Release APK 为未签名产物。Release 使用 R8 混淆和资源收缩。 ## 发布规范 - 当前本地默认版本号:`1.0.0`,`versionCode` 为 `10000`。 - 正式发布由 GitHub Actions 手动触发。 - 正式发布输入 `v主版本.次版本.修订版本`,CI 会写入 APK 的 `versionName` 和正式版 `versionCode`。 - Release notes 根据上一个 `v*` tag 到当前提交之间的 commit message 自动生成。 - Release APK 由 CI 使用 PKCS#12 证书签名后发布到 GitHub Releases。 ## 当前风险与注意事项 - 依赖统一由 `AppServices` 提供,服务使用应用上下文。 - mDNS 自动发现依赖局域网 multicast / DNS-SD 支持,部分路由器、访客网络、热点隔离、跨网段场景可能无法发现服务;此时用户可继续使用网段扫描或在设置中手动配置网段。 - 局域网扫描依赖网络拓扑,手机热点、旁路由、访客网络、跨网段场景需要用户在设置中手动配置网段。 - 本机应用安装到目标设备当前只支持用户应用的单 APK 导出;Split APK / App Bundle 不在当前范围。 - Shell 是单条命令执行,不是交互式终端。 - 设备断线后的主动心跳和自动重连当前未作为常驻功能实现,避免增加耗电和后台复杂度。