用 DeepSeek Harness 从零创建「墨页 PDF」安卓应用

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


0. 最终成果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

交付物路径说明
APK 安装包InkPDF\download\app-debug.apk18MB,中文版,Android 8.0+ 可装
完整工程源码InkPDF\Kotlin + Jetpack Compose,33 个 Kotlin 文件
源码+APK 打包InkPDF-source.zip拷到联网电脑即可继续构建
交互原型InkPDF\demo\app-prototype.html浏览器可点的界面原型
深色设计稿design\mockups\*.pngGDI+ 程序化渲染
构建/分发脚本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 草图、避坑提示)。这是最好的起点——需求越明确,产出越准。关键决策点:

  1. 永久可用:图片转 PDF 用 android.graphics.pdf.PdfDocument,PDF 读取用 PdfRenderer——纯系统 API,零第三方 PDF 库。
  2. 零权限:文件访问走 SAF / PhotoPicker / MediaStore,不需要存储权限。
  3. 深色优雅: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. 工程搭建(离线也能干)

没有网络也能搭好工程骨架:

  1. Gradle Wrapper:本机无法运行 gradle wrapper(守护进程锁、权限问题),改为从磁盘上已有的其他 Gradle 项目复制 gradle-wrapper.jar + gradlew + gradlew.bat(找到的正好是 Gradle 8.8 时代的 wrapper),自己写 gradle-wrapper.properties
  2. 版本目录 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,统一管理。
  3. 构建脚本settings.gradle.kts(预留阿里云镜像注释)、根/模块 build.gradle.ktsgradle.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 渲染界面设计稿,但宿主不可用。改用两条替代路径

  1. GDI+ 程序化渲染:写一个 PowerShell 脚本(design/render_mockups.ps1),用 System.Drawing 按坐标画出 5 个屏幕(390×844 @2x)+ 应用图标 + 总览板。踩坑:函数名 H 撞了 PowerShell 内置别名 Get-History(大小写不敏感!),且 .ps1 需 UTF-8 BOM 才能读中文。全部修复后渲染成功。
  2. HTML 交互原型demo/app-prototype.html——纯 CSS/JS 还原深色界面,手机壳里可点:选图→编辑→拖拽排序→进度动画→预览翻页→工具。用户双击浏览器即可"体验"应用。

经验:外部组件不可用时,用语言自带的绘图/HTML 能力做等价交付,保证用户"看得见"。


7. 真实构建与排错(最有价值的部分)

用户安装 Android Studio 后开始真构建。每一轮编译都暴露了真实问题——这正是"能跑命令"比"只写代码"强的地方:

#错误根因修复
1Directory 'E:\deepseek_1' does not contain a Gradle buildgradlew 在错误工作目录执行pwsh 指定 workdir
2SDK location not foundlocal.properties 被 PowerShell 写入 UTF-8 BOM,Java properties 解析失败无 BOM 重写 + ANDROID_HOME 双保险
3Failed to find Platform SDK platforms;android-37新 SDK 只有 android-37.0 平台,AGP 8.5 需要 android-34;SDK XML 版本 4 与 AGP 8.5 不兼容复制 37 目录伪装成 34(后改用官方包)
4jlink.exe does not existIntelliJ 精简 JBR 缺 jlink换完整 JDK 17
5编译错误 ×9:it 变量遮蔽、coil RotationTransformation 不存在、BitmapImageBitmap 类型不符、挂起函数位置错误、combinedClickable 缺 OptIn、PageSettings 缺字段手写代码的真实 bug逐一定位修复
6真机启动闪退导航路由注册错误composable(route="preview") 但声明了必填参数 uri,导航库启动即抛 IllegalArgumentExceptionroute 改为 "preview?uri={uri}&name={name}"

排错方法论:静态校验(grep 资源引用、括号配平、runCatching 内挂起函数)→ 真构建暴露编译错误 → 模拟器复现运行时错误 → logcat 拿堆栈。每层都能抓到不同类型的 bug


8. 模拟器验证(本机自测的完整链路)

没有真机时,自己搭模拟器做端到端验证:

  1. 发现网络其实通:PowerShell/curl 失败是 Windows Schannel 凭证问题(SEC_E_NO_CREDENTIALS),但 Java 的 TLS 正常(Gradle 能下载依赖证明了这点)。用 Java 写了个 10 行下载器 tools/D.java 下载 SDK 组件。
  2. 补平台:从 repository2-3.xml 找到官方 platform-34-ext7_r03.zip,下载并 SHA1 校验,替换伪装的目录。
  3. 下载系统镜像x86_64-34_r04.zip(687MB),解压到 system-images/android-34/default/
  4. 手工建 AVD:无 cmdline-tools,直接写 config.ini + .iniANDROID_AVD_HOME 指向可写目录)。
  5. 启动:WHPX 硬件加速可用,90 秒 boot。
  6. 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. 经验总结(给后来者)

  1. 先侦察环境:工具链/网络/权限决定策略,一分钟排查省一天返工。
  2. 需求文档化:让用户先写方案(哪怕要点),开发有依据。
  3. 分层实现:UI / 数据 / 引擎分离,出错好定位。
  4. 尽早真构建:编译器/运行时抓到的 bug 比想象中多(本应用约 10 处)。
  5. 模拟器自动化:uiautomator + adb 可以全自动测 UI 流程,比截图可靠。
  6. 网络被"伪断"时换路子:schannel 失败但 Java TLS 通——工具选对了,网络就是通的。
  7. 兜底思维:OpenPencil 不可用→GDI+/HTML;adb 连不上→崩溃日志捕获器;只要目标明确,总有路径。
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐