# StandAPP 智能调度终端 - 开发指南 (AGENTS.md) 本文档为 StandAPP 项目的开发规范与技术参考,旨在帮助开发者快速理解项目架构、构建流程及核心业务逻辑。 ## 1. 项目概况 StandAPP 是一款基于 Kotlin 和 Jetpack Compose 开发的 Android 应用。集成了 `AgentWeb`(网页交互)、打印服务、自动更新以及核心的 **PTT (Push-to-Talk) 对讲模块**。 - **主包名:** `com.stand.standapp` - **PTT 包名:** `com.example.kingway.ptt` (严禁修改,与 Native 层硬绑定) - **技术栈:** Kotlin, Jetpack Compose, Gradle (Kotlin DSL), OkHttp, AgentWeb, NDK (C++). - **SDK 版本:** Compile SDK 36, Target SDK 34, Min SDK 24. ## 2. 构建、检查与测试 ### 构建命令 - **编译 Debug APK:** `./gradlew assembleDebug` - **清理项目:** `./gradlew clean` - **编译 Release APK:** `./gradlew assembleRelease` ### 检查与测试 - **运行 Lint 检查:** `./gradlew lint` - **运行单元测试:** `./gradlew test` - **运行单项测试:** `./gradlew :app:testDebugUnitTest --tests "包名.类名"` ## 3. 代码风格与规范 - **缩进:** 4 个空格。 - **命名:** 类名使用 `PascalCase`;函数和变量使用 `camelCase`;常量使用 `SCREAMING_SNAKE_CASE`。 - **Compose:** 优先使用 Material 3 组件;Composable 函数首字母大写;Modifier 必须作为第一个可选参数。 - **错误处理:** 必须使用 `try-catch` 包裹 IO、网络、JSON 解析等易错操作,并使用 `Log.e` 记录异常。 ## 4. PTT (对讲) 核心业务逻辑解析 PTT 模块是本项目的通讯核心,依赖底层 `libptt.so` 原生引擎。其业务流程高度依赖 **十六进制 AT 指令** 交互。 ### 4.1 核心组件与关键方法 #### **A. 指令发送:`SendAtUtil` (指令工厂)** 封装了所有发往 Native 引擎的控制指令。 - `toLogin(account, pwd, ip, location, tempCall)`: **登录接口**。将账号、密码、服务器 IP、GPS 开启标志及单呼标志拼接为 `010000` 开头的十六进制指令。 - `speakPlay()`: **开始对讲**。发送 `0B0000` 指令,触发底层 POC 引擎进入发送模式并准备处理语音数据。 - `speakRelease()`: **停止对讲**。发送 `0C0000` 指令通知引擎结束通话,并同步停止本地录音线程。 - `sendTCP()` / `sendUDP()`: **心跳维持**。登录成功后,必须每 **40秒** 调用一次。`570000` 为 TCP 心跳,`580000` 为 UDP 心跳。 - `getGroupInfo()`: **查询群组**。发送 `0D0000` 指令。 - `getGroupMemberInfo(groupId)`: **查询成员**。发送 `0E0000` + 群组 ID。 - `jumpGroup(groupId)`: **切换群组**。发送 `090000` + 群组 ID,用于即时切换监听的群组。 #### **B. 指令解析:`CallBackResolution` (响应处理器)** 解析 Native 引擎通过 JNI 异步返回的十六进制数据。 - `at_OEM_AT_cb(lisHex)`: **解析入口**。识别首字节指令码: - `82`: 登录/离线状态变更。 - `80`: 接收群组详细信息(ID、名称、成员数)。 - `81`: 接收群成员在线状态及视频能力。 - `83`: 语音发起者信息(当前谁在说话)。 - `8b`: 播音状态变更(引擎开始或停止播放对方声音)。 - `8d`: 经纬度数据通知。 - `at_Play_TTS_cb(sData)`: **TTS 状态解析**。解析中文状态描述。当识别到“已登录”时,需触发心跳定时器。 - `isLoginConflict(state)`: **冲突检测**。逻辑:1 分钟内若状态在“离线”和“登录中”切换超过 5 次,则判断为登录冲突。 #### **C. 录音管理:`AudioRecordManager` (音频采集)** - `startRecord()`: 启动录音循环。设置优先级为 `THREAD_PRIORITY_URGENT_AUDIO`。 - `stopRecord()`: 释放 `AudioRecord` 资源。 - **技术参数**: 采样率 8000Hz, 16bit, 单声道。每读取 320 字节 PCM 原始数据即调用 `pttNativeSendRecordCmd` 推送至 Native 层。 #### **D. JNI 桥接:`pttNative` (底层交互)** - `OEM_Play_cb(byte[] bytes)`: **播放回调**。底层接收到的音频流会实时回调此方法,数据需直接写入 `AudioTrack` 实例进行播放。 - `pttNativePocTaskStart()`: **引擎初始化**。 ### 4.2 业务技术流程 1. **初始化**: 调用 `MyApplication.init(context)` -> 加载 SO 库 -> 启动 Native 任务。 2. **认证**: 调用 `toLogin` -> 异步等待 `82` 回调或 TTS “已登录”提示。 3. **在线维持**: 登录成功后启动周期为 40s 的任务发送 TCP/UDP 心跳。 4. **对讲过程**: - **按下 PTT**: `speakPlay` -> 收到成功反馈 -> `AudioRecordManager` 持续采音并推送。 - **松开 PTT**: `speakRelease` -> 停止录音 -> 发送结束指令。 5. **UI 更新**: 引擎回调均在 **子线程**。所有 UI 操作(Toast、Dialog、TextView 更新)必须切回主线程。 ## 5. 开发约束与安全 1. **包名与类名**: `com.example.kingway.ptt.pttNative` 严禁改名或移动,否则会导致 JNI 方法找不到实现导致崩溃。 2. **权限管理**: 必须先通过 `XXPermissions` 获取 `RECORD_AUDIO` 权限后再执行对讲。 3. **线程规范**: 回调处理严禁阻塞。耗时操作必须异步执行。 --- *本文档由 AI 助手维护,旨在确保业务逻辑的一致性。*