You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi TWebBrowser在Android/iOS端Window.Print功能失效问题

核心根因

FMX 跨平台框架封装的 TWebBrowser 组件在 iOS、Android 端本质是调用系统原生 WebView 内核,默认没有实现完整浏览器自带的 window.print 事件响应逻辑,这和独立 Safari、Chrome 这类完整浏览器的实现存在差异,和你写的 PDF.js 业务逻辑本身没有关系。

排查步骤
  • 先做最小场景验证:剥离所有PDF.js相关逻辑,在嵌入页面加一个绑定window.print()调用的测试按钮,确认最简打印调用是否生效。如果这个场景下点击按钮也没有任何打印响应,即可确定问题出在WebView层的能力缺失,和前端PDF.js逻辑无关。
  • 开启WebView远程调试确认链路:iOS端用Mac端Safari连接设备调试WebView,Android端用PC端Chrome连接设备调试WebView,在PDF.js打印按钮的点击逻辑、window.print调用位置加断点,确认:
    • 点击打印按钮后逻辑是否正常走到window.print调用
    • 控制台有没有抛出Blob资源访问、权限类的静默错误
    • PDF.js生成的打印用临时Blob URL是否被WebView安全策略拦截
  • 核对平台配置差异:
    • iOS端:确认当前TWebBrowser使用的是WKWebView(老版本FMX默认用被废弃的UIWebView,本身打印支持就有缺陷),确认FMX封装层有没有实现WKWebView的打印相关代理方法。
    • Android端:确认应用是否声明了打印相关权限,当前设备的系统WebView版本是否支持打印API,TWebBrowser有没有开启JavaScript自动弹窗/文件访问权限。
解决方案

优先推荐:JS桥接原生打印方案(跨版本兼容性最好)

不要依赖WebView默认的window.print实现,自行打通前端和原生层的打印通信链路:

  1. 前端层重写全局window.print方法,拦截PDF.js的打印请求,把待打印的PDF数据通过桥接传给原生层:
// 在Web应用初始化阶段注入这段逻辑,适配FMX WebView环境
const originalPrint = window.print;
window.print = function() {
  // 优先判断是否在FMX WebView环境,存在原生桥接方法时走原生打印
  if (window.FMXBridge && typeof window.FMXBridge.printPDF === 'function') {
    // 从PDF.js实例获取当前打开的PDF二进制数据,根据自身业务的PDF.js初始化逻辑调整取值方式
    const pdfBinaryData = pdfViewer.currentDocument.getData();
    // 转成Base64传给原生层,避免二进制传输的类型转换问题
    const base64Pdf = btoa(String.fromCharCode.apply(null, new Uint8Array(pdfBinaryData)));
    window.FMXBridge.printPDF(base64Pdf);
    return;
  }
  // 普通浏览器环境走原有打印逻辑
  originalPrint.call(window);
}
  1. FMX原生层实现桥接逻辑:
  • 给TWebBrowser组件注册JS交互接口,暴露FMXBridge.printPDF方法给前端调用
  • 接收到前端传的Base64格式PDF数据后,转存为平台可识别的PDF文件
  • 调用系统原生打印API完成打印:iOS端用UIPrintInteractionController弹出系统打印面板,Android端用系统PrintManager提交PDF打印任务

快速修复方案(改动量小,适配特定FMX版本)

  • iOS端:如果使用Delphi 11及以上版本,可以直接给WKWebView注入一段补丁JS,手动把window.print调用桥接到原生的viewPrintFormatter方法,不需要改动现有PDF.js逻辑;低于11的版本需要手动补全WKWebView的打印代理实现,替换掉FMX默认的空实现。
  • Android端:给TWebBrowser绑定的WebView注册自定义JavascriptInterface,拦截window.print调用,主动唤起系统打印服务,同时在应用Manifest里添加android.permission.PRINT权限,开启WebView的文件访问开关。
避坑注意
  • 不要直接用PDF.js默认的iframe打印方案,iOS WKWebView对跨域iframe、Blob iframe的打印有严格的沙箱限制,大概率会静默失败。
  • Android端存储待打印PDF时,不要放到公共存储目录,Android 10及以上的分区存储机制会拦截文件访问,直接存到应用私有缓存目录即可。
  • FMX的TWebBrowser默认会吞掉大部分JS权限类错误,不开启远程调试的话很难定位到具体失败点,排查阶段一定要开远程调试看控制台日志。

内容的提问来源于stack exchange,提问作者Carlos Z.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 00:18:15