移动办公应用的“页面能打开”,与“用户可以完成一次编辑任务”,是两个不同的验收目标。模板卡片可能正常显示,但创建副本时才调用到错误的资源服务;登录框可能正常出现,但 Logo 在安装包中无法解码;Web 页面的图片已经修改,原生启动图却仍沿用旧资源。
本文以开源项目海豹办公(Seal Office)1.9.15 为案例,介绍 Android WebView 应用如何围绕真实用户动作建立生产回归:从服务装配、图片资源、本地协议、原生线程到最终包核验,分别验证哪些事情,怎样避免把开发环境正常误认为发布成品正常。
海豹办公将文字、表格、演示和 PDF 页面工具放在同一工作台中。移动端使用 uni-app x 的 UTS 外壳加载安装包内的编辑器,桥接层适配原生文件、网络与页面行为。这里的“共用编辑器”并不代表所有平台拥有相同的系统能力。
以演示模板为例,一次点击后至少涉及模板描述、页面结构、图片资源恢复、多页预览、编辑副本创建以及工作区状态。列表测试通过,只覆盖了入口,并没有证明后续资源生命周期正确。
当前模板市场包含 300 套原创可编辑模板,每套为 9 页。手机列表按封面与分页加载,每页 8 套。回归脚本逐一打开首屏 8 套模板,检查九页预览、真实图片和编辑副本;这一测试范围不应被写成“300 套模板在所有设备上全部验收”。
本轮曾出现点击模板后提示“恢复 is not a function”。根因不在卡片样式,而在演示通道初始化时的参数位置:第二个参数是资源存储,第三个参数才是识别、录制等服务依赖。把服务依赖对象放到资源存储位置,后续方法调用自然无法满足契约。
修复后的调用位于 mobile/web/bridge.ts:
core.presentation.注册演示通道(ipcMain, undefined, {
识别服务: core.recognition.创建识别服务({ 助手服务: assistant }),
录制服务: recording
})回归测试不只检查异常提示消失,还通过实际浏览器侧 IPC 操作资源:恢复、读取、同步、导出和释放,并校对读取数据与原始数据一致。这样才能发现“为了不报错而补一个空方法”留下的功能缺口。
对复用多个服务的桥接层,值得持续检查可选参数的位置、对象职责与类型约束。错误发生在读取图片时,并不代表应该只在图片组件中增加重试。
登录 Logo 丢失的问题来自生产资源路径。脚本二次合并后,运行时 URL 没有保留正确的 assets 目录基准。开发服务器可访问某个路径,不代表本地 file:// 页面具有相同的资源解析结果。
生产回归直接加载最终本地页面,找到登录图片,再等待浏览器解码,而不是只检查 img 标签存在。核心观察可以概括为:
await image.decode()
const rect = image.getBoundingClientRect()
const loaded = image.complete && image.naturalWidth > 0
// 分别检查 loaded、资源协议和实际显示宽高。这里的 image 指页面中的真实图片元素。资源路径、网络或本地访问、浏览器解码和 CSS 显示尺寸,是不同阶段;只验证其中一个布尔值,很难说明其余阶段也正常。
当前登录回归还检查 Logo 显示为 64×64 的正方形,并且来源为本地文件或内联资源。截图用于人工观察比例与布局,尺寸和解码断言用于稳定识别回归,两者不能相互替代。
项目的移动回归脚本运行实际打包后的 IIFE 和浏览器侧 IPC,加载 mobile/static/office/index.html。它没有用伪造的桌面 API 替代演示资源操作,因此可以覆盖一部分开发服务器与生产资源之间的差异。
本地页面出错时,需要先分清主文档、图片、字体与接口请求。一个字体或图片失败,不应直接把已加载的整个工作台替换成错误页。当前原生桥接只允许对应的本地入口文档获得桥接或替换工作台,子资源错误不能被放大成主页面失败。
这种分层也有边界:桌面环境中的本地页面回归,可以验证构建资源与部分逻辑,但不能替代 Android 系统 WebView、真机内存、输入法与文件选择器的验收。
前一轮移动端修复涉及原生网络回调在后台线程调用 WebView。项目将相关脚本执行与分享操作放回 UI 线程处理。当前封装位于 mobile/native/workspace.uts:
export function onUIThread(task: () => void) {
// #ifdef APP-ANDROID
UTSAndroid.getUniActivity()?.runOnUiThread(task)
// #endif
// #ifndef APP-ANDROID
task()
// #endif
}调用回到 UI 线程之后,还需要检查页面是否仍然存活、工作台是否处于可接收脚本的状态。否则,用户离开页面后才返回的请求,仍可能向已经失效的页面写入。
排错时应分别记录 JavaScript 异常、主文档加载失败和原生进程退出。它们都可能被用户描述为“打不开”,但对应的证据与处理路径并不相同。
启动页属于原生资源,不是进入 WebView 后的普通图片。1.9.15 Android 改用专用留白启动图,只保留一个标识,移除重复且拉伸的底部品牌图。
密度资源 | 当前图片画布 | 检查重点 |
|---|---|---|
xhdpi | 576×576 | 使用专用启动图,标识保持正方形与留白 |
xxhdpi | 864×864 | 可见标识约 96dp,不能只看画布像素 |
xxxhdpi | 1152×1152 | 包内存在对应资源,且没有重复底部标识 |
回归脚本检查配置不再包含 brand 图,逐个读取图片,按透明像素边界计算实际可见范围,并检查居中与比例。这样可以区分“文件很大”和“用户看到的 Logo 很大”,避免直接把铺满画布的应用图标拿来当启动图。
静态资源检查仍需与设备启动效果结合。不同系统版本的启动过渡、状态栏和窗口尺寸,应在目标设备上分别观察。
办公应用常有文档标签、弹窗、功能面板和云目录。返回键如果在任何页面都退出进程,或者永远被 WebView 历史记录吞掉,都会让用户难以预期。
当前移动端按层级处理:先关闭弹窗与功能面板;在云空间子目录先回到上级;其他模块先回首页;首页一级页面再返回系统桌面,保留工作区并触发备份。
测试应覆盖每一个分支,以及应用退到后台后重新进入的状态。仅验证首页按返回键的结果,不能证明编辑页和子目录也符合预期。保留工作区也不等于可以忽略尚未完成的本地写入与备份检查。
可以把这类应用的检查拆成四层:服务层验证参数契约与资源生命周期;生产页面验证本地路径、图片解码与用户动作;原生层验证线程、启动资源和返回键;最终软件包再核对版本、签名与内置编辑器是否一致。
同一版本号内多次重新打包时,尤其需要核对成品是否包含当前修复。开发者本地文件已更新,不代表之前下载的 APK 或 App Pack 自动变成了新包。
1.9.15 本轮移动包已核对版本、发布签名和内置编辑器,并增加生产本地资源回归;这不代替目标真机对安装、启动、导入导出与生命周期的验收。Android 最低支持 Android 9;HarmonyOS 使用独立的正式签名 App Pack,两种包不能混装。当前没有公开 iOS IPA。
本文的案例不能证明全部 Office 文档对象无损往返,也不能把 Windows Access Runtime / ACE 的数据库维护能力推导为移动端完整运行 Access 应用。基础编辑可本地使用;云空间与用户自行配置的模型服务属于可选网络能力,需要分别说明数据去向。
对大型模板市场,也不能用首屏测试替代整个模板集的抽样与完整性检查,更不能没有实测就给出内存下降或启动加速的百分比。把已检查的层级、设备与样本写清楚,比笼统宣称“全面兼容”更有帮助。
本文为基于海豹办公 1.9.15 源码的技术分享,使用 AI 辅助整理文字。项目采用 MIT 许可证,依赖与第三方服务按各自条款使用。反馈问题时请提供稳定复现步骤与脱敏文件,不要公开真实客户资料、账号密钥或恢复密钥。
图1展示多页模板预览,图2展示本地登录页。截图与解码、尺寸断言配合使用,不单独作为全部功能正常的证明。


原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。