On the open web, window.print() opens the browser print sheet, and from there a user can save the page as a PDF or send it to a printer. Inside a WebView that same call is a silent no-op. Android exposes printing only through a host-side API, and iOS WKWebView ignores the call completely. A host-owned runtime bridges print and PDF export — one API that produces a real document on every engine.
Android: printing is a host-only API
The Android documentation is explicit: to print from a WebView you call webView.createPrintDocumentAdapter(jobName) and hand it to the system PrintManager. There is no window.print() path the page can trigger on its own. The docs also list hard limitations: you cannot use JavaScript in the HTML document to trigger printing, only one print job can run per WebView instance at a time, and HTML documents with CSS print attributes such as landscape orientation are not supported. So a checkout page with a Print ticket button that works in Chrome does nothing inside the app's WebView. A developer must own the WebView instance, build the adapter, and present the system print sheet — and PDF export rides the exact same path; the page cannot initiate it.
iOS: window.print() is silently ignored
In WKWebView the window.print() call does not open a print panel. The widely used workaround is to inject a user script that overrides window.print to post a message to a WKScriptMessageHandler, then the native side drives UIPrintInteractionController. Even then, iOS has no desktop-equivalent silent web print: the print controller must present a user-visible print interface for confirmation. There is no headless print pipeline a web page can reach. PDF export is the same story — the bridge has to live in the app.
What breaks when print dies
- Receipts and itineraries never appear. A Print / Save PDF button that works in Safari does nothing in the WebView.
- Invoices and reports cannot be exported. Finance and SaaS flows that rely on browser print-to-PDF lose the path.
- Logistics and retail slips fail. Warehouse pick lists, shipping labels, and POS receipts cannot be produced in-app.
- Embedded browsers diverge further. WeChat, Douyin, and similar in-app WebViews rarely expose any print surface, so the break hides during desktop QA.
The runtime fix
A host-owned runtime bridges the print and export layer. The page calls one uniform API — runtime.print() or runtime.exportPdf() — and the host renders through the native PrintManager on Android and UIPrintInteractionController on iOS. Header, footer, page numbers, and orientation are handled natively and consistently. One integration, every engine, one document format.
| Dimension | WebView | Host-owned runtime |
|---|---|---|
| Trigger | window.print() is a no-op | Uniform runtime.print() |
| Android path | Host must wire adapter + PrintManager | Native PrintManager |
| iOS path | window.print() ignored | Native UIPrintInteractionController |
| JS-triggered print | Blocked by platform | Native bridge |
| PDF export | Not from the page | One API |
| Consistency | Per-engine | Uniform |
A native app prints a receipt on every device. A stock WebView prints on almost none. A runtime gives the page one print surface — and a real PDF at the end of it.
Sources
- Android Developers — Printing HTML documents —
createPrintDocumentAdapter+PrintManager, and the limitations: no JavaScript-triggered printing, one job per WebView, no CSS print attributes like landscape. - Stack Overflow — How to create PDF from webview in Android — the PrintManager approach that turns a WebView into a PDF from API 19.
- Exchangetuts — Capturing window.print() from a WKWebView — the
window.printoverride to aWKScriptMessageHandlerplusUIPrintInteractionControllerworkaround. - 博客园 — iOS Safari/WKWebView 无等价静默 Web 打印 — the structural limit: no desktop-equivalent silent print on iOS WebView.
- MDN — window.print() — the web API that WebView silently drops.