溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android實(shí)現(xiàn)PDF預(yù)覽打印功能

發(fā)布時(shí)間:2020-09-09 14:51:45 來(lái)源:腳本之家 閱讀:384 作者:guocheng6 欄目:移動(dòng)開(kāi)發(fā)

最近在做一個(gè)項(xiàng)目,需要用到android手機(jī)連接打印機(jī)進(jìn)行打印的功能,目前在網(wǎng)上找到的教程介紹的都是藍(lán)牙連接熱敏打印機(jī)(pos機(jī)大小的打印機(jī))和藍(lán)牙打印機(jī),如果連接日常所見(jiàn)到的網(wǎng)絡(luò)打印機(jī),進(jìn)行打印,很顯然這些教程是做不到的。

由于android沒(méi)有提供任何標(biāo)準(zhǔn),都是自家封的API,參考了WPS的APP的打印功能,決定按照WPS的方案來(lái)寫,需要安裝打印服務(wù)插件,比如PrinterShare以及三星、HP提供的自家打印服務(wù)插件。

一、連接打印管理者

  當(dāng)程序需要直接管理打印進(jìn)程時(shí),在收到用戶的打印請(qǐng)求之后,第一步就是連接Android的打印框架,以及操作PrintManager類的實(shí)例。這個(gè)類允許你實(shí)例化一個(gè)打印工作并開(kāi)始打印的生命過(guò)程。下面的代碼展示了如何獲得一個(gè)打印管理者和啟動(dòng)打印進(jìn)程。

private void onPrintPdf() {
    PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
    PrintAttributes.Builder builder = new PrintAttributes.Builder();
    builder.setColorMode(PrintAttributes.COLOR_MODE_COLOR);
    printManager.print("test pdf print", new MyPrintAdapter(this,filePath), builder.build());
  }

二、創(chuàng)建打印適配器

  打印適配器會(huì)與Android的打印框架相連接,并會(huì)處理打印過(guò)程的每一個(gè)步驟。這個(gè)過(guò)程要求用戶在創(chuàng)建文檔打印之前選擇打印機(jī)及相關(guān)的打印選項(xiàng)。這些過(guò)程會(huì)影響最終的輸出結(jié)果,就像用戶選擇了不同打印能力,不同的頁(yè)面尺寸,不同的頁(yè)面方向一樣。隨著這些選項(xiàng)的設(shè)置,打印框架會(huì)要求適配器展示并生成一個(gè)打印文稿,為最終的打印做準(zhǔn)備。一旦用戶按下了打印按鈕,打印框架會(huì)拿到最終的打印文檔然后交付給打印提供者以便打印。

package com.android.guocheng.printdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.pdf.PdfDocument;
import android.graphics.pdf.PdfDocument.PageInfo;
import android.graphics.pdf.PdfRenderer;
import android.os.Bundle;
import android.os.CancellationSignal;
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 java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by guocheng on 2017/6/13.
 */
public class MyPrintAdapter extends PrintDocumentAdapter {

  private Context context;
  private int pageHeight;
  private int pageWidth;
  private PdfDocument mPdfDocument;
  private int totalpages = 1;
  private String pdfPath;
  private List<Bitmap> mlist;

  public MyPrintAdapter(Context context,String pdfPath) {
    this.context = context;
    this.pdfPath = pdfPath;
  }

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

    mPdfDocument = new PrintedPdfDocument(context, newAttributes); //創(chuàng)建可打印PDF文檔對(duì)象

    pageHeight = newAttributes.getMediaSize().ISO_A4.getHeightMils() * 72 / 1000; //設(shè)置尺寸
    pageWidth = newAttributes.getMediaSize().ISO_A4.getWidthMils() * 72 / 1000;

    if (cancellationSignal.isCanceled()) {
      callback.onLayoutCancelled();
      return;
    }

    ParcelFileDescriptor mFileDescriptor = null;
    PdfRenderer pdfRender = null;
    PdfRenderer.Page page = null;
    try {
      mFileDescriptor = ParcelFileDescriptor.open(new File(pdfPath), ParcelFileDescriptor.MODE_READ_ONLY);
      if (mFileDescriptor != null)
        pdfRender = new PdfRenderer(mFileDescriptor);

      mlist = new ArrayList<>();

      if (pdfRender.getPageCount() > 0) {
        totalpages = pdfRender.getPageCount();
        for (int i = 0; i < pdfRender.getPageCount(); i++) {
          if(null != page)
            page.close();
          page = pdfRender.openPage(i);
          Bitmap bmp = Bitmap.createBitmap(page.getWidth()*2,page.getHeight()*2, Bitmap.Config.ARGB_8888);
          page.render(bmp, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
          mlist.add(bmp);
        }
      }
      if(null != page)
        page.close();
      if(null != mFileDescriptor)
        mFileDescriptor.close();
      if (null != pdfRender)
        pdfRender.close();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }

    if (totalpages > 0) {
      PrintDocumentInfo.Builder builder = new PrintDocumentInfo
          .Builder("快速入門.pdf")
          .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
          .setPageCount(totalpages); //構(gòu)建文檔配置信息

      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) {
    for (int i = 0; i < totalpages; i++) {
      if (pageInRange(pageRanges, i)) //保證頁(yè)碼正確
      {
        PageInfo newPage = new PageInfo.Builder(pageWidth,
            pageHeight, i).create();
        PdfDocument.Page page =
            mPdfDocument.startPage(newPage); //創(chuàng)建新頁(yè)面

        if (cancellationSignal.isCanceled()) { //取消信號(hào)
          callback.onWriteCancelled();
          mPdfDocument.close();
          mPdfDocument = null;
          return;
        }
        drawPage(page, i); //將內(nèi)容繪制到頁(yè)面Canvas上
        mPdfDocument.finishPage(page);
      }
    }

    try {
      mPdfDocument.writeTo(new FileOutputStream(
          destination.getFileDescriptor()));
    } catch (IOException e) {
      callback.onWriteFailed(e.toString());
      return;
    } finally {
      mPdfDocument.close();
      mPdfDocument = 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;
  }

  //頁(yè)面繪制(渲染)
  private void drawPage(PdfDocument.Page page,int pagenumber) {
    Canvas canvas = page.getCanvas();
    if(mlist != null){
      Paint paint = new Paint();
      Bitmap bitmap = mlist.get(pagenumber);
      int bitmapWidth = bitmap.getWidth();
      int bitmapHeight = bitmap.getHeight();
      // 計(jì)算縮放比例
      float scale = (float)pageWidth/(float)bitmapWidth;
      // 取得想要縮放的matrix參數(shù)
      Matrix matrix = new Matrix();
      matrix.postScale(scale, scale);
      canvas.drawBitmap(bitmap,matrix,paint);
    }
  }

}


最后看一下效果圖

Android實(shí)現(xiàn)PDF預(yù)覽打印功能

通過(guò)打印服務(wù)插件添加打印機(jī)就可以進(jìn)行打印了。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI