草庐IT

初探Android系统打印功能

有何不可0307 2023-04-10 原文

在Android平台上对激光打印机和喷墨式打印机进行了连接共享和打印效果测试。并对比Windows平台上的打印测试,分析其中的打印协议,现记录总结如下。

一、网络共享打印机

用户请求打印操作,会产生一个打印任务。系统把这个打印job放在打印队列中,有打印服务器从打印队列中一个个取走。因为打印机是独占设备,每个进程只能一次次的访问打印节点。
打印服务把打印队列中的打job转化成打印机认识的格式,主流是Postscript格式,转化这个工作是由打印机驱动程序来完成的。即打印服务会调用具体的打印机驱动程序。

  • 如何把普通打印机变成网络打印机
  1. 需要两个硬件设备:一个是打印机,一个是作为打印机服务器的主机。若打印机本身带有网络功能,可不用主机,打印机本身就是另一形式的主机。
  2. 需要两层软件设备:一个是打印机驱动(底层用来驱动打印机工作的),一个就是打印机服务器,用来协调用户对打印机的需求,并最终调用打印机驱动进行打印工作。
  • 网络共享测试
  1. 惠普激光式打印机(HP LaserJet Pro P1606dn):使用NP330网络打印服务器,打印机usb线连接NP330,NP330网线连接路由器。

    结果:使用第三方趣打印apk,打印普通pdf正常,打印点阵pdf很慢且效果差,达不到识别标准。

  2. 联想激光式打印机(Lenovo LJ2206W): 使用CentOS系统搭建的CUPS网络打印服务器,打印机usb线连接虚拟机CentOS,虚拟机网络设置成桥接模式。开放防火墙端口631,搭建完毕后局域网内平板可访问http://192.168.3.52:631/printers/

    结果:使用第三方打印apk连接时未找到该设备,主机无法打印,缺少该设备对应的linux驱动。

二、Android系统打印功能

Android默认实现了基于CUPS打印的框架,CUPS可以提供打印协议来让用户使用打印机,提供Web界面让用户设置和管理打印机。

开发者可使用PrintManager+PrintDocumentAdapter 接入系统打印API方式实现打印功能,使用指南请参考:https://developer.android.google.cn/training/printing/custom-docs

  • 打印处理服务PrintSpooler

系统打印通过一个系统apk[包名com.android.printspoole]实现的,源码位置:frameworks/base/packages/PrintSpooler
该apk接收来自用户app的打印请求。用户app的打印请求先被PrintManger通过PrintJob方式封装,然后通过Intent唤起PrintSpooler的PrintActivity进行预览。如果打印机设备厂商实现了Print Plugin并提供apk安装到系统,那么PrintSpooler就可以找到对应打印机驱动进行打印。

  • 默认打印服务BuiltInPrintService

AOSP系统默认集成的打印插件服务,源码位于packages/services/BuiltInPrintService。BuiltInPrintService启动后会去查找MDNS、P2P类型的打印机,如果发现了具体打印机则将该打印机的信息提交给系统,打印处理服务PrintSpooler将会显示该打印机。BuiltInPrintService还包括pdf渲染、处理ipp协议请求等基于CUPS实现的打印服务。其中默认ipp协议端口631,打印分辨率dpi默认300。

三、Android端打印机连接

  • 如何测试连接:
  1. 关于ip连接和端口使用情况,可使用ping命令和nmap工具扫描端口。
  2. Android通过NSD网络发现服务搜索并匹配附近可进行通信的设备。
  3. ping网络助手:https://www.cr173.com/soft/1334119.html
  • 连接测试实验:
  1. 小米喷墨式打印机(Mi All-in-one Inkjek Printer):平板系统打印服务能发现并能连接上IPP,默认使用IPP协议的631端口。

  2. 联想激光式打印机(Lenovo LJ2206W):使用平板默认打印机服务不能显示该打印机,通过log看出平板系统打印服务能发现但IPP请求失败。查看电脑主机连接的打印机属性默认设置的是LPD协议515端口,可设定成RAW协议的9100端口。

四、打印协议分析

分别对Android 10和Windows 10平台连接的小米喷墨打印机打印属性进行设置,对比并分析两个平台的打印协议(主要关注传输层和应用层的协议)。

协议抓包过程:
  • Android端:
  1. 使用米家喷墨打印助手APP,设置该APP打印参数,例如黑白、A4、普通纸、1份、1页、中等质量。
  2. 抓包过程:Android端使用命令抓取特定IP的网络数据包并保存pcap文件:tcpdump -v host 10.10.0.110 -w /sdcard/capture_mi.pcap
  3. 使用Wireshark工具分析pcap文件。
  4. 设置过滤器、筛选列表,以一行报文IPP Request (Create-Job)为例 ,跟踪其数据流。
  • Windows端:
  1. 在Windows 10 web浏览器上设置打印参数:彩色、A4、合适区域大小、1份,双面、600dpi
  2. 点击开始打印时,使用Wireshark工具开始捕获,打印完毕时,停止捕获。
  3. 刷选列表,http、ipp、printer等关键字,跟踪其数据流。
  4. 可保存为pcapng格式文件便于后续分析。

有关初探Android系统打印功能的更多相关文章

  1. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  2. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  3. 电脑0x0000001A蓝屏错误怎么U盘重装系统教学 - 2

      电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。  准备工作:  1、U盘一个(尽量使用8G以上的U盘)。  2、一台正常联网可使用的电脑。  3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。  4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。  U盘启动盘制作步骤:  注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注

  4. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  5. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  6. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  7. ruby - 在没有基准或时间的情况下用 Ruby 测量用户时间或系统时间 - 2

    因为我现在正在做一些时间测量,我想知道是否可以在不使用Benchmark类或命令行实用程序time的情况下测量用户时间或系统时间。使用Time类只显示挂钟时间,而不显示系统和用户时间,但是我正在寻找具有相同灵active的解决方案,例如time=TimeUtility.now#somecodeuser,system,real=TimeUtility.now-time原因是我有点不喜欢Benchmark,因为它不能只返回数字(编辑:我错了-它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。*NIX系统的time实用程序也应该可以解决我的问题,但我想知道是否已经在Ruby中实

  8. ruby - 如何打印 ruby​​ 对象的实例变量 - 2

    classPacketdefinitialize(name,age,number,array)@name=name@age=age@number=number@neighbors=arrayendendp1=Packet.new("n1",5,2,[1,2,3,4])putsp1.name我有上面的代码,但是每当我执行puts语句时,我都会收到nameisnotamethod的错误。我不知道任何其他方式来打印p1的名称。如何打印姓名? 最佳答案 这里的问题是,虽然您拥有实例变量,但您并未使它们可访问。attr_reader:vari

  9. ruby - 以毫秒为单位获取当前系统时间 - 2

    在Ruby中,以毫秒为单位获取自纪元(1970)以来的当前系统时间的正确方法是什么?我试过了Time.now.to_i,好像不是我想要的结果。我需要结果显示毫秒并且使用long类型,而不是float或double。 最佳答案 (Time.now.to_f*1000).to_iTime.now.to_f显示包含十进制数字的时间。要获得毫秒数,只需将时间乘以1000。 关于ruby-以毫秒为单位获取当前系统时间,我们在StackOverflow上找到一个类似的问题:

  10. ruby - 如何打印出 Mechanized 存储的 cookie? - 2

    我正在使用mechanize登录网站,然后检索页面。我遇到了一些问题,我怀疑这是由于cookie中的某些值造成的。当Mechanize登录网站时,我假设它存储了cookie。如何通过Mechanize打印出存储在cookie中的所有数据? 最佳答案 代理有一个cookie方法。agent=Mechanize.newpage=agent.get("http://www.google.com/")agent.cookiesagent.cookies.to_scookie返回一个Mechanize::Cookiesobject

随机推荐