Android wifiでプリンタを呼び出す

9477 ワード

Androidはwifiでプリンタを呼び出して画像やドキュメントを印刷することができ、API 19の前にプリンタを呼び出すのはSocket通信で物を印刷するもので、Socketは比較的原始的な通信モードであり、比較的下位層でもあり、一般的にポート接続で任意の2台の機器に接続してデータ伝送や操作を行うことができる.プリンタも例外ではありません.しかし、API 19の後、androidには独自の印刷フレームワークがあり、Kit Kat Printであり、この印刷フレームワークはpdfまたは印刷画像またはドキュメントを直接生成することができ、ここでのドキュメントはwordのようなものを指し、Viewペイントドキュメントを直接操作し、pdfまたは者がwifiを介してプリンタを呼び出して印刷することを生成する.
これはandroidのエッジ技術で、結局これを使うのは多くないので、大まかに言います.
       1.Kit Kat Printという印刷フレームワークは印刷機能のみを提供しており、検索機能も実現していないのか、まったくないのか分からない.私が使っている方法は、まずHp printサービスプラグインをダウンロードすることです.これはモバイル端末のサービスタイプのappで、wifiの下の同じセグメントを検索するプリンタを提供し、インストール後にインタフェースがありません.このプラグインを使用していない場合は、検索中であり、インストールが完了すると、設定中にプリンタのオプションが表示されます.一部の機種では、leX 820などの設定中であり、一部の機種では、Vivoなどの機種ではありませんが、プリンタにスキャンすることができます.
Hp printサービスプラグインは、さまざまなアプリケーションストアで直接探すことができ、簡単に検索できます.
       2.次に、コードがどのように実現されるかについてお話しします.一般的には、画像やドキュメントを印刷します.まず、画像を印刷します.コードは以下の通りです.
private void doPhotoPrint() {
		//  sd   
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS},
                4);

		//    
        PrintHelper photoPrinter = new PrintHelper(this);
        photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);//       ,         A4          ,    

        //  
        Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/doctor/testprint.jpeg");
        photoPrinter.printBitmap("jpgTestPrint", bitmap);//            jobName
}
には一部の説明が必要です.充填タイプScaleModeは全部で2種類あります.ソースコードの説明は以下の通りです.
    /**
     * image will be scaled but leave white space
     */
    public static final int SCALE_MODE_FIT = 1;

    /**
     * image will fill the paper and be cropped (default)
     */
    public static final int SCALE_MODE_FILL = 2;
はまだ説明がはっきりしていません.説明すると、Fitモードでは、印刷した画像がA 4紙に拡大してすべての画像の内容を表示することができます.Fillモードでは、印刷した画像が、対応するA 4紙のエッジ長と一致するまで、印刷した画像を伸ばします.
また、printBitmapの最初のパラメータは、2回以上印刷する場合は、毎回送信されるパラメータが一致しないことが望ましいので、印刷ミスはありません.
       2.面倒なのはドキュメントを印刷することです.ドキュメントを印刷すると、普段パソコンでドキュメントを印刷するのに適しています.カスタムViewの上に何かを描くのと同じように、印刷方法を先に提示します.
 //print picture in document
private void onPrintDoc(String jobName, String absPicturePath){
	PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
	PrintAttributes.Builder builder = new PrintAttributes.Builder();
	builder.setColorMode(PrintAttributes.COLOR_MODE_COLOR);//      ,      ,   
	builder.setMinMargins(new PrintAttributes.Margins(300, 200, 300, 200));//     ,                    ,   
//  builder.setDuplexMode(DUPLEX_MODE_SHORT_EDGE);//              ,   
	PrintAttributes.MediaSize temp = PrintAttributes.MediaSize.ISO_A4;//          ,  A4,A8 ,   
	temp.asLandscape();
	Log.i("blb", "--------is portrait:" + temp.isPortrait());
	builder.setMediaSize(temp);//      
//  builder.setResolution(new PrintAttributes.Resolution("white", "whiteRadish", 150, 150));//         ,      
	MyPrintAdapter myPrintAdapter = new MyPrintAdapter(this, absPicturePath);
	printManager.print(jobName, myPrintAdapter, builder.build());
}
そんなに多くのパラメータが書かれているのを見て、実は1つも使っていません.hp print serviceはこれらのパラメータ設定を受け入れていないので、設定は何もできません.またプリンタの解像度は300 dpi、600 dpiなど設定できますが、分からない場合は前に書いた画素の変換記事を参考にしてください.
前のは呼び出しの方式で、かばんを案内すればいいので、面倒なことはありません.MyPrintAdapterというものについては自分で書く必要があります.ここでは、androidの中で、adapterの名前のクラスであれば、一般的にはデータを処理したり、返したり、いろいろな中間過程で変換したりする必要があります.このMyPrintAdapterも似ています.まず、サンプルコードを見てみましょう.
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.pdf.PdfDocument;
import android.graphics.pdf.PdfDocument.PageInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo;
import android.print.pdf.PrintedPdfDocument;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by whiteRadish on 2017/6/14.
 */

@TargetApi(Build.VERSION_CODES.KITKAT)
public class MyPrintAdapter extends PrintDocumentAdapter {

    Context mContext;
    private int pageHeight;
    private int pageWidth;
    public PdfDocument myPdfDocument;
    public int totalpages = 1;//         

    public MyPrintAdapter(Context context) {//            
        this.mContext = context;
    }

    @Override
    public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal,
                         LayoutResultCallback callback,
                         Bundle metadata) {

        Log.i("blb", "--------run onLayout");
        myPdfDocument = new PrintedPdfDocument(mContext, newAttributes); //     PDF    

        pageHeight =
                newAttributes.getMediaSize().getHeightMils() / 1000 * 72; //    ,    1000 * 72, 72dpi
        pageWidth =
        newAttributes.getMediaSize().getWidthMils() / 1000 * 72;

        if (totalpages > 0) {
            PrintDocumentInfo.Builder builder = new PrintDocumentInfo
                    .Builder("whiteRadish")
                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
                    .setPageCount(totalpages);  //        

            PrintDocumentInfo info = builder.build();
            callback.onLayoutFinished(info, true);
        } else {
            callback.onLayoutFailed("Page count is zero.");
        }
    }

    @Override
    public void onWrite(final PageRange[] pageRanges, final ParcelFileDescriptor destination, final CancellationSignal cancellationSignal,
                        final WriteResultCallback callback) {

        Log.i("blb", "--------run onWrite");

        for (int i = 0; i < totalpages; i++) {
            if (pageInRange(pageRanges, i)) //      
            {
                PageInfo newPage = new PageInfo.Builder(pageWidth,
                        pageHeight, i).create();//     Page

                PdfDocument.Page page =
                        myPdfDocument.startPage(newPage);  //     

                if (cancellationSignal.isCanceled()) {  //    
                    callback.onWriteCancelled();
                    myPdfDocument.close();
                    myPdfDocument = null;
                    return;
                }
                drawPage(page, i);  //        Canvas 
                myPdfDocument.finishPage(page);
            }
        }

        try {
            myPdfDocument.writeTo(new FileOutputStream(
                    destination.getFileDescriptor()));
        } catch (IOException e) {
            callback.onWriteFailed(e.toString());
            return;
        } finally {
            myPdfDocument.close();
            myPdfDocument = null;
        }

        callback.onWriteFinished(pageRanges);
    }

    private boolean pageInRange(PageRange[] pageRanges, int page) {
        for (int i = 0; i < pageRanges.length; i++) {
            if ((page >= pageRanges[i].getStart()) &&
                    (page <= pageRanges[i].getEnd()))
                return true;
        }
        return false;
    }

    //    
    private void drawPage(PdfDocument.Page page,
                          int pagenumber) {
        Canvas canvas = page.getCanvas();
       
        //     。     0  
        pagenumber++;

        Paint paint = new Paint();

        PageInfo pageInfo = page.getInfo();

        //draw heart rate line
        if (pageWidth > pageHeight){
            drawViewsOnPaper(Canvas canvas, Paint paint);
        }
    }

    //draw views
    private void drawViewsOnPaper(Canvas canvas, Paint paint){
		//              ,        ,  pageHeight,pageWidth    ,         View     ,
		//    View              
    }
}
大まかな説明では、このMyPrintAdapterはPrintDocumentAdapterから継承されています.PrintDocumentAdapterには独自のライフサイクルがあります.このライフサイクルは印刷時の操作に対応しています.必要なパラメータ変数があれば、構造方法で伝えることができます.例えば、Contextを伝えました.あまり使いませんが、彼のライフサイクルはonStart,onLayout,onWrite,onFinishの順で、名前から大体いつ呼び出されるかがわかりますが、startは最初から、layoutのコールバックは印刷プレビューを生成するときにレイアウトされるときのコールバックで、コードが書かれているうちに必要なものを描く必要があります.このときwriteのコールバックは、writeのコールバックでカスタムviewで必要な内容を描けばいいのでfinishは終わりです.このライフサイクルは比較的簡単で、ソースコードを自分で参照してみると大まかな流れがわかります.WriteResultCallBackというコールバックは、物を描くプロセスであり、独自のサイクルもあり、コールバックによってPrintDocumentAdapterの描画に関する結果が失敗したり成功したりすることを通知することができます.残りのコードには説明があります.
ここで厄介な点は、androidは描画時にdpi、またはpxでコンテンツを描画しますが、紙ではcmでコンテンツを描画します.その間に比例変換関係があり、getHeightMilesはmile値を取得します.この値はインチよりも小さい単位で、インチに変換した後、例えばインチに変換すると*72が72 dots per inch、72 dpiになりますが、もちろんもっと高く設定できるので、プリンタの構成に合わせて試してみましょう.
また、携帯電話で印刷するのはパソコンに及ばず、思ったほど速くないので、少し待つ必要があります.
      3.参考の内容は、sdkの下のsourceソースファイルを自分で表示することができ、sdkソースファイルの表示方法、例えばクラスのパッケージ名がpackage androidである.printは、sourceの下にあるandroidフォルダの下にあるprintフォルダに直接行けば見つかります.または公式API、公式APIリンク:http://www.android-doc.com/reference/android/print/PrintDocumentAdapter.html