Google 为了支持移动设备打印功能在Android4.4加入了printservice打印框架。既如果你想让你的打印机能够在Android系统上完成打印工作,那么一种可选的方式就是按照Google提供的打印框架来实现相关打印机的各种功能,包括发现打印机、预览、设置打印参数、打印等工作。当然,在Android设备上实现打印功能的技术多种多样,早在Google推出打印框架之前就已经有软件能够让Android设备实现打印功能,比如Mopria,还有诸如将windows设备作为服务器,Android设备将数据发送到Windows,Windows负责将数据发送到具体打印机打印,总之就是要实现和打印机进行消息通信既可完成打印工作。只是Google提供了打印框架后,遵循这个框架可以更方便的实现打印功能,Android用户在使用的时候也更方便而已。
Android提供的打印框架只是一个空架子,只是提供了一种标准的规则而已,并没有实现任何具体的打印功能,打印机厂商在Android上开发自己打印机打印功能的时候,必须自行完善代码流程。如上图,Android打印框架有以下几个重要的概念:
- PrintDocument 代表一个待打印的文件。里面包含了打印机id(也就是这个待打印的文件应该由哪个打印机去完成打印工作),PrintDocumentInfo(framework中打印框架中的类,指待打印文件的详细描述信息,如名称、页数、类型、大小等)。
- PrintDiscoverySession 封装了打印机发现过程中一个打印服务和系统的交互操作。翻译成白话就是:发现具体打印机的动作要自己去写,具体怎么查找打印机Android系统不管,但是你找到了打印机就得告诉Android系统,系统得知道它已经具备了这个打印机的打印能力,在后续诸如用户点击了一张图片右上角的菜单按钮或分析按钮,系统就能显示相关界面,用以告诉用户你这个图片可以用某某打印机打印出来。
- PrintJob 代表一个打印任务。就是当用户已经选择了一个打印机开始了打印工作,但是还没完成,那么这就是一个打印任务,Android还提供了查询任务进度、终止任务等功能。
- PrintService 打印服务的基础类,并且是一个抽象类,任何遵循Android打印框架的打印插件服务都必须实现它。具体实现包括复写onCreatePrinterDiscoverySession 方法以实现发现打印机等功能。
在具体的问题中来分析打印框架的具体实现。
当安装了一个打印插件服务程序后,就可以在Android 设置界面里看到该打印服务,这是如何做到的?
要让自己开发的打印插件服务显示在系统设置菜单里很简单:
- 新建一个类ActPrintService,extends PrintService,必须实现onCreatePrinterDiscoverySession、onRequestCancelPrintJob、onPrintJobQueued三个方法。
- AndroidManifest.xml中配置这个服务类,配置信息如下图
必须指定android:permission="android.permission.BIND_PRINT_SERVICE",否则Android系统会忽略这个打印服务。
必须添加action android:name="android.printservice.PrintService",否则Android系统会忽略这个打印服务。
实际上Android设置在打开扫描插件列表页面的时候会根据以上的条件查找所有满足条件的服务,并认为它们是打印服务,即使我添加的打印服务里所有的实现都是空的。具体代码在framework中的UserState.java中
至于最后一个meta-data,printservice是自定义的xml文件,它指定了一个打印服务所具备的更多能力,这些能力都需要自行开发,具体参数含义见下图:
以上,即使什么都不实现,只是简单的继承PrintService类,配置AndroidManifest,也能在Android系统的设置菜单显示该打印插件应用。
Android系统中的"默认打印服务"程序,实现了什么功能?
默认打印服务程序在Android P中的代码位于packages/services/BuiltInPrintService中,是系统默认集成的打印插件服务。同样的,BuiltInPrintService也遵循Android的打印框架规则,继承PrintService类,并在PrintService类中实现PrintDiscoverySession 去发现打印机,如果发现了具体打印机将将该打印机的信息提交给系统。BuiltInPrintService一启动就会去查找MDNS、P2P类型的打印机:
那么MDNS和P2P类型的打印机具体指什么打印机呢?
MdnsDiscovery这个具体类负责查找mdns类型打印机,代码中的官方注释很简陋:Search the local network for devices advertising IPP print services
同理,P2pDiscovery这个具体类负责查找p2p类型的打印机,代码中的注释:Discover previously-added P2P devices, if any.