HTML ドキュメントの印刷

Android でシンプルな写真以外のコンテンツを印刷するには、印刷ドキュメントでテキストとグラフィックを作成する必要があります。Android フレームワークでは、HTML を使用してドキュメントを作成し、最小限のコードでそれを印刷できます。

Android 4.4(API レベル 19)では WebView クラスが更新され、HTML コンテンツを印刷できるようになりました。このクラスを使用すると、ローカルの HTML リソースを読み込むか、ウェブからページをダウンロードして印刷ジョブを作成し、Android の印刷サービスに渡すことができます。

このレッスンでは、テキストとグラフィックを含む HTML ドキュメントをすばやく作成し、WebView を使用して出力する方法を示します。

HTML ドキュメントを読み込む

WebView を使用して HTML ドキュメントを印刷するには、HTML リソースを読み込むか、HTML ドキュメントを文字列として作成する必要があります。このセクションでは、HTML 文字列を作成し、印刷のために WebView に読み込む方法について説明します。

このビュー オブジェクトは、通常、アクティビティ レイアウトの一部として使用されます。ただし、アプリで 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() メソッドの最初のパラメータでベース 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 のインスタンスが処理できるのは、一度に 1 つの印刷ジョブだけです。
  • 横長プロパティなどの 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 オブジェクトのインスタンスを保存しますが、これは必須ではありません。アプリケーションは、このオブジェクトを使用して、処理中の印刷ジョブの進行状況を追跡できます。この方法は、アプリケーションの印刷ジョブのステータス(完了、失敗、ユーザーによるキャンセル)をモニタリングする場合に便利です。印刷フレームワークによって印刷ジョブのシステム通知が自動的に作成されるため、アプリ内通知を作成する必要はありません。