将 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 而崩溃。问题是,我无法实现这些回调的存根,因为 LayoutResultCallback
和 WriteResultCallback
是包保护的。
所以,我的问题是:
真的有可能做到我想要在这里实现的目标吗?我的意思是,不使用系统的打印机 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(EditText
、Button
、ImageView
、ViewPager
、WebView
、ConstraintLayout
中的一些小部件组合, 等等。)。如果Canvas
由Bitmap
支持——这可能是他们在这里使用的——你会得到一个Bitmap
。
是否有可能像我在第二个示例中尝试那样使用由 Web 视图本身创建的打印适配器?
您可以尝试将LayoutResultCallback
和WriteResultCallback
的实现放在android.print
包中的应用程序中,方法是将该Java 包添加为项目的一部分。俗话说,YMMV。
【讨论】:
以上是关于将 WebView HTML 内容直接打印到 PDF 文件的主要内容,如果未能解决你的问题,请参考以下文章
Android - Webview 元素 onClick 事件未触发?