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

时间:2018-01-29 11:38:28

标签: 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,上面的代码崩溃了。问题是,我无法实现这些回调的存根,因为LayoutResultCallbackWriteResultCallback是受包保护的。

所以,我的问题是:

  1. 我真的可以做我想在这里实现的目标吗?我的意思是,从网页视图制作PDF而不使用系统的打印机UI

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

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

  4. 谢谢。

1 个答案:

答案 0 :(得分:1)

  

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

打印API用于打印。他们从来没有创建过PDF文件。

  

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

draw()将用户界面呈现为Canvas,无论源用户界面如何(EditTextButtonImageViewViewPager,{ {1}},WebView中的某些小部件组合,等等。如果ConstraintLayoutCanvas支持 - 这是他们可能在此处使用的内容 - 那么您将获得Bitmap

  

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

您可以尝试将BitmapLayoutResultCallback的实现放在WriteResultCallback包中的应用中,方法是将Java包添加为项目的一部分。俗话说,YMMV。