Android KitKat Print框架

941 查看

你有没有想过给你的Android应用添加打印的功能?

在Android4.4之前,Android上没有专门为打印提供的API,如果要实现打印的话,只能依赖第三方的解决方案,或者自己实现SMB/CIFS这样的协议,用WIFI、蓝牙或者USB直接和打印机通信。而我们绝大多数人也不会想去直接和打印机通信,一般都是依靠已经存在的方案,这也是最好的选择了。其实,这就是Android新增的功能,可以让打印功能更加简单和可靠。

云打印技术

Google Cloud Print Service最先是在2010年4月对外发布的,GCP是一个基于web的打印机,也是一个可以提供打印功能的管理系统,它能让任何联网设备都可以使用GCP服务来链接任何一台打印机。用户可以为GCP服务添加任何一台打印机,设置是很老式打印机、非云端连接的打印机也是可以的,只需要保证打印机与连接的电脑在web上是共享的,并且装有Google的Chrome。据作者所说,使用GCP是让Android4.4以下的系统支持打印功能的最简单方式。GCP也是我们最希望在Android4.4以上设备上见到的新功能,所以可以开始学习了。点击这里查看资料。

KitKat之前的打印技术

Google云打印技术给开发者提供了一系列API,只要开发者拥有Google认证账号就可以提交打印任务和接收打印任务了。可以从这里下载Google云打印相关的开发资料https://developers.google.com/cloud-print/。本文不会涉及任何实现的细节,因为它有点长,而且帮助不大。还有一点是,用户必须正确设置GCP账号,并和打印机绑定,下面将要介绍两种实现方法。

Google云打印APP

Paulo Fernandes是第一个在APP中使用云打印服务的人,它的Cloud Print应用是第一款使用GCP API来为Android设备提供打印服务的APP。两年后,也就是2013年六月的时候,Google退出了它自己的版本,叫做Google Cloud Print。我会用Google Cloud Print作为例子进行讲解,因为它更流行一些,不过我自己也觉得大多数云打印类APP都差不多。首先,我们需要使用PackageManager这个类来保证Android设备上已经运行了Google Cloud Print服务,可以使用这个函数:

如果设备上装了Google Cloud Print服务的话,我们就可以使用一个Intent来开始打印了:

或者,还可以使用webview调用Google Cloud Print的web接口,这里省略了这部分,这里有一个例子,感兴趣的可以看看完整示例.

在KitKat系统中进行打印

有了这个打印的API,Android上打印就变得更简单、更可靠了。这是它的API的更新列表,以包的形式组织:

Android.support.v4.print

  • PrintHelper – bitmap打印队列工具类。

Android.print

  • PrintDocumentAdapter – 提供自定义打印文档的基础类。
  • PrintManager – 访问打印队列,并提供PrintDocumentAdapter类支持。

Android.print.pdf

  • PrintedPdfDocument – 基于特定PrintAttributeshelper创建PDF。

Android.webkit

  • WebView.createPrintDocumentAdapter – 为WebView打印内容创建PrintDocumentAdapter。

Android.printservice

  • 实现自定义PrintService的容器类。

我们先来看看Android.printservice,这个包里面有与实现自己的打印服务相关的类,Print Service抽象出了与真实打印机(或者其它中间部件如GCP)之间的通信,Google Cloud Print APP就在KitKat上实现了这个服务,所以就可以在GCP上创建打印任务了。关于Print Service的具体实现超出了本文的范围,不过可以关注一下PrintService,它还是挺实用的,它是实现打印所必须的一个类,还有其它需要的相关类稍后就介绍。(需要注意的是:大多数KitKat设备中预装了Google Cloud Print,Chrome,Drive,Gallery还有Quickoffice的,都会提供打印的服务)

接下来要说的是PrintHelper,它也在Android.support.v4.print包下,你可能会想,既然这个类放在Android的兼容包里,那么就可以在老版本的Android上使用打印的功能了。但是很不幸的是,事实不是这样的,PrintHelper这个类有一个静态方法systemSupportsPrint(),从本人进行的测试来看,这个方法只有在KitKat设备中才会返回true。如果在systemSupportPrint()这个方法返回false的设备上调用printBitmap()方法的话,会直接被忽略,不会发生任何事件。现在我们只需要了解为什么PrintHelper这个类会包含在Android的兼容包里面,好像也没有什么用,至少目前还没有什么用处。

不管怎么样,PrintHelper这个类在KitKat中进行打印操作还是很实用的,它提供了简单,直接的方式来打印图片。

  • 可以指定图片的缩放模式,FILT或者FIT模式,FILT模式会用给出的图片填充整个区域,并保持整体比例不变,可能会有裁剪。FIT模式会水平填充或者垂直填充,这取决于文档或者图片的尺寸,它也会保持整体的比例,但是不会裁剪,所以可能会出现空白区域,除非图片的比例和要打印的文档的比例正好合适。
  • 可以指定颜色模式,COLOR或者MONOCHROME。

还有一个很实用的新增方法叫createPrintDocumentAdapter(),为webview准备的。这个方法会和PrintManager一起使用,让打印webview的内容更加简单。

在打印webview的内容时,还需要注意的是:

  • 使用者不能指定打印的页面范围,所以只能打印整个文档。
  • PrintDocumentAdapter在被Webview创建的时候,只能提供当前载入的内容,如果文档没加载完毕,或者中途又加载了别的文档,那么可能会导致不可预料的结果,或者PrintDocumentAdapter会加载失败。
  • 一个webview实例一次只能处理一个打印任务。

PrintManager这个类只有两个公开的方法:getPrintJobs()和print()方法。getPrintJobs()方法会返回一个PrintJob类型的列表,这些PrintJob对象由应用调用。PrintJob对象在检测状态或者在取消或者重启打印任务的时候很有用。在打印的时候会创建一个PrintJob对象(带有标题,PrintDocumentAdapter和PrintAttributes),其中PrintAttributes可以让你指定一种颜色模式,媒体尺寸,边距还有分辨率,还有要特别注意这些属性的操作都是由PrintService操作的,用户只是把任务提交而已。而且很有可能很多属性与对应的服务是没有关系的,或者是会被直接忽略掉的。一个简单的例子就是在选择“save as PDF”的时候,就会忽略掉颜色模式这个属性。

最后要看的这个类叫PrintDocumentAdapter。这个类是一个基础类,继承它可以创建自定义的布局和内容。尽管是可以用PrintHelper和Bitmap类来轻松对绘制的内容进行打印,但是PrintDocumentAdapter在布局和属性上更加灵活,在实现PrintDocumentAdapter的时候,有两个可选的方法和两个必须的方法,可选的方法是onStart()onFinish(),在分配和释放资源的时候会需要这两个方法。首先要看的一个必须的方法叫onLayout(),在PrintAttribute改变的时候就会调用这个方法,这个方法的主要目的就是为了创建PrintDocumentInfo对象,用于描述所打印的内容,和调用LayoutResultCallback对象里的一个方法(有三个方法)。这也是创建PrintedPdfDocument对象最好的地方,所以就可以往里面传递相应的打印属性。