PrintService类打印
系统打印服务框架代码位于android.printservice
包中。系统并没有实现具体打印功能,需要打印机厂商制作插件接入系统打印服务之后,自行实现
主要类:
PrintDocument:表示待打印文件
PrintDiscoverySession:用于发现打印机和打印机状态更新
PrintJob:代表打印任务
PrintService:接入系统打印Service
打印机发现过程:
当用户在设置里开启你的打印服务插件和进入系统打印服务界面时,系统会调用 PrinterDiscoverySession 里的 onStartPrinterDiscovery(List priorityList) 函数,通知你的插件查找打印机。具体查找方式需要自己实现,可能是查找USB接口,可能是搜索网络。系统只管结果,你通过调用其父类的 addPrinters() 方法将打印机添加进去。打印机是放在List数组里传入。
打印机选择过程
当用户通过一些有打印功能的APP调用系统打印服务时,如果选择了你的插件的打印机,那么系统会调用 PrinterDiscoverySession 里的 onStartPrinterStateTracking(PrinterId printerId) 方法。这里系统主要希望得到打印机的 PrinterCapabilitiesInfo 和状态,里面包括打印机支持的纸张大小,以及色彩等详细功能参数。
打印过程:
当用户在刚刚的系统打印服务界面点击右上角的打印按钮时,系统会调用打印机所属的 PrintService 里的 onPrintJobQueued(PrintJob printJob) 方法,插件需要处理该 PrintJob 。首先需要通过 PrintJob.isQueued() 判断,该PrintJob是否准备好打印,返回true代表可以打印。然后可以通过 PrintJob.getDocument() 获得要打印的文档,这里面的数据可以通过 PrintDocument.getData() 读取。开始打印的时候,调用PrintJob.start()标记开始状态。当打印成功时,调用 PrintJob.complete() 标记打印成功。或者打印失败时,调用 PrintJob.fail( String) 标记失败。
打印服务需要添加的权限:
<uses-permission android:name="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
打印类:
public class MyPrintService extends PrintService { private static final String TAG = "MyPrintService"; @Override protected PrinterDiscoverySession onCreatePrinterDiscoverySession() { Log.d(TAG, "onCreatePrinterDiscoverySession()"); return new MyPrintDiscoverySession(this); } @Override protected void onRequestCancelPrintJob(PrintJob printJob) { Log.d(TAG, "onRequestCancelPrintJob()"); printJob.cancel(); } @Override protected void onPrintJobQueued(PrintJob printJob) { Log.d(TAG, "onPrintJobQueued()"); PrintJobInfo printjobinfo = printJob.getInfo(); PrintDocument printdocument = printJob.getDocument(); if (printJob.isQueued()) { return; } printJob.start(); String filename = "docu.pdf"; File outfile = new File(this.getFilesDir(), filename); outfile.delete(); FileInputStream file = new ParcelFileDescriptor.AutoCloseInputStream(printdocument.getData()); //创建一个长度为1024的内存空间 byte[] bbuf = new byte[1024]; //用于保存实际读取的字节数 int hasRead = 0; //使用循环来重复读取数据 try { FileOutputStream outStream = new FileOutputStream(outfile); while ((hasRead = file.read(bbuf)) > 0) { //将字节数组转换为字符串输出 //System.out.print(new String(bbuf, 0, hasRead)); outStream.write(bbuf); } outStream.close(); } catch (IOException e) { e.printStackTrace(); }finally { //关闭文件输出流,放在finally块里更安全 try { file.close(); } catch (IOException e) { e.printStackTrace(); } } printJob.complete(); } }
PrinterDiscoverySession实现类编写:
public class MyPrintDiscoverySession extends PrinterDiscoverySession { private static final String TAG = "MyPrintDiscoverySession"; private final MyPrintService myPrintService; public MyPrintDiscoverySession(MyPrintService myPrintService) { Log.d(TAG, "MyPrintDiscoverySession()"); this.myPrintService = myPrintService; } @Override public void onStartPrinterDiscovery(List<PrinterId> priorityList) { Log.d(TAG, "onStartPrinterDiscovery()"); List<PrinterInfo> printers = this.getPrinters(); String name = "printer1"; PrinterInfo myprinter = new PrinterInfo .Builder(myPrintService.generatePrinterId(name), name, PrinterInfo.STATUS_IDLE) .build(); printers.add(myprinter); addPrinters(printers); } @Override public void onStopPrinterDiscovery() { Log.d(TAG, "onStopPrinterDiscovery()"); } /** * 确定这些打印机存在 * @param printerIds */ @Override public void onValidatePrinters(List<PrinterId> printerIds) { Log.d(TAG, "onValidatePrinters()"); } /** * 选择打印机时调用该方法更新打印机的状态,能力 * @param printerId */ @Override public void onStartPrinterStateTracking(PrinterId printerId) { Log.d(TAG, "onStartPrinterStateTracking()"); PrinterInfo printer = findPrinterInfo(printerId); if (printer != null) { PrinterCapabilitiesInfo capabilities = new PrinterCapabilitiesInfo.Builder(printerId) .setMinMargins(new PrintAttributes.Margins(200, 200, 200, 200)) .addMediaSize(PrintAttributes.MediaSize.ISO_A4, true) //.addMediaSize(PrintAttributes.MediaSize.ISO_A5, false) .addResolution(new PrintAttributes.Resolution("R1", "200x200", 200, 200), false) .addResolution(new PrintAttributes.Resolution("R2", "300x300", 300, 300), true) .setColorModes(PrintAttributes.COLOR_MODE_COLOR | PrintAttributes.COLOR_MODE_MONOCHROME, PrintAttributes.COLOR_MODE_MONOCHROME) .build(); printer = new PrinterInfo.Builder(printer) .setCapabilities(capabilities) .setStatus(PrinterInfo.STATUS_IDLE) // .setDescription("fake print 1!") .build(); List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); printers.add(printer); addPrinters(printers); } } @Override public void onStopPrinterStateTracking(PrinterId printerId) { Log.d(TAG, "onStopPrinterStateTracking()"); } @Override public void onDestroy() { Log.d(TAG, "onDestroy()"); } private PrinterInfo findPrinterInfo(PrinterId printerId) { List<PrinterInfo> printers = getPrinters(); final int printerCount = getPrinters().size(); for (int i = 0; i < printerCount; i++) { PrinterInfo printer = printers.get(i); if (printer.getId().equals(printerId)) { return printer; } } return null; } }