HTML ドキュメントの印刷

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

Android 4.4(API レベル 19)では、HTML コンテンツを印刷できるように WebView クラスが更新されました。このクラスを使用すると、ローカル 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 オブジェクトのインスタンスが保存されますが、これは必須ではありません。アプリでは、このオブジェクトを使用して、処理中の印刷ジョブの進行状況を確認できます。このアプローチは、印刷ジョブの完了、失敗、ユーザーによるキャンセルなどのステータスをアプリで監視するときに役立ちます。印刷ジョブのシステム通知が印刷フレームワークによって自動的に作成されるため、アプリ内通知を作成する必要はありません。