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

标签 android pdf webview

使用 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 而崩溃。问题是,我无法实现这些回调的 stub ,因为 LayoutResultCallbackWriteResultCallback 受包保护。

所以,我的问题是:

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

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

  3. 是否可以利用 Web View 本身创建的打印适配器,就像我在第二个示例中尝试做的那样?

谢谢。

最佳答案

Using Android 19 print APIs, I'm trying to render the content of a WebView directly into a PDF file on device storage.

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

Why the WebView.draw(PdfDocument.Page.getCanvas()) produces a raster PDF with non-selectable text?

draw() 将 UI 渲染到 Canvas,而不管源 UI(EditTextButton) 、ImageViewViewPagerWebViewConstraintLayout 中的一些小部件组合等)。如果 CanvasBitmap 支持(他们可能在这里使用),您将获得一个 Bitmap

Is it somehow possible to make use of the print adapter created by the web view itself, like I was trying to do in the second example?

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

关于android - 将 WebView HTML 内容直接打印到 PDF 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48500382/

相关文章:

php - 未捕获的异常 'ImagickException',消息为 'Unable to read the file'

Android:来自 WebView 的 shouldOverrideUrlLoading 的 CalledFromWrongThreadException

javascript - JQuery Mobile 对话框页面无法正常工作

internet-explorer - 在 Edge/IE11 中显示 Blob PDF

android - 确定 Subject 何时没有订阅者

c# - 如何从字节数组 c# MVC .NET Core 在 iframe 中显示 pdf

java - 如何在 Android WebView 中访问 WhatsAppWeb?

JavaFX Web View : Java not accessible

android - 如何在android中为自定义按钮实现onkeydown事件

java - 以编程方式在RelativeLayout中设置 View 边距没有任何影响