Android系统上部署usb打印机

一、综述

android系统现多用于手持设备,为手机等设备应用提供了很好的系统级支持。但对于PC机常用的打印功能,android到目前并不支持,也没有打印机厂家专门为android设备做打印机驱动。因此在android上实现usb打印功能有一点繁琐。本文提供了androidjava应用程序实现usb打印的一种方案。这个方案在android系统中打开了一条实现usb打印的从上层应用到内核配置的通路。

由于android系统使用linux内核,而很多打印机都有在linux下的驱动,因此本文采用移植linux下相关开源驱动的方式实现android系统上的usb打印功能。本方案涉及到linux内核配置、linux下的两个自由软件ghostscriptfoo2zjs的移植、iTextandroid程序中的应用,java应用程序调用ghostscriptfoo2zjs

二、Linux打印原理

  Linux系统上的打印原理如下(注:图片来自http://www.linuxidc.com):

  各种类型的文档经由一个(或一些)转换程序转换成用户正在使用的打印机可以认识的格式,即用各种类型的打印机语言描述的流,系统将这个流直接发送到打印机端口,由打印机对其进行解释并形成硬拷贝。

  目前大多数Linux系统以下面的流程来实现文档到打印机语言的转换注:图片来自http://www.linuxidc.com

  普通文本文件和各种类型的图形由适当的转换程序转换成PostScript文件,有些应用程序将其输出直接写成PostScript文件,这些PostScript文件经由一个作为打印机过滤器的应用程序Ghostscript转换成打印机语言。因此,如果系统的打印系统已经配置成使用Ghostsript作为打印过滤器,应用程序要实现的就是输出合乎程序要求和语法的PostScript文件。

      三、使用工具介绍

  1. Ghostscript简介

      Ghostscript是一套Adobe系统的PostScriptPDF页面描述语言的解释器,是一款免费软件。Ghostscript可打开PostscriptPDF格式文件,并可将其转换成其他格式。Gs多用于将PostscriptPDF格式文件转换成为打印机语言文件。

  2. Foo2zjs简介

          Foo2zjslinux下的一个通用打印程序,支持多种型号的打印机。foo2zjs包提供多个驱动,如foo2zjsfoo2hpfoo2lavafoo2xqx等,它们分别支持一系列打印机。在foo2zjs根目录下的README文件中详细说明了它所支持的打印机型号。

  3. Itext简介

      iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDFrtf的文档,而且可以将XMLHtml文件转化为PDF文件。

      四、Android系统的打印实现

      Android系统采用linux内核,因此完全可以根据Linux打印原理搭建一套打印系统。据此,作者配置内核支持USB打印,将Ghostscript移植到android下,结合linuxcat命令,搭建了一套打印系统,实现了使用USB打印机打印PostScript或PDF文档的功能。为了能在java程序中生成PDF文档,需要使用iText.jar包作为从普通文本图形到PDF文档的转换程序,后面会介绍iTextandroid程序中的使用。

      作者发现,在linux命令行下测试打印过程用cat命令向打印机发送过滤后的打印机语言文件时,等待时间约为10秒甚至更长。如果用android上层java软件调用打印功能,又会多用几秒时间。后面增加的这部分时间是android系统启动服务产生的,我们无法避免,而且这段时间主要是开机后第一次启动打印功能时才比较长,一但后台服务启动完成,之后的使用会消耗较短的时间了。

        为了减少整体消耗时间,作者将cat命令换成了foo2zjsfoo2xqx。在linux命令行下测试打印过程,原来的10秒甚至更长缩为1秒左右,用android上层java软件调用打印功能,也就56秒等待时间。

      五、部署过程

  1. 内核配置

    配置内核支持USB打印。

 makemenuconfig -->Device Drivers -->USB Support -->USB Printersupport

这里要强调一点,配置完内核后,将内核编译并更新到开发板,运行。在编译gs等之前,先试试驱动是否配置成功。有的朋友都把后面的完成了,因为这里卡住了。首先,不要忘记mknod一个打印机对应的节点,对USB打印机,linux提供的主设备号是180,子设备号是0-15,字符型设备。比如mknod /dev/lp0 c 180 0。然后连上打印机,可以用命令 “echo abc> /dev/lp0”测试,只要打印机有响应就行,不用管打印格式。

  1. 移植ghostscript

因为Android没有glib库,为了使程序能在开发板上运行,我们自己的C程序需要采用静态编译。

  • 获取源代码

ghostscript的下载地址为http://downloads.ghostscript.com/public/。我用的是ghostscript-9.04

解压ghostscript-9.04.tar.gz,并将解压后的ghostscript-9.04目录拷贝成ghostscript-9.04-pcghostscript-9.04-arm两分,分别用于编译PC主机上的gsarm-linux上的gs

命令:

$ tarzxvf ghostscript-9.04.tar.gz

$ cpghostscript-9.04 ghostscript-9.04-pc -R

$ mvghostscript-9.04 ghostscript-9.04-arm

  • 编译

$ tarzxvf ghostscript-9.04.tar.gz

$ cd ghostscript-9.04

$ ./configure--host=arm-linux

修改Makefile

320行:修改STDLIBS=-lpthread-lm

STDLIBS=-lpthread-lm -static

387行:修改CCAUX=arm-linux-gcc

CCAUX=gcc

$ make



  1. 移植foo2zjs(foo2xqx)

$ wget-O foo2zjs.tar.gz http://foo2zjs.rkkda.com/foo2zjs.tar.gz

$ tarzxf foo2zjs.tar.gz

$ cdfoo2zjs

$ geditMakefile

Makefile文件最开始插入下面两行,分别用于指定编译工具和指定静态链接:

 CC=arm-linux-gcc

 CFLAGS+= -static

 $ exportPATH=$PATH:/opt/FriendlyARM/toolschain/4.5.1/bin

 $ make

  1. java程序调用linux命令行方法

publicclass linux_cmd {

publicstatic String execute(String cmd)

{

ProcessBuilder pb =new ProcessBuilder("/system/bin/sh");

String str=new String();

pb.directory(newFile("/"));//设置shell的当前目录。

try{

Processproc = pb.start();

//获取输入流,可以通过它获取SHELL的输出。

BufferedReaderin =new BufferedReader(newInputStreamReader(proc.getInputStream()));

BufferedReadererr =new BufferedReader(newInputStreamReader(proc.getErrorStream()));

//获取输出流,可以通过它向SHELL发送命令。

PrintWriterout =new PrintWriter(new BufferedWriter(newOutputStreamWriter(proc

.getOutputStream())),true);

out.println(cmd);

out.println("exit");

Stringline;

while((line = in.readLine()) !=null) {

str+=line;

}

while((line = err.readLine()) !=null) {

System.out.println(line); //打印错误输出结果

str+=line;

}

in.close();

out.close();

proc.destroy();

}catch (Exception e) {

System.out.println("exception:"+ e);

}

returnstr;

}

}

  1. Androidjava中使用iText的方法。

      iText的安装非常方便,在http://itextpdf.com/网站上下载iText.jar文件后,只需要在系统的CLASSPATH中加入iText.jar的路径,或将iText.jar添加到java工程中,就可以使用iText类库了。

  • 在工程中添加iText源文件

  右击项目-->New-->SourceFolder (取名itext)-->右击itext-->import-->General-->ArchiveFile-->Next-->Browse(添加 itextpdf-5.1.2-sources.jaritext-xtra-5.1.2-sources.jar-->Finish

  • 在工程中添加iText需要的库(jar包)

  右击项目-->BuildPath -->Add Libraries -->User Library--> Next -->右侧按钮UserLibraries... -->New (新建,名字为lib_for_android_iText-->AddJARs(添加所需要jar)-->OK-->Finish

  iText所依赖的jar包有:

bcmail-jdk16-1.38.jar

bcprov-jdk16-1.38.jar

bctsp-jdk16-1.38.jar

awt-jdk16-1.38.jar

imageio-jdk16-1.38.jar

  其中bcmail-jdk16-1.38.jarbcprov-jdk16-1.38.jarbctsp-jdk16-1.38.jar是从网上下载的,awt-jdk16-1.38.jarimageio-jdk16-1.38.jar是用JDK1.6jre/lib/rt.jar中的java/awtjavax/imageio自己制作的.AndroidSDK中googlesun的类库做了大量修改,awtimageio这两个库就被裁剪掉了。

  • 使用iText生成PDF文件

  voidMakePDF(String fileName,String data,Font font)throwsFileNotFoundException, DocumentException

{

linux_cmd.execute("touch"+fileName);//不存在时创建

Documentdocument =new Document();

FileOutputStreamstream=new FileOutputStream(fileName);

PdfWriter.getInstance(document,stream);

document.open();

Paragraphpar =new Paragraph(data,font);

document.add(par);

document.close();

}

  • 使用中文字体文件

  以使用simfang.ttf为例。在window下找到font文件夹下的simfang.ttf文件(或下载),将它放在android系统的/system/fonts/路径下,就可以使用它将中文字符写入PDF了。Java代码如下:

  StringnameBase="/system/fonts/simfang.ttf";

String encoding=BaseFont.IDENTITY_H;

BaseFont bfChinese = BaseFont.createFont(nameBase, encoding,false);

Font fontChinese =newFont(bfChinese, 25, Font.NORMAL);

  • 打印测试

    将编译好的新内核、gsfoo2xqx下载到开发板如果没有/dev/lp0 节点,需要用mknod命令生成一个:mknod /dev/lp0 c 180 0

    StringfileName=“/var/Hello.PDF”;

Stringdata=”我的第一个打印测试”;

MakePDF(fileName,data,fontChinese)

    Stringcmd="gs -q -dBATCH -dSAFER -dQUIET -dNOPAUSE -sPAPERSIZE=letter-r1200x600 -sDEVICE=pbmraw -sOutputFile=- - < "

+fileName+" | foo2xqx -r1200x600 -g10200x6600 -p1 >/dev/lp0";

linux_cmd.execute(cmd);



注:本文提出的思路并不完善,因为通用性不是很好,支持的文件格式比较少,而且并非以后台服务的方式提供打印功能。如果大家有兴趣,请参考关于linux打印更详细的资料

更多相关文章

  1. NPM 和webpack 的基础使用
  2. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  3. Unity5与Android交互通信(使用Android(安卓)Studio2.4) 详细操作一
  4. Android(安卓)项目在Eclipse中的目录结构
  5. Android命令行下运行JAVA程序之StatusBar控制
  6. Android(安卓)资源(resource)学习小结
  7. Android(安卓)系统log抓取,实现原理分析
  8. Android(安卓)NDK编程入门笔记
  9. android init进程说明

随机推荐

  1. 接口之命令模式
  2. 如何在2D阵列中找到局部最小值?
  3. Java中累计时间的计算(以小时为最终结果)
  4. Java读取Unicode文件(UTF-8等)时碰到的BOM
  5. java类与对象,用程序解释
  6. idea配置完tomcat启动键为什么还是灰的
  7. java数组的拷贝四种方法:for、clone、Syst
  8. “java.exe”已退出,代码为 1。
  9. 经典算法问题的java实现
  10. java高并发测试实例(精确到几百纳秒)