打印 HTML 文档

如需在 Android 上打印简单照片以外的内容,需要在打印文档中撰写文本和图形。Android 框架提供了一种使用 HTML 编写文档并用少量代码输出该文档的方法。

在 Android 4.4(API 级别 19)中,WebView 类已更新,以支持打印 HTML 内容。该类可让您加载本地 HTML 资源或从网络中下载网页,创建打印作业并将其移交给 Android 的打印服务。

本课介绍了如何快速构建包���文本和图形的 HTML 文档,���使用 WebView 输出该文档。

加载 HTML 文档

使用 WebView 打印 HTML 文档涉及加载 HTML 资源或以字符串形式构建 HTML 文档。本部分介绍如何构建 HTML 字符串并将其加载到 WebView 中以便输出。

此视图对象通常用作 Activity 布局的一部分。但是,如果您的应用没有使用 WebView,则可以创建专门用于打印目的的类的实例。创建此自定义打印视图的主要步骤如下:

  1. 创建可在加载 HTML 资源后启动打印作业的 WebViewClient
  2. 将 HTML 资源加载到 WebView 对象中。

以下代码示例演示了如何创建简单的 WebViewClient 并加载即时创建的 HTML 文档:

Kotlin

private var mWebView: WebView? = null

private fun doWebViewPrint() {
    // Create a WebView object specifically for printing
    val webView = WebView(activity)
    webView.webViewClient = object : WebViewClient() {

        override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest) = false

        override fun onPageFinished(view: WebView, url: String) {
            Log.i(TAG, "page finished loading $url")
            createWebPrintJob(view)
            mWebView = null
        }
    }

    // Generate an HTML document on the fly:
    val htmlDocument =
            "<html><body><h1>Test Content</h1><p>Testing, testing, testing...</p></body></html>"
    webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null)

    // Keep a reference to WebView object until you pass the PrintDocumentAdapter
    // to the PrintManager
    mWebView = webView
}

Java

private WebView mWebView;

private void doWebViewPrint() {
    // Create a WebView object specifically for printing
    WebView webView = new WebView(getActivity());
    webView.setWebViewClient(new WebViewClient() {

            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return false;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                Log.i(TAG, "page finished loading " + url);
                createWebPrintJob(view);
                mWebView = null;
            }
    });

    // Generate an HTML document on the fly:
    String htmlDocument = "<html><body><h1>Test Content</h1><p>Testing, " +
            "testing, testing...</p></body></html>";
    webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null);

    // Keep a reference to WebView object until you pass the PrintDocumentAdapter
    // to the PrintManager
    mWebView = webView;
}

注意:请确保用于生成打印任务的调用发生在上一部分中创建的 WebViewClientonPageFinished() 方法中。如果您没有等到网页加载完成,则打印输出可能不完整或空白,也可能完全失败。

注意:上面的示例代码保存了 WebView 对象的实例,以便在创建打印作业之前不会对该实例进行垃圾回收。请务必在自己的实现中也执行相同的操作,否则打印过程可能会失败。

如果要在页面中添加图形,请将图形文件放在项目的 assets/ 目录中,并在 loadDataWithBaseURL() 方法的第一个参数中指定基准网址,如以下代码示例所示:

Kotlin

webView.loadDataWithBaseURL(
        "file:///android_asset/images/",
        htmlBody,
        "text/HTML",
        "UTF-8",
        null
)

Java

webView.loadDataWithBaseURL("file:///android_asset/images/", htmlBody,
        "text/HTML", "UTF-8", null);

您也可以通过将 loadDataWithBaseURL() 方法替换为 loadUrl() 来加载要打印的网页,如下所示。

Kotlin

webView.loadUrl("https://developer.android.com/about/index.html")

Java

// Print an existing web page (remember to request INTERNET permission!):
webView.loadUrl("https://developer.android.com/about/index.html");

使用 WebView 创建打印文档时,请注意以下限制:

  • 您不能向文档中添加页眉或页脚,包括页码。
  • HTML 文档的打印选项不支持打印页面范围,例如:不支持打印 10 页 HTML 文档中的第 2 至 4 页。
  • WebView 的实例一次只能处理一个打印作业。
  • 不支持包含 CSS 打印属性(例如横向属性)的 HTML 文档。
  • 您不能在 HTML 文档中使用 JavaScript 触发打印作业。

注意:布局中包含的 WebView 对象的内容在其加载文档后也可以打印。

如果您希望创建自定义程度更高的打印输出并完全控制打印页面上的内容绘制,请转到下一课:打印自定义文档课程。

创建 WebView 并加载 HTML 内容后,您的应用即将完成这一部分打印过程。接下来的步骤是访问 PrintManager,创建打印适配器,最后创建打印作业。以下示例说明了如何执行这些步骤:

Kotlin

private fun createWebPrintJob(webView: WebView) {

    // Get a PrintManager instance
    (activity?.getSystemService(Context.PRINT_SERVICE) as? PrintManager)?.let { printManager ->

        val jobName = "${getString(R.string.app_name)} Document"

        // Get a print adapter instance
        val printAdapter = webView.createPrintDocumentAdapter(jobName)

        // Create a print job with name and adapter instance
        printManager.print(
                jobName,
                printAdapter,
                PrintAttributes.Builder().build()
        ).also { printJob ->

            // Save the job object for later status checking
            printJobs += printJob
        }
    }
}

Java

private void createWebPrintJob(WebView webView) {

    // Get a PrintManager instance
    PrintManager printManager = (PrintManager) getActivity()
            .getSystemService(Context.PRINT_SERVICE);

    String jobName = getString(R.string.app_name) + " Document";

    // Get a print adapter instance
    PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(jobName);

    // Create a print job with name and adapter instance
    PrintJob printJob = printManager.print(jobName, printAdapter,
            new PrintAttributes.Builder().build());

    // Save the job object for later status checking
    printJobs.add(printJob);
}

此示例保存了 PrintJob 对象的实例供应用使用,这不是必需的。您的应用可能会使用此对象来跟踪正在处理打印任务的进度。当您想监控应用中打印任务的状态,例如完成、失败或用户取消时,此方法会非常有用。无需创建应用内通知,因为打印框架会自动为打印任务创建系统通知。