列印 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;
}

注意:請確保產生列印工作的呼叫是透過上一節所建 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 物件的執行個體以供應用程式使用,但這不是必要步驟。您的應用程式可能會在進行列印工作時使用這個物件來追蹤列印工作的進度。當您要監控應用程式中的列印工作狀態,例如完成、失敗或使用者取消作業時,這個方法非常實用。列印架構會自動為列印工作建立系統通知,因此您不需要建立應用程式內通知。