Android调用系统默认打印机并反射获取打印任务状态

	Android4.4通过PrintManger调用系统默认打印服务的默认打印机进行打印任务,
	并通过反射调用PrintManager的getPrintJob方法获取打印任务状态。
	不说太多,直接上代码。
	第一步,调用系统默认打印机打印任务。
	```
	在这里插入打印代码
	PrintManager printManager = (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
	PrintAttributes attributes = new PrintAttributes.Builder()
                .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
                .build();
    MyPrintAdapter myPrintAdapter = new MyPrintAdapter(bitmap, null);
    PrintJob printJob = printManager.print("print job " + System.currentTimeMillis(), myPrintAdapter, attributes);
	```
	MyPrintAdapter .java
	```
	在这里插入代码片
	public class MyPrintAdapter extends PrintDocumentAdapter {

	    private final Bitmap mBitmap;
	    private final Runnable mCallback;
	    private PdfDocument mPdfDocument;
	    private int mPageWidth = 101 * 65 / 25;
	    private int mPageHeight = 140 * 65 / 25;
	
	    private BitmapProcessor processor;
	
	
	    //TODO 亮度+80,对比度-20
	    public MyPrintAdapter(Bitmap bitmap, Runnable runnable) {
	        this.mBitmap = bitmap;
	        this.mCallback = runnable;
	        );
	
	    }
	
	    @Override
	    public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal,
	                         LayoutResultCallback callback,
	                         Bundle metadata) {
	
	        final Context context = Library.getContext();
	        mPdfDocument = new PrintedPdfDocument(context, newAttributes); //创建可打印PDF文档对象
	
	        if (cancellationSignal.isCanceled()) {
	            callback.onLayoutCancelled();
	            return;
	        }
	
	        PrintDocumentInfo.Builder builder = new PrintDocumentInfo
	                .Builder("print.pdf")
	                .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
	                .setPageCount(1);  //构建文档配置信息
	
	        final PrintDocumentInfo info = builder.build();
	        callback.onLayoutFinished(info, true);
	    }
	
	    @Override
	    public void onWrite(final PageRange[] pageRanges, final ParcelFileDescriptor destination, final CancellationSignal cancellationSignal,
	                        final WriteResultCallback callback) {
	        final PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(
	                mPageWidth,//= (int) (PrintAttributes.MediaSize.NA_INDEX_4X6.getWidthMils() / 1000 * 72 *(135/145.0)),
	                mPageHeight,//= (int) (PrintAttributes.MediaSize.NA_INDEX_4X6.getHeightMils() / 1000 * 72*(135/145.0)),
	                1)
	                .create();
	        PdfDocument.Page page = mPdfDocument.startPage(pageInfo);  //创建新页面
	
	        if (cancellationSignal.isCanceled()) {  //取消信号
	            callback.onWriteCancelled();
	            mPdfDocument.close();
	            mPdfDocument = null;
	            return;
	        }
	        drawPage(page);  //将内容绘制到页面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);
	    }
	
	
	    public void setBitmapProcessor(BitmapProcessor processor) {
	        if (processor != null)
	            this.processor = processor;
	    }
	
	    //页面绘制(渲染)
	    private void drawPage(PdfDocument.Page page) {
	        final Canvas canvas = page.getCanvas();
	        final Bitmap temp = processor
	                .size(mPageWidth, mPageHeight)
	                .apply(mBitmap);
	
	        final Matrix matrix = new Matrix();
	        final Paint paint = new Paint();
	        paint.setAntiAlias(true);
	        if (temp != null && !temp.isRecycled())
	            canvas.drawBitmap(temp, matrix, paint);
	        else
	            Logger.error("bitmap is recycled");
	        try {
	            if (temp != null && !temp.isRecycled()) {
	                temp.recycle();
	            }
	        } catch (Exception e) {
	
	        }
	    }
	
	
	    @Override
	    public void onFinish() {
	        if (mCallback != null)
	            new Thread() {
	                @Override
	                public void run() {
	                    try {
	                        mCallback.run();
	                    } catch (Exception e) {
	                        Logger.debug(e);
	                    }
	                }
	            }.start();
	        super.onFinish();
	    }
	}
	```
	在这里,调用打印任务的方法大概就是这样。

	第二步,获取打印任务状态
	使用调用任务返回的PrintJob参数,通过调用PrintManager类的getPrintJob方法获取打印状态。
	我们查看PrintManager的源代码可以看到PrintManager.java里面的getPrintJob方法是hide的,
	需要的参数类型是PrintJobId,返回值为PrintJob
	
	```
	在这里插入代码片
	/**
     * Gets a print job given its id.
     * 
     * @return The print job list.
     * @see PrintJob
     * @hide
     */
    public PrintJob getPrintJob(PrintJobId printJobId) {
        try {
            PrintJobInfo printJob = mService.getPrintJobInfo(printJobId, mAppId, mUserId);
            if (printJob != null) {
                return new PrintJob(printJob, this);
            }
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error getting print job", re);
        }
        return null;
    }
	```
	接下来我们通过反射取调用这个方法。
	

		```
			try {
                Class<?> c = PrintManager.class;
                Method getPrintJob = c.getDeclaredMethod("getPrintJob", PrintJobId.class);
                if (getPrintJob != null) {
                    getPrintJob.setAccessible(true);
                    //这里使用的printJobId为开始打印任务是的返回值	PrintJob.getId()
                    PrintJob printJobState = (PrintJob) (getPrintJob.invoke(printManager, printJobId)); 
                    Log.e("Printer", "printJob--" + printJobState.getInfo().toString());
                    if (printJobState.isCompleted()) {
                        Log.e("Printer", "printJob--complete");
                    } else if (printJobState.isFailed()) {
                            Log.e("Printer", "printJob--printFail");
                    }else if(printJobState.isCancelled()){
                        Log.e("Printer", "printJob--cancel");
                    }else if(!printJobState.isStarted()){
                        waitCount++;
                        if (waitCount>30){
                            isComplete = true;
                            onPrintListener.printFail();
                            printJobState.cancel();
                            Log.e("Printer", "printJob--not statrt");
                        }
                    }
                }
                Thread.sleep(2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
	```
	这样就可以根据项目的实际情况来处理打印任务状态了。

	这样就实现了调用系统打印服务了,但是这种方法有一个缺点,就是它实际上调用了系统默认的一个打印页面,需要人为的选择打印机去确认打印,这种方式有些场景可能不太合适,下一篇文章我将介绍如何自定义一个打印服务去实现后台打印(注意,这种情况是需要选择固定名称的打印机)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值