Android Print API
Android默认实现了打印的框架,使用PrintManager+PrintManagerService可以轻松实现打印功能,具体的example可以参考https://developer.android.com/training/printing/index.html
打印功能作为一个feature,在一些定制的Android系统(包括Hikey960)上包括Android TV系统(包括小米盒子和Nvidia Shield),是被裁减掉的。裁减这个功能的系统,系统没有启动PrintManagerService,无法通过Android API访问到打印机设备。 我们可以通过PackageManager的hasSystemFeature方法进行判断系统是否支持print feature:
PackageManager pm = context.getPackageManager();if (!pm.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
Log.i(TAG, "Feature android.software.print not available");
}
实际上,没有PackageManager.FEATURE_PRINTING的系统仍然是可以通过特殊的方式支持打印的。 PackageManagerService中实现hasSystemFeature方法是通过判断feature列表中是否含有这个feature决定的:
这个列表读取的是/sytem/etc/permissions下面的xml文件的feature节点进行添加的:
一般手机中这些xml文件有:
一般没有print feature的系统,是因为没有加入android.software.print.xml这个文件,因此我们只要增加这个文件就可以了(当然这个前提是需要Root权限,可以使用TWRP刷入Recovery并使用SuperSu Root即可,之后还有将System分区以可读可写方式重新挂载mount -o rw,remount /system),文件内容为:
<?xml version="1.0" encoding="utf-8"?><permissions>
<feature name="android.software.print" /></permissions>
增加这个xml文件之后,adb shell “stop && start”重启SystemServer,SystemServer就会默认启动PrintMangerService服务:
系统打印是通过一个系统apk实现的,叫做com.android.printspooler,位置在/system/app/PrintSpooler/中
这个apk的另外一个作用是接收来自用户APP的打印请求。用户APP的打印请求先被PrintManger通过PrintJob方式封装,然后通过Intent唤起PrintSpooler的PrintActivity进行预览。如果打印机设备厂商实现了Print Plugin并提供apk安装到系统,那么PrintSpooler就可以找到对应打印机驱动进行打印。
Android系统提供的这个打印框架尽管简单,但是接口功能局限,不能实现很多自定义的需求。
LPD全称是Line Printer Daemon Protocol,标准是RFC1179. LPD是一种基于TCP的老式打印机协议,用于作为打印服务器与打印客户端之间的通信协议。 LPD在服务器端默认使用515端口,严格模式下要求TCP请求客户端的端口号为721~731之间。打印请求以Job方式进行管理。 通过LPD可以实现网络打印。有些打印机设备本身采用linux系统,开启了LPD后台服务,可以直接使用LPD协议进行打印。
IPP全称是Internet Printing Protocol,标准是RFC2911 IPP基于HTTP实现,比LPD协议更进一步,支持功能更为强大,模型如下:
这里不对IPP协议进行分析,相关介绍参考RFC2911文档。
CUPS(Common Unix Printing System)是苹果公司开发的用于macOS和类Unix系统上的开源打印系统。Github地址:CUPS CUPS功能强大,支持多种打印协议,包括Socket、LPD、IPP等。 CUPS的实现类似编译器,支持多种不同的文档格式打印,它实现了不同的解释器可以将PostScript等文档转换成raster文档格式,然后打印机厂商只需要实现raster接口的打印驱动即可。当然CUPS还实现了LPD/IPP/Socket等协议的后端,便于支持网络打印机。
CUPS默认使用631端口,安装之后会启动一个HTTP Server,通过浏览器访问http://localhost:631能进行CUPS服务管理,包括打印机添加、删除、维护,打印任务的添加、取消等。
以下为macOS上添加的的CUPS打印机列表:
在macOS上安装CUPS之后可以使用CUPS自带的lp/lpr命令创建打印任务,也可以使用其他命令进行打印机和任务管理。
CUPS依赖PPD(PostScript Printer Description)文件来描述打印机,PPD文件描述了打印机的型号、厂商、所需的cups filter驱动程序以及支持的尺寸等信息。比如一个Canon打印机的PPD描述文件部分内容如下:
尽管CUPS功能强大,但是目前很少有移植到Android上的案例,这里有人做过类似的尝试,本人通过这种方式,也成功在ubuntu上交叉编译了cups并在Android上运行起来(由于Android上没有实际使用的canon打印机的cups驱动,因此调试成功手头的打印机):
另外Github上也有人通过busybox将CUPS集成到APK中,但是由于CUPS版本较老,也没有加入新型打印机驱动,并不能兼容新型的打印机。
Gutenprint 是一个高质量的Ghostscript打印机驱动。最新的Gutenprint 5.2.13版本已经支持了本人手头的canon打印机型号。 Gutenprint也可以为CUPS提供打印驱动,其保护大量品牌打印机的PPD及驱动,包括Canon, Epson, Lexmark, Sony, Olympus以及PCL等。 理论上也可以gutenprint也可以通过交叉编译移植到Android上配合CUPS进行工作。
Google提供了一项云打印的服务,可以将自己的打印机注册到Google的服务器上,通过其提供的API,可以实现随时随地使用不同设备客户端进行打印的功能,当然打印机支持Wifi并且能访问外国网站。
打印机设备商一般会实现自己的打印SDK,这些SDK可能基于以上介绍的某些技术实现,比如CUPS。另外厂商会直接提供相关的APP供用户使用,比如Canon的“佳能打印”APP,但是并不能直接作为SDK调用。
另外Android上其他打印方案包括使用一台Linux机器连接打印机,并作为打印服务器,使用Android设备将要打印的文件发送到Linux服务器上进行打印。 如果要实现一些复杂的自定义打印需求,使用打印机设备商提供的SDK是最好的选择。
作者简介:dc, 天天P图AND工程师
文章后记: 天天P图是由腾讯公司开发的业内领先的图像处理,相机美拍的APP。欢迎扫码或搜索关注我们的微信公众号:“天天P图攻城狮”,那上面将陆续公开分享我们的技术实践,期待一起交流学习!
加入我们: 天天P图技术团队长期招聘: (1) AND / iOS 开发工程师 (2) 图像处理算法工程师 期待对我们感兴趣或者有推荐的技术牛人加入我们(base 上海)!联系方式:ttpic_dev@qq.com
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有