Android系统打印方案分析

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系统提供的这个打印框架尽管简单,但是接口功能局限,不能实现很多自定义的需求。

LPR/LPD打印协议

LPD全称是Line Printer Daemon Protocol,标准是RFC1179. LPD是一种基于TCP的老式打印机协议,用于作为打印服务器与打印客户端之间的通信协议。 LPD在服务器端默认使用515端口,严格模式下要求TCP请求客户端的端口号为721~731之间。打印请求以Job方式进行管理。 通过LPD可以实现网络打印。有些打印机设备本身采用linux系统,开启了LPD后台服务,可以直接使用LPD协议进行打印。

IPP打印协议

IPP全称是Internet Printing Protocol,标准是RFC2911 IPP基于HTTP实现,比LPD协议更进一步,支持功能更为强大,模型如下:

这里不对IPP协议进行分析,相关介绍参考RFC2911文档。

CUPS打印服务

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打印驱动

Gutenprint 是一个高质量的Ghostscript打印机驱动。最新的Gutenprint 5.2.13版本已经支持了本人手头的canon打印机型号。 Gutenprint也可以为CUPS提供打印驱动,其保护大量品牌打印机的PPD及驱动,包括Canon, Epson, Lexmark, Sony, Olympus以及PCL等。 理论上也可以gutenprint也可以通过交叉编译移植到Android上配合CUPS进行工作。

Google云打印

Google提供了一项云打印的服务,可以将自己的打印机注册到Google的服务器上,通过其提供的API,可以实现随时随地使用不同设备客户端进行打印的功能,当然打印机支持Wifi并且能科学上网。

打印机设备商提供SDK

打印机设备商一般会实现自己的打印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

原文发布于微信公众号 - 天天P图攻城狮(ttpic_dev)

原文发表时间:2018-11-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏高性能服务器开发

C++日志系统如何设计

笔者在写作本章节的时候,并不敢把此章节的标题叫做《高性能日志系统的设计》,之所以不敢加上“高性能”三个字的原因是,第一,我的对于日志系统设计知识和经验都来自于学...

5603
来自专栏salesforce零基础学习

salesforce 零基础学习(四十五)Approval Lock & UnLock相关注意事项

我们都知道,当一条记录进入审批流程以后会自动加锁,apex提供Approval类的lock和unlock方法可以让我们使用代码对记录进行加锁和解锁。 项目中遇到...

2738
来自专栏用户画像

第3章 网络设备及其操作系统介绍

C.隔离冲突域 (每个端口都是一个独立的冲突域) D.寻找目的以太网段的最佳路径

1552
来自专栏即时通讯技术

网络编程懒人入门(一):快速理解网络通信协议(上篇)

论坛和群里常会有技术同行打算自已开发IM或者消息推送系统,很多时候连基本的网络编程理论(如网络协议等)都不了解,就贸然定方案、写代码,显得非常盲目且充满技术风险...

1001
来自专栏蓝天

LVS初步

很多人知道LVS,但可能知之不多,希望阅读本文后,能够对LVS有一个基本的感性认识。

743
来自专栏FreeBuf

我是如何黑掉惠普打印机的?

步骤 首先,我有机会测试惠普Officejet Pro系列打印机 其次,我决定测试它的安全性并用本地无线网络连接做一次扫描。 注:所有的安装步骤都是按照惠普说明...

2105
来自专栏linux系统运维

负载均衡集群介绍,LVS介绍, LVS调度算法,LVS NAT模式搭建

1912
来自专栏吴裕超

要不要用gzip优化前端项目

这两天在做项目优化,注意到webpack有一个compression-webpack-plugin插件,可以打包成gzip格式部署到服务器,了解到了GZIP,其...

1K8
来自专栏FreeBuf

Linux设备TCP连接曝高危漏洞:只要接入网络就可能被攻击

一般我们会认为,要确认互联网上的任意两台主机设备是否建立TCP连接通讯,其实并不容易——攻击者如果不在双方的通讯路径中,就更是如此了。另外如果攻击者并不在通讯路...

2858
来自专栏Java进阶

聊聊TCP传输的滑动窗口协议的演进

38110

扫码关注云+社区

领取腾讯云代金券