用 DeepSeek Harness 从零创建「墨页 PDF」安卓应用
用 DeepSeek Harness 从零创建「墨页 PDF」安卓应用
本文档完整记录:如何仅靠 DeepSeek Harness(对话式 AI 代理 + 本机工具链)
从零开发、构建、测试、修复一款可安装的 Android 应用(图片转 PDF 工具)。
全程真实经历,含所有踩坑与解决过程。
0. 最终成果



| 交付物 | 路径 | 说明 |
|---|---|---|
| APK 安装包 | InkPDF\download\app-debug.apk | 18MB,中文版,Android 8.0+ 可装 |
| 完整工程源码 | InkPDF\ | Kotlin + Jetpack Compose,33 个 Kotlin 文件 |
| 源码+APK 打包 | InkPDF-source.zip | 拷到联网电脑即可继续构建 |
| 交互原型 | InkPDF\demo\app-prototype.html | 浏览器可点的界面原型 |
| 深色设计稿 | design\mockups\*.png | GDI+ 程序化渲染 |
| 构建/分发脚本 | build.bat / serve.bat / download\index.html | 一键构建 + 手机局域网直装 |
功能:图片转 PDF、PDF 合并/拆分/转图、图片压缩、文字水印、最近记录、后台生成、深色纸墨风 UI。
原则:纯离线、零权限(仅一个可选通知权限)、全部基于 Android 系统原生 API。
1. Harness 是什么、怎么工作
DeepSeek Harness 是一个对话式开发环境:AI 代理在真实电脑上执行操作,工具集包括:
- 文件工具:
write(创建/覆盖)、edit(精准替换)、read(带行号阅读)、glob/grep(搜索) - 命令工具:
pwsh(执行 PowerShell,支持前台/后台 job、超时、工作目录) - 后台任务:长任务(构建、下载)放后台跑,完成自动通知,不阻塞对话
- 目标工具:
create_goal建立长周期目标,跨多轮自动推进 - 搜索工具:
web_search(联网信息) - 外部组件:OpenPencil(设计画布)、subagent/workflow(多代理)
核心工作流:用户用自然语言提需求 → 代理把需求拆解成可执行步骤 → 用工具真实执行(写代码、跑命令、查错误)→ 把执行结果反馈给用户 → 迭代。
2. 第一步:需求与方案
用户直接给出了一份完整的方案文档(技术选型、架构图、功能表、UI 草图、避坑提示)。这是最好的起点——需求越明确,产出越准。关键决策点:
- 永久可用:图片转 PDF 用
android.graphics.pdf.PdfDocument,PDF 读取用PdfRenderer——纯系统 API,零第三方 PDF 库。 - 零权限:文件访问走 SAF / PhotoPicker / MediaStore,不需要存储权限。
- 深色优雅:Material 3 + 自定义"深夜纸墨"配色(背景
#0B0E13、主色暖金#E8B469)。
经验:先让用户/自己把方案写清楚(哪怕只是要点),再动手——本应用 90% 的功能点都来自那份方案文档。
3. 环境侦察(动手前先摸清工具链)
开发前必须先探明本机环境,否则会白干。用 pwsh 一次性检查:
java -version; echo $env:JAVA_HOME; gradle --version # Java/Gradle
echo $env:ANDROID_HOME; Test-Path "$env:LOCALAPPDATA\Android\Sdk" # Android SDK
Invoke-WebRequest https://dl.google.com -TimeoutSec 8 # 网络
本机真实情况:
- ✅ JDK 17(
D:\develop\Java\jdk-17.0.1) - ❌ 无 Android SDK、无 Gradle 命令、无网络(Google/阿里云镜像全断)
- ✅ 有 Gradle 8.8 发行版缓存、JDK、Python 3.10
结论:无法直接构建 APK → 策略调整为"先产出完整可构建的源码 + 视觉稿",等用户安装 Android Studio 后再真构建。环境侦察决定了整个开发策略,这一步不能省。
4. 工程搭建(离线也能干)
没有网络也能搭好工程骨架:
- Gradle Wrapper:本机无法运行
gradle wrapper(守护进程锁、权限问题),改为从磁盘上已有的其他 Gradle 项目复制gradle-wrapper.jar+gradlew+gradlew.bat(找到的正好是 Gradle 8.8 时代的 wrapper),自己写gradle-wrapper.properties。 - 版本目录
gradle/libs.versions.toml:AGP 8.5.2 / Kotlin 2.0.20 / Compose BOM 2024.09.03 / Room 2.6.1 / Work 2.9.1,统一管理。 - 构建脚本:
settings.gradle.kts(预留阿里云镜像注释)、根/模块build.gradle.kts、gradle.properties(开 AndroidX)。
// libs.versions.toml 片段
[versions]
agp = "8.5.2"
kotlin = "2.0.20"
composeBom = "2024.09.03"
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
5. 分层实现(架构即代码)
按方案文档的 MVVM 分层,一个文件一个文件写:
com.inkpdf.app/
├── ui/ # Compose 界面:首页/编辑/预览/设置 + 深色主题
├── data/ # Room(最近记录) + DataStore(设置) + 领域模型/状态机
├── engine/ # PdfEngine / ImageProcessor / BitmapUtils(纯逻辑)
├── repository/ # PdfRepository / FileRepository(SAF+MediaStore) / ShareUtils
├── work/ # WorkManager 后台导出
├── notification/ # 通知渠道与进度
关键设计(都对应方案文档):
- 防 OOM:解码采样(长边 2400px)+ 逐页
recycle() - EXIF 方向:API 28+ 用
ImageDecoder,26-27 用BitmapFactory+ExifInterface - 灰度/黑白:
ColorMatrix饱和度 0 + 阈值矩阵 - 质量参数真实生效:先按 JPEG 重编码再嵌入
- 后台导出:
CoroutineWorker+ 系统通知
设计系统:ui/theme/ 里定义配色 token、字重、圆角——"深色纸墨风"贯穿所有界面。
6. 视觉稿与交互原型(OpenPencil 不可用时的替代)
原计划用 OpenPencil 渲染界面设计稿,但宿主不可用。改用两条替代路径:
- GDI+ 程序化渲染:写一个 PowerShell 脚本(
design/render_mockups.ps1),用System.Drawing按坐标画出 5 个屏幕(390×844 @2x)+ 应用图标 + 总览板。踩坑:函数名H撞了 PowerShell 内置别名Get-History(大小写不敏感!),且.ps1需 UTF-8 BOM 才能读中文。全部修复后渲染成功。 - HTML 交互原型:
demo/app-prototype.html——纯 CSS/JS 还原深色界面,手机壳里可点:选图→编辑→拖拽排序→进度动画→预览翻页→工具。用户双击浏览器即可"体验"应用。
经验:外部组件不可用时,用语言自带的绘图/HTML 能力做等价交付,保证用户"看得见"。
7. 真实构建与排错(最有价值的部分)
用户安装 Android Studio 后开始真构建。每一轮编译都暴露了真实问题——这正是"能跑命令"比"只写代码"强的地方:
| # | 错误 | 根因 | 修复 |
|---|---|---|---|
| 1 | Directory 'E:\deepseek_1' does not contain a Gradle build | gradlew 在错误工作目录执行 | pwsh 指定 workdir |
| 2 | SDK location not found | local.properties 被 PowerShell 写入 UTF-8 BOM,Java properties 解析失败 | 无 BOM 重写 + ANDROID_HOME 双保险 |
| 3 | Failed to find Platform SDK platforms;android-37 | 新 SDK 只有 android-37.0 平台,AGP 8.5 需要 android-34;SDK XML 版本 4 与 AGP 8.5 不兼容 | 复制 37 目录伪装成 34(后改用官方包) |
| 4 | jlink.exe does not exist | IntelliJ 精简 JBR 缺 jlink | 换完整 JDK 17 |
| 5 | 编译错误 ×9:it 变量遮蔽、coil RotationTransformation 不存在、Bitmap→ImageBitmap 类型不符、挂起函数位置错误、combinedClickable 缺 OptIn、PageSettings 缺字段 | 手写代码的真实 bug | 逐一定位修复 |
| 6 | 真机启动闪退 | 导航路由注册错误:composable(route="preview") 但声明了必填参数 uri,导航库启动即抛 IllegalArgumentException | route 改为 "preview?uri={uri}&name={name}" |
排错方法论:静态校验(grep 资源引用、括号配平、runCatching 内挂起函数)→ 真构建暴露编译错误 → 模拟器复现运行时错误 → logcat 拿堆栈。每层都能抓到不同类型的 bug。
8. 模拟器验证(本机自测的完整链路)
没有真机时,自己搭模拟器做端到端验证:
- 发现网络其实通:PowerShell/curl 失败是 Windows Schannel 凭证问题(
SEC_E_NO_CREDENTIALS),但 Java 的 TLS 正常(Gradle 能下载依赖证明了这点)。用 Java 写了个 10 行下载器tools/D.java下载 SDK 组件。 - 补平台:从
repository2-3.xml找到官方platform-34-ext7_r03.zip,下载并 SHA1 校验,替换伪装的目录。 - 下载系统镜像:
x86_64-34_r04.zip(687MB),解压到system-images/android-34/default/。 - 手工建 AVD:无 cmdline-tools,直接写
config.ini+.ini(ANDROID_AVD_HOME指向可写目录)。 - 启动:WHPX 硬件加速可用,90 秒 boot。
- adb 自动化 UI 测试:
uiautomator dump读界面文本 →input tap模拟点击 → 完整跑通"选图→编辑→生成 PDF→预览"(真实产出了 123KB PDF 文件)。
这次模拟器测试直接抓到了导航闪退——没有它,用户会一直拿到坏包。
9. 交付与分发
download\目录:APK + 深色下载页index.html(自动检测 APK 是否就绪)serve.bat:Python 起局域网 HTTP,手机浏览器输地址即下载安装build.bat/build.sh:联网电脑一键构建(自动检测 JDK/SDK、生成 local.properties)InkPDF-source.zip:源码+APK 打包,随时可转移
10. 中文化与真机问题
- 中文化:应用文案本身全中文;模拟器系统语言切
zh-CN后,系统组件(PhotoPicker"影集/照片"、SAF"保存/下载")也全中文;文件名/目录改为"墨页PDF_时间戳.pdf"。 - 真机闪退排查(进行中):模拟器 Android 14 正常,用户平板 Android 15 闪退。已做:16KB 对齐检查(通过)、在应用里加崩溃日志捕获器(闪退时把完整堆栈写入下载目录,无需 adb 即可取回)、准备无线调试路径。关键教训:不同 Android 版本的行为差异必须用真机日志定位,模拟器验证 ≠ 真机验证。
11. 经验总结(给后来者)
- 先侦察环境:工具链/网络/权限决定策略,一分钟排查省一天返工。
- 需求文档化:让用户先写方案(哪怕要点),开发有依据。
- 分层实现:UI / 数据 / 引擎分离,出错好定位。
- 尽早真构建:编译器/运行时抓到的 bug 比想象中多(本应用约 10 处)。
- 模拟器自动化:uiautomator + adb 可以全自动测 UI 流程,比截图可靠。
- 网络被"伪断"时换路子:schannel 失败但 Java TLS 通——工具选对了,网络就是通的。
- 兜底思维:OpenPencil 不可用→GDI+/HTML;adb 连不上→崩溃日志捕获器;只要目标明确,总有路径。
更多推荐


所有评论(0)