1. ホーム
  2. アンドロイド

アンドロイドがプリンターに接続し、印刷する

2022-02-24 18:25:04

<スパン Androidユーザーは自分の端末だけでコンテンツを見ることが多いですが、誰かの画面を見せることが情報共有として適切でない場合もあります。Androidアプリから情報を印刷することで、アプリを通してコンテンツを拡大表示したり、アプリを使っていないユーザーと共有したりすることができます。また、印刷することで、デバイスや十分なバッテリー電力、ワイヤレスネットワーク接続に依存しない情報のスナップショットを作成することができます。
<スパン で Android 4.4 (API level 19) 以降の場合 は、その <スパン フレームワークは、Android アプリケーションから画像や文書を直接印刷するためのサービスを提供します。このトレーニングでは、画像やHTMLページの印刷、印刷用のカスタムドキュメントの作成など、アプリケーションで印刷機能を有効にする方法について説明します。

I: 写真をプリントする

<スパン <スパン 写真を撮ったり共有したりすることは、モバイル機器の最も一般的な用途の一つです。アプリで写真を撮影したり、写真を表示したり、ユーザーが画像を共有したりする場合は、アプリでこれらの画像の印刷を可能にすることを検討してください。 Androidサポートライブラリ <スパン 最小限のコードとシンプルな印刷レイアウトオプションで、画像印刷を可能にする便利な機能を提供します。

このセクションでは、v4サポートライブラリの使用方法を紹介します。 PrintHelper <スパン クラス印刷イメージです。

AndroidサポートライブラリPrintHelperクラスは、画像を印刷するためのシンプルな方法を提供します。このクラスは、以下のようなレイアウトオプションを1つだけ持っています。 setScaleMode() で、2つのオプションのうち1つを表示することができます。
SCALE_MODE_FIT
<スパン - このオプションは、画像全体がページの印刷可能領域内に表示されるように、画像のサイズを変更します。
スケールモードフィル - このオプションは、ページの印刷可能領域全体を埋めるように画像を拡大縮小します。この設定を選択すると、画像の上下や左右の端の一部が印刷されなくなります。スケーリングモードが設定されていない場合、このオプションがデフォルトとなります。
setScaleMode()スケーリングオプションは、画像の既存のアスペクト比を変更しないようにします。以下のコード例では、PrintHelperクラスのインスタンスを作成し、スケーリングオプションを設定し、印刷処理を開始する方法を示しています。

private void doPhotoPrint() {
    PrintHelper photoPrinter = new PrintHelper(getActivity());
    photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.droids);
    photoPrinter.printBitmap("droids.jpg - test print", bitmap);
}

このメソッドは、メニュー項目操作と呼ぶことができる。 常にサポートされていない操作(印刷など)のメニュー項目は、オーバーフローメニューに配置することに注意してください . 詳しくは アクションバー デザインガイドです。
printBitmap()メソッドを呼び出した後、アプリケーションからそれ以上のアクションを実行する必要はありません。Android Print UIが表示され、ユーザーはプリンターと印刷オプションを選択することができます。その後、ユーザーは画像を印刷するか、操作をキャンセルすることができます。ユーザーが画像の印刷を選択した場合、印刷ジョブが作成され、システムバーに印刷通知が表示されます。
画像以外のものを印刷物に含める場合は、印刷用ドキュメントを作成する必要があります。印刷用ドキュメントの作成については、下にスクロールしてください。

2: HTMLドキュメントを印刷する

<スパン Androidで単純な写真以外の印刷を行うには、印刷文書にテキストやグラフィックを合成する必要があります。Androidフレームワークでは、HTMLを使って文書を記述し、最小限のコードで印刷する方法が用意されています。


Android 4.4 (APIレベル19) <スパン で ウェブビュー クラスが更新され、印刷が可能になりました HTML のコンテンツがあります。このクラスは、ローカルのHTMLリソースを読み込んだり、ウェブからページをダウンロードしたり、印刷ジョブを作成してAndroidの印刷サービスに渡したりすることができます。
を使用して、テキストとグラフィックスを含む HTML ドキュメントをすばやく構築する方法を紹介します。 WebView 印刷を実行する。

<スパン 1. HTMLドキュメントを読み込む

WebView を使って HTML 文書を印刷する場合、HTML リソースを読み込んだり、HTML 文書を文字列として構築する必要があります。このセクションでは、HTML 文字列を構築し、それを WebView に読み込んで印刷する方法について説明します。
このビューオブジェクトは、通常、アクティブレイアウトの一部として使用されます。しかし、アプリケーションが WebView を使用しない場合、印刷用に特別にこのクラスのインスタンスを作成することができます。このカスタム印刷ビューを作成するための主な手順は、以下のとおりです。
(1) HTMLリソースを読み込んだ後に開始する印刷ジョブを作成する
WebViewClient .
(2)HTMLリソースを
WebView オブジェクトを作成します。
次のコード例では、単純な WebViewClient を作成し、動的に作成された HTML 文書を読み込む方法を示しています。

<スパン

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 = "

テストコンテンツ

テスト、"。

+             "testing, testing... ";     webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null);     // Keep a reference to the WebView object until you pass the PrintDocumentAdapter     // to the PrintManager     mWebView = webView; }

注:印刷ジョブを生成するための呼び出しは、前のセクションで作成したWebViewClientの中で行われることを確認してください。 onPageFinished() メソッドを使用します。ページの読み込みが終了するのを待たないと、印刷が不完全になったり、空白になったり、完全に失敗する可能性があります。
注意:上記のサンプルコードでは、WebViewオブジェクトのインスタンスを保持しているため、印刷ジョブが作成されるまでガベージコレクトされません。そのため、印刷ジョブが作成されるまでガベージコレクションは行われません。独自の実装でも同様の処理を行うようにしてください。
ページにグラフィックを含めたい場合は、グラフィックファイルをプロジェクトの
アセット ディレクトリに、そして loadDataWithBaseURL() ベースURLは、次のコード例に示すように、メソッドの最初のパラメーターで指定します。

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

また、新しい要素を追加するために loadUrl() を置き換えるために loadDataWithBaseURL() メソッドを使って、印刷するページを読み込んでいます。

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

WebViewを使用して印刷物を作成する場合、以下の制約に注意する必要があります。
(1) 文書にヘッダーやフッター(ページ番号を含む)を付けることはできません。
<スパン (2)
HTML文書の印刷オプションには、ページ範囲を印刷する機能は含まれていません。例えば、10ページのHTML文書の2ページから4ページまでを印刷することはサポートされていません。
<スパン (3) WebViewのインスタンスは、一度に1つの印刷ジョブしか処理できません。
<スパン (4) CSS の print 属性(horizontal 属性など)を含む HTML 文書はサポートされません。
<スパン (5) HTML文書内でJavaScriptを使用して印刷のトリガーとすることはできません。

注:レイアウトに含まれるWebViewオブジェクトの内容も、ドキュメントが読み込まれた後に印刷することができます。

<スパン よりカスタマイズされた印刷物を作成し、印刷物の内容を完全に制御するには、次のセクションを参照してください。 <スパン カスタムドキュメントを印刷する

<スパン 2. 印刷ジョブを作成する

WebView を作成し、HTML コンテンツを読み込むと、アプリケーションは印刷処理の一部をほぼ終了します。次のステップでは PrintManager プリントアダプターが作成され、最後に印刷ジョブが作成されます。次の例は、これらのステップを実行する方法を示しています。

private void createWebPrintJob(WebView webView) {

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

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

    // Create a print job with name and adapter instance
    String jobName = getString(R.string.app_name) + " Document";
    PrintJob printJob = printManager.print(jobName, printAdapter,
            Builders().build());

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

この例では プリントジョブ アプリケーションで使用するためのPrintJobオブジェクトのインスタンスは必須ではありません。アプリケーションは、処理中の印刷ジョブの進捗を追跡するために、このオブジェクトを使用することができます。このメソッドは、完了、失敗、またはユーザーがキャンセルしたアクションのために、アプリケーションで印刷ジョブのステータスを監視したい場合に便利です。印刷フレームワークは、印刷ジョブのシステム通知を自動的に作成するため、アプリ内通知を作成する必要はありません。

<スパン III: カスタムドキュメントの印刷

<スパン ドローイングアプリケーションやページレイアウトアプリケーションなど、グラフィカルな出力に重点を置くアプリケーションでは、美しい印刷ページを作成することが重要な機能となる場合があります。この場合、画像やHTML文書を印刷するだけでは十分ではありません。このようなアプリケーションの印刷では、フォント、テキストフロー、改ページ、ヘッダー、フッター、グラフィック要素など、ページに表示されるすべての要素を正確に制御する必要があります。

<スパン アプリケーション用に完全にカスタマイズ可能な印刷物を作成するには、先に説明したアプローチよりも多くのプログラミング投資が必要です。印刷フレームワークと通信し、プリンター設定に適応し、ページ要素を描画し、複数ページの印刷を管理するコンポーネントを構築する必要があります。
ここでは、プリントマネージャーとの接続、プリントアダプターの作成、プリントコンテンツの構築について説明します

1. プリントマネージャに接続する

アプリが印刷処理を直接管理する場合、ユーザーから印刷要求を受け取った後の最初のステップは、Android印刷フレームワークに接続し、以下の情報を取得することです。 PrintManager PrintManagerクラスのインスタンスです。このクラスは、印刷ジョブを初期化し、印刷のライフサイクルを開始することができます。次のコード例では、プリントマネージャーを取得し、印刷処理を開始する方法を示しています。

private void doPrint() {
    // Get a PrintManager instance
    PrintManager printManager = (PrintManager) getActivity()
            .getSystemService(Context.PRINT_SERVICE);

    // Set job name, which will be displayed in the print queue
    String jobName = getActivity().getString(R.string.app_name) + " Document";

    // Start a print job, passing in a PrintDocumentAdapter implementation
    // to handle the generation of a print document
    printManager.print(jobName, new MyPrintDocumentAdapter(getActivity()),
            null); //
}

上記のサンプルコードでは、印刷ジョブに名前を付けて PrintDocumentAdapter 印刷のライフサイクルのステップを処理するクラスのインスタンスです。プリントアダプタクラスの実装については、次のセクションで説明します。

<スパン 注意事項 print() このメソッドの最後の引数には PrintAttributes オブジェクトを作成します。このパラメータを使用して、印刷フレームへのヒントを提供したり、過去の印刷サイクルに基づくプリセットオプションを提供して、ユーザーエクスペリエンスを向上させることができます。また、このパラメータを使用して、印刷するコンテンツに適したオプションを設定することもできます。例えば、写真を横向きに印刷する場合は、その向きを設定します。

2. プリントアダプターの作成

<スパン プリントアダプターは、Androidの印刷フレームワークと対話し、印刷プロセスのステップを処理します。このプロセスでは、印刷するドキュメントを作成する前に、ユーザーがプリンターと印刷オプションを選択する必要があります。ユーザーは、異なる出力機能、異なるページサイズ、または異なるページ方向を持つプリンターを選択するため、これらの選択は最終出力に影響を与える可能性があります。これらの選択が行われると、印刷フレームは最終的な出力の準備として、印刷ドキュメントをレイアウトして生成するようアダプタに要求します。ユーザーが印刷ボタンをクリックすると、フレームワークは最終的な印刷ドキュメントを取得し、出力のためにプリントプロバイダに渡します。印刷中、ユーザーは印刷操作をキャンセルすることができるので、プリントアダプターはキャンセル要求を聞き、それに応答する必要があります。
PrintDocumentAdapter この抽象クラスは印刷のライフサイクルを処理するために設計されており、4つの主要なコールバックメソッドを持っています。印刷フレームワークと適切にやり取りするためには、これらのメソッドを印刷アダプタに実装する必要があります。
<スパン (1) オンスタート() - 印刷開始時に一度だけ呼び出される。印刷するデータのスナップショットを取得するなど、アプリケーションで1回だけ実行する準備作業がある場合は、ここで実行します。このメソッドをアダプタに実装する必要はありません。
<スパン (2) onLayout ()
- ユーザーが出力に影響を与える印刷設定(異なるページサイズやページ方向など)を変更するたびに呼び出され、印刷されるページレイアウトを計算する機会をアプリケーションに提供します。最低限、このメソッドは印刷されるドキュメントの予想ページ数を返さなければなりません。
<スパン (3) onWrite ()
- 印刷されたページを印刷するファイルに変換するために呼び出されます。このメソッドは onLayout() 呼び出しの後に1回以上呼び出される。
<スパン (4) onFinish ()
- 印刷処理の終了時に一度だけ呼び出される。もし、アプリケーションに一度だけ実行するティアダウンタスクがある場合は、ここで実行します。このメソッドをアダプタに実装する必要はありません。
プリントアダプタの機能として重要な layout メソッドと write メソッドの実装方法について説明します。
注意: これらのアダプタ・メソッドは、アプリケーションのメイン・スレッドで呼び出されます。実装の中でこれらのメソッドの実行に多くの時間がかかることが予想される場合は、 別のスレッドで実行するように実装してください。たとえば、レイアウトをカプセル化するか、あるいは別のスレッドで呼び出すようにします。
AsyncTask オブジェクト内の印刷文書作成ジョブ

3. 印刷文書情報の算出

PrintDocumentAdapter クラスの実装では、作成されるドキュメントの種類を指定し、印刷ジョブの総ページ数を計算し、印刷されるページのサイズに関する情報を提供できるようにする必要があります。アダプタに onLayout() メソッドを実装し、これらの計算を実行し、印刷サイズに関する情報を提供します。 PrintDocumentInfo クラスは、ページ数やコンテンツの種類など、ジョブの予想される出力に関する情報を表示します。次のコード例は、PrintDocumentAdapter の onLayout() メソッドの基本的な実装を示したものです。

@Override
public void onLayout(PrintAttributes oldAttributes,
                     PrintAttributes newAttributes,
                     CancellationSignal cancellationSignal,
                     LayoutResultCallback callback,
                     Bundle metadata) {
    // Create a new PdfDocument with the requested page attributes
    mPdfDocument = new PrintedPdfDocument(getActivity(), newAttributes);

    // Respond to cancellation request
    if (cancelationSignal.isCancelled() ) {
        callback.onLayoutCancelled();
        return;
    }

    // Compute the expected number of printed pages
    int pages = computePageCount(newAttributes);

    if (pages > 0) {
        // Return print information to print framework
        PrintDocumentInfo info = new PrintDocumentInfo
                .Builder("print_output.pdf")
                .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
                .setPageCount(pages);
                .build();
        // Content layout reflow is complete
        callback.onLayoutFinished(info, true);
    } else {
        // Otherwise report an error to the print framework
        callback.onLayoutFailed("Page count calculation failed.");
    }
}

onLayout()メソッドの実行結果は、完了、キャンセル、失敗(レイアウトの計算が完了できなかった場合)の3つがあります。の呼び出しによって結果を得る必要があります。 PrintDocumentAdapter.LayoutResultCallback オブジェクトの対応するメソッドを使用して、結果のひとつを指定します。

<スパン 注意事項 onLayoutFinished() のメソッドを使用します。 ブーリアン パラメータは、レイアウト内容が前回のリクエスト以降に実際に変更されたかどうかを示します。このパラメータを正しく設定することで、印刷フレームワークが不必要に onWrite() メソッドを使用することで、基本的に以前に書き込まれた印刷ドキュメントをキャッシュし、パフォーマンスを向上させることができます。

onLayout()の主な仕事は、与えられたプリンタプロパティに対して出力されると予想されるページ数を計算することです。この数がどのように計算されるかは、アプリケーションが印刷されるページをどのようにレイアウトするかに大きく依存します。次のコード例では、ページ数が印刷方向によって決定される実装を示しています。

private int computePageCount(PrintAttributes printAttributes) {
    int itemsPerPage = 4; // default item count for portrait mode

    MediaSize pageSize = printAttributes.getMediaSize();
    if (!pageSize.isPortrait()) {
        // Six items per page in landscape orientation
        itemsPerPage = 6;
    }

    // Determine number of print items
    int printItemCount = getPrintItemCount();

    return (int) Math.ceil(printItemCount / itemsPerPage);
}

4. 印刷用ドキュメントファイルの作成

印刷出力をファイルに書き込む必要がある場合、Android 印刷フレームワークは、アプリケーションの PrintDocumentAdapter クラスの onWrite() メソッドを呼び出します。このメソッドのパラメーターは、書き込むべきページと、使用する出力ファイルを指定します。このメソッドの実装は、要求された各ページの内容を複数ページのPDF文書ファイルとしてレンダリングする必要があります。この処理が完了したら、コールバック・オブジェクトの onWriteFinished() メソッドを呼び出します。
注:Android印刷フレームワークは、onLayout()が呼ばれるたびに、onWrite()メソッドを1回以上呼び出すことができます。そのため、印刷内容のレイアウトに変更がない場合は、onLayoutFinished() メソッドの boolean パラメータを false に設定し、印刷文書の不要な書き換えを回避することが重要です。
注:onLayoutFinished() メソッドの boolean パラメータは、レイアウト内容が前回のリクエスト以降に実際に変更されたかどうかを示します。このパラメータを正しく設定すると、印刷フレームワークは不必要な onLayout() メソッドの呼び出しを避けることができ、本質的に以前に書かれた印刷ドキュメントをキャッシュしてパフォーマンスを向上させることができます。
次の例では
PrintedPdfDocument このPDF文書を作成する処理の基本的な仕組みは、クラスの中で

@Override
public void onWrite(final PageRange[] pageRanges,
                    final ParcelFileDescriptor destination,
                    final CancellationSignal cancellationSignal,
                    final WriteResultCallback callback) {
    // Iterate over each page of the document,
    // check if it's in the output range.
    for (int i = 0; i < totalPages; i++) {
        // Check to see if this page is in the output range.
        if (containsPage(pageRanges, i)) {
            // If so, add it to writtenPagesArray. writtenPagesArray.size()
            // is used to compute the next output page index.
            writtenPagesArray.append(writtenPagesArray.size(), i);
            PdfDocument.Page page = mPdfDocument.startPage(i);

            // check for cancellation
            if (cancelationSignal.isCancelled()) {
                callback.onWriteCancelled();
                mPdfDocument.close();
                mPdfDocument = null;
                return;
            }

            // Draw page content for printing
            drawPage(page);

            // Rendering is complete, so page can be finalized.
            mPdfDocument.finishPage(page);
        }
    }

    // Write PDF document to file
    try {
        mPdfDocument.writeTo(new FileOutputStream(
                destination.getFileDescriptor())));
    } catch (IOException e) {
        callback.onWriteFailed(e.toString());
        return;
    } finally {
        mPdfDocument.close();
        mPdfDocument = null;
    }
    PageRange[] writtenPages = computeWrittenPages();
    // Signal the print framework the document is complete
    callback.onWriteFinished(writtenPages);

    ...
}

この例では、PDFページのコンテンツのレンダリングを drawPage() メソッドで、次のセクションで説明します。
レイアウトと同様、onWrite()メソッドの実行結果は、完了、キャンセル、コンテンツが書き込めなかった場合の失敗の3種類です。PrintDocumentAdapter.WriteResultCallback オブジェクトの適切なメソッドを呼び出して、これらの結果のいずれかを指定する必要があります。
注:印刷用のドキュメントのレンダリングは、リソースを大量に消費する操作になることがあります。アプリケーションのメインユーザーインターフェースのスレッドがブロックされるのを避けるため、ページのレンダリングと書き込み操作を AsyncTask などの別のスレッドで実行することを検討する必要があります。非同期タスクなどの実行スレッドの使用に関する詳細については プロセスおよびスレッド

5. PDFのページ内容を描画する

アプリケーションが印刷を行う場合、アプリケーションがPDF文書を生成し、それをAndroid印刷フレームワークに渡して印刷する必要があります。この目的のために、任意のPDF生成ライブラリを使用することができます。このレッスンでは、PrintedPdfDocumentクラスを使用して、コンテンツに基づいてPDFページを生成する方法について説明します。
PrintedPdfDocument クラスは キャンバス オブジェクトを使用して、アクティブレイアウトに描画するのと同じように、PDF ページに要素を描画します。印刷されたページ上に要素を描画するために、Canvas 描画メソッドを使用することができます。以下のサンプルコードでは、以下のメソッドを使用してPDF文書ページ上にいくつかの簡単な要素を描画する方法を示しています。

<スパン

private void drawPage(PdfDocument.Page page) {
    Canvas canvas = page.getCanvas();

    // units are in points (1/72 of an inch)
    int titleBaseLine = 72;
    int leftMargin = 54;

    Paint paint = new Paint();
    paint.setColor(Color.BLACK);
    paint.setTextSize(36);
    canvas.drawText("Test Title", leftMargin, titleBaseLine, paint);

    paint.setTextSize(11);
    canvas.drawText("Test paragraph", leftMargin, titleBaseLine + 25, paint);

    paint.setColor(Color.BLUE);
    canvas.drawRect(100, 100, 172, 172, paint);
}

Canvasを使ってPDFのページに描画する場合、要素は1/72インチであるポイントで指定します。ページ上の要素の大きさを指定する際は、必ずこの単位を使用してください。描画した要素の位置は、ページの左上隅の0,0から座標系が始まります。
ヒント: Canvas オブジェクトを使用すると、PDF 文書の端に印刷要素を配置できますが、多くのプリンタは物理的な紙の端まで印刷することができません。このタイプのビルドを使用して文書を印刷する場合は、ページの印刷不可能なエッジを考慮するようにしてください。