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();
}
```
这样就可以根据项目的实际情况来处理打印任务状态了。
这样就实现了调用系统打印服务了,但是这种方法有一个缺点,就是它实际上调用了系统默认的一个打印页面,需要人为的选择打印机去确认打印,这种方式有些场景可能不太合适,下一篇文章我将介绍如何自定义一个打印服务去实现后台打印(注意,这种情况是需要选择固定名称的打印机)。
Android调用系统默认打印机并反射获取打印任务状态
最新推荐文章于 2026-04-23 03:42:02 发布
博客围绕Android打印展开,但具体内容缺失。推测可能涉及Android系统下打印功能的实现、相关技术等信息技术方面内容。

2045

被折叠的 条评论
为什么被折叠?



