打印HTML文档

在Android上打印超出简单照片的内容需要在打印文档中组合文本和图形。Android框架提供了一种使用HTML编写文档并以最少的代码打印它的方法。

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

本课程将向您展示如何快速构建包含文本和图形的HTML文档,并使用WebView打印它。

加载HTML文档

使用WebView打印HTML文档涉及加载HTML资源或将HTML文档构建为字符串。本节介绍如何构建HTML字符串并将其加载到WebView中以进行打印。

此视图对象通常用作活动布局的一部分。但是,如果您的应用程序未使用WebView,则可以专门为打印目的创建该类的实例。创建此自定义打印视图的主要步骤是

  1. 创建一个WebViewClient,在加载HTML资源后启动打印作业。
  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;
}

注意:确保您生成打印作业的调用发生在您在上节中创建的onPageFinished()方法中。如果您不等待页面加载完成,则打印输出可能不完整或为空白,或者可能完全失败。

注意:上面的示例代码保留了WebView对象的实例,因此在创建打印作业之前不会被垃圾回收。确保您在自己的实现中也这样做,否则打印过程可能会失败。

如果要在页面中包含图形,请将图形文件放在项目的assets/目录中,并在loadDataWithBaseURL()方法的第一个参数中指定一个基本URL,如下面的代码示例所示

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对象的实例供应用程序使用,这不是必需的。您的应用程序可以使用此对象跟踪打印作业在处理过程中的进度。当您想在应用程序中监控打印作业的完成、失败或用户取消状态时,此方法很有用。无需创建应用内通知,因为打印框架会自动为打印作业创建系统通知。