# KIOSK 自助照片打印 KIOSK 是一套运行在 Android 终端上的自助照片打印应用,面向线下自助设备场景。应用负责设备绑定、照片获取与裁剪、打印任务处理、打印机状态上报、海报展示以及在线升级等功能。 当前应用名称为“自助照片打印”,包名为 `com.yzx.kiosk`。 ## 主要功能 - 上传、选择、裁剪并打印照片 - 扫码取片及隐私打印任务处理 - 人脸识别与照片检索 - DNP RX1、QW410 照片打印机接入 - WebSocket 长连接、任务接收和设备心跳 - 打印机状态、纸张余量和打印记录管理 - 海报、视频及直播内容展示 - APK 在线检查、下载和安装更新 - 开机启动及应用更新后自动恢复 ## 技术栈 - Kotlin 2.1.10 - Jetpack Compose + ViewBinding - Android Gradle Plugin 8.10.0 - Gradle 8.11.1 - Hilt、KSP、Room、Retrofit、OkHttp、MMKV - CameraX、ML Kit、ZXing - 阿里云 OSS、语音合成、高德地图 - DNP 本地打印 SDK ## 环境要求 | 项目 | 要求 | | --- | --- | | Android Studio | 支持 AGP 8.10.0 的较新稳定版本 | | JDK | JDK 17,推荐直接使用 Android Studio 内置 JBR | | Android SDK | Compile SDK 36 / Target SDK 36 | | 最低系统版本 | Android 8.0(API 26) | | 调试设备 | 开启开发者选项和 USB 调试的 Android 真机 | | 打印设备 | DNP RX1 或 QW410,打印功能需要对应设备及驱动环境 | 项目依赖 Google、Maven Central、华为、JitPack 和阿里云 Maven 仓库,首次同步需要能够访问这些仓库。 ## 获取工程 ```bash git clone ssh://git@gitea.zhifly.cn:2222/lujiuyin/kiosk.git cd kiosk git checkout main ``` 仓库使用 SSH 端口 `2222`。拉取前请确认本机 SSH 公钥已添加到 Gitea 账号。 ## 本地依赖 打印、地图和语音能力依赖 `app/libs/` 中的本地 AAR、JAR 及原生库。至少应确认下列文件存在: ```text app/libs/ ├── dnpext.aar ├── dnpphotocolorcnv-1.2.aar ├── dnpphotoprintlib-1.2.aar ├── AMap3DMap_10.1.600_AMapSearch_9.7.4_AMapLocation_6.5.1_20251020.jar ├── nuisdk-release.aar ├── fastjson-1.1.46.android.jar ├── arm64-v8a/ └── armeabi-v7a/ ``` 缺少这些文件时,Gradle 同步可能失败,或者应用能够安装但对应硬件能力无法工作。 ## 在 Android Studio 中运行 1. 使用 Android Studio 打开工程根目录。 2. 将 Gradle JDK 设置为 Android Studio 内置 JBR(JDK 17)。 3. 等待 Gradle Sync 完成;Android Studio 会自动生成包含 SDK 路径的 `local.properties`。 4. 使用数据线连接真机,并在设备上允许 USB 调试。 5. 在设备选择器中选择目标真机,运行 `app` 的 `debug` 构建。 6. 首次启动时按系统提示授予相机、照片、定位和安装未知应用等业务所需权限。 可以用下面的命令确认设备已连接: ```bash adb devices ``` 设备状态应为 `device`。如果显示 `unauthorized`,请解锁设备并确认 USB 调试授权弹窗。 ## 命令行构建与安装 仓库当前的 `gradlew` 使用 CRLF 换行且没有执行权限。在 macOS 或 Linux 首次使用时,先执行: ```bash perl -pi -e 's/\r$//' gradlew chmod +x gradlew ``` 构建 Debug APK: ```bash ./gradlew :app:assembleDebug ``` 安装到已连接的真机: ```bash ./gradlew :app:installDebug ``` 启动应用: ```bash adb shell am start -n com.yzx.kiosk/.SplashActivity ``` APK 输出目录为: ```text app/build/outputs/apk/debug/ app/build/outputs/apk/release/ ``` APK 文件名会自动包含应用名、版本号、版本代码、构建类型和构建时间,例如: ```text 照片打印机_1.1.1_21_debug_yyyyMMdd_HHmm.apk ``` ## 构建环境 | 构建类型 | 后端环境 | 调试 | 代码压缩 | | --- | --- | --- | --- | | `debug` | 测试环境 `api-test.zhifly.cn` | 开启 | 关闭 | | `release` | 正式环境 `api.zhifly.cn` | 关闭 | 关闭 | 请勿使用 Release 包连接测试设备随意操作,Release 会访问正式接口并连接正式 WebSocket。 ### Release 签名警告 当前工程存在发布阻断问题: - Debug 和 Release 的 keystore 路径及口令直接写在 `app/build.gradle.kts` 中。 - `release` 构建当前实际选择的是 Debug 签名,而不是已声明的 Release 签名。 - keystore 已存在于工程目录中,泄露后可能被用于签署可覆盖安装的 APK。 在正式发布前,必须将签名信息迁移到本机安全配置或 CI Secret,修正 Release 签名配置,并根据已发布版本情况评估密钥轮换。不要在 README、提交记录或聊天中传播 keystore 口令。 ## 真机和打印机检查 运行完整业务前建议依次确认: 1. 真机系统版本不低于 Android 8.0。 2. 网络能够访问对应的测试或正式接口。 3. 设备已完成业务侧的终端绑定和 Token 配置。 4. DNP 打印机已上电、装纸并与终端正确连接。 5. 应用内打印机管理页能够识别设备,状态不是离线。 6. 使用测试照片完成一次打印,并核对打印结果、纸张余量和服务端任务状态。 RX1 使用约 `1840 × 1240` 的横向打印画布,QW410 使用约 `1266 × 1836` 的纵向打印画布。应用会根据识别到的打印机型号处理图片方向和缩放。 ## 常用质量检查 ```bash # 编译 Debug ./gradlew :app:assembleDebug # JVM 单元测试 ./gradlew :app:testDebugUnitTest # Android Lint ./gradlew :app:lintDebug # 需要已连接真机或模拟器 ./gradlew :app:connectedDebugAndroidTest ``` 目前工程自动化测试覆盖较少,Lint 也仍有待处理的问题。发布前不要只以“能够编译安装”作为质量判断依据。 ## 目录结构 ```text KIOSK/ ├── app/ │ ├── libs/ # 打印、地图、语音及原生依赖 │ ├── src/main/java/com/yzx/kiosk/ │ │ ├── datastore/ # 本地状态与配置 │ │ ├── navigation/ # Compose 页面导航 │ │ ├── network/ # 接口、数据库和数据仓库 │ │ ├── priter/ # 打印机接入(历史目录名) │ │ ├── ui/ # 页面和 ViewModel │ │ ├── utils/ # 上传、下载、更新等工具 │ │ └── websocket/ # 长连接及打印任务 │ └── build.gradle.kts # Android、构建类型和签名配置 ├── docs/ │ └── 工程代码审查报告.md ├── gradle/libs.versions.toml # 依赖版本目录 └── settings.gradle.kts ``` `priter` 是工程中现有的历史目录名,并非 README 拼写错误;重命名时需要同步修改包名和引用。 ## 已知问题与发布前检查 详细问题和修复建议见 [工程代码审查报告](docs/工程代码审查报告.md)。当前需要优先处理: - Release 签名与密钥管理 - 打印最终结果的可靠判定 - 隐私政策同意流程和敏感数据保护 - WebSocket、上传下载与状态通知的并发可靠性 - APK 更新文件的完整性及签名校验 - Room 数据迁移、自动化测试和 Lint ## 版本信息 - Version Name:`1.1.1` - Version Code:`21` - Application ID:`com.yzx.kiosk` - Root Project:`KIOSK` 版本号以 `app/build.gradle.kts` 中的配置为准。