将 WebView HTML 内容直接打印到 PDF 文件

Posted

技术标签:

【中文标题】将 WebView HTML 内容直接打印到 PDF 文件【英文标题】:Printing a WebView HTML content directly to a PDF file 【发布时间】:2018-07-08 02:19:16 【问题描述】:

使用 android 19 打印 API,我正在尝试将 WebView 的内容直接呈现为设备存储上的 PDF 文件。我知道我可以将PrintJob 发送到PrintManager 并让用户在那里选择“另存为PDF”,但我不希望这样。我想从我的应用程序中立即保存 PDF。

我尝试使用WebView.draw(PdfDocument.Page.getCanvas()),但生成的 PDF 是光栅,而不是矢量 ???? Here's the result(文本不可选,也可以尝试缩放)下面的代码:

final String htmlDocument = "<html><body><h1>Test Content</h1><p>Testing, testing, testing...</p></body></html>";
webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null);

// ...The following is on web view client's onPageFinished()

final PrintAttributes attrs = new PrintAttributes.Builder()
    .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
    .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
    .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
    .setResolution(new PrintAttributes.Resolution("1", "label", 300, 300))
    .build();

final PrintedPdfDocument document = new PrintedPdfDocument(this, attrs);
final PdfDocument.Page page = document.startPage(1);

webView.draw(page.getCanvas());
// Also tried: webView.capturePicture().draw(page.getCanvas());
document.finishPage(page);

final FileOutputStream outputStream = new FileOutputStream(new File(Environment.getExternalStorageDirectory(), "test.pdf"));
document.writeTo(outputStream);
outputStream.close();

document.close();

鉴于将PrintJob 发送到PrintManager 会生成带有可选文本的漂亮矢量PDF,我在阅读了打印作业的工作原理后尝试直接使用这些API:

final PrintDocumentAdapter webViewPrintAdapter = webView.createPrintDocumentAdapter();

outputFile = new File(Environment.getExternalStorageDirectory(), "test2.pdf");
final ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.open(outputFile, ParcelFileDescriptor.MODE_CREATE | ParcelFileDescriptor.MODE_READ_WRITE);

webViewPrintAdapter.onStart();
webViewPrintAdapter.onLayout(attrs, attrs, new CancellationSignal(), null, new Bundle());
webViewPrintAdapter.onWrite(new PageRange[] PageRange.ALL_PAGES , fileDescriptor, new CancellationSignal(), null);
webViewPrintAdapter.onFinish();

上面的代码由于带有两个 null 回调的 NPE 而崩溃。问题是,我无法实现这些回调的存根,因为 LayoutResultCallbackWriteResultCallback 是包保护的。

所以,我的问题是:

    真的有可能做到我想要在这里实现的目标吗?我的意思是,不使用系统的打印机 UI,从 Web 视图制作 PDF?

    为什么WebView.draw(PdfDocument.Page.getCanvas()) 会生成带有不可选择文本的光栅 PDF?

    是否可以像我在第二个示例中尝试那样使用由 Web 视图本身创建的打印适配器?

谢谢。

【问题讨论】:

更多详情请参考annalytics.co.uk/android/pdf/2017/04/06/…,使用了你的第二种方法。 我觉得这个链接可以解决你的问题 这里是a link! @Akshay 谢谢,它有效!这基本上是我的第二个示例,其中他们设法使用 CommonsWare 在他的回答中建议的技巧来实例化回调 @lorenzo-s 很高兴为您提供帮助 【参考方案1】:

使用 Android 19 打印 API,我正在尝试将 WebView 的内容直接呈现为设备存储上的 PDF 文件。

打印 API 用于打印。它们从未用于创建 PDF 文件。

为什么 WebView.draw(PdfDocument.Page.getCanvas()) 会生成带有不可选择文本的光栅 PDF?

draw() 将 UI 呈现到 Canvas,而不管源 UI(EditTextButtonImageViewViewPagerWebViewConstraintLayout 中的一些小部件组合, 等等。)。如果CanvasBitmap 支持——这可能是他们在这里使用的——你会得到一个Bitmap

是否有可能像我在第二个示例中尝试那样使用由 Web 视图本身创建的打印适配器?

您可以尝试将LayoutResultCallbackWriteResultCallback 的实现放在android.print 包中的应用程序中,方法是将该Java 包添加为项目的一部分。俗话说,YMMV。

【讨论】:

以上是关于将 WebView HTML 内容直接打印到 PDF 文件的主要内容,如果未能解决你的问题,请参考以下文章

iOS 将WKWebView内的HTML打印为PDF

appium不能获取webview内容的解决办法

Android - Webview 元素 onClick 事件未触发?

解决 Json 中 Html 内容因为反编译带有"\"导致 WebView 无法直接加载问题(字符串的查找与替换)

将 SWF 加载到 WebView

将Playbuzz加载脚本加载到Android中的WebView中