网上关于通过android来操作打印机的例子太少了,为了方便更多的开发同仁,将近日所学分享一下。

我这边是通过android设备通过无线来对打印机(佳博58mm热敏式-58130iC)操作,实现餐厅小票的打印。写了一个简单的小demo,分享下。

前提:

1、android设备一个(coolPad8085N)

2、小票打印机(佳博 58mm热敏式打印机-58130IC)

这里将打印机IP设置为固定IP(这里略微复杂,是前辈设置过的,我没有具体操作,问了一下:打印机自检出的条子可以显示IP、通过自带或者官网的window管理软件设置)

3、无线路由器一个(从局域网口引出一根网线接到小票打印机网口)

4、android设备连接wifi到同一网络

(这样就保证了android和打印机在同一网络内,并且打印机的IP是固定的,开发人员是知道的,很变态)

流程:

1、android运行app,根据打印机的IP地址和端口号创建套接字socket,得到可写流outputStream

2、根据订单号,获取订单信息(demo是模拟的)

3、套入模板,打印小票

难点在于小票的排版的实现,我做了个工具库,如下:

 package com;

 public class printerCmdUtils {

     public static final byte ESC = 27;//换码
public static final byte FS = 28;//文本分隔符
public static final byte GS = 29;//组分隔符
public static final byte DLE = 16;//数据连接换码
public static final byte EOT = 4;//传输结束
public static final byte ENQ = 5;//询问字符
public static final byte SP = 32;//空格
public static final byte HT = 9;//横向列表
public static final byte LF = 10;//打印并换行(水平定位)
public static final byte CR = 13;//归位键
public static final byte FF = 12;//走纸控制(打印并回到标准模式(在页模式下) )
public static final byte CAN = 24;//作废(页模式下取消打印数据 ) //------------------------打印机初始化----------------------------- /**
* 打印机初始化
* @return
*/
public static byte[] init_printer()
{
byte[] result = new byte[2];
result[0] = ESC;
result[1] = 64;
return result;
} //------------------------换行----------------------------- /**
* 换行
* @param lineNum要换几行
* @return
*/
public static byte[] nextLine(int lineNum)
{
byte[] result = new byte[lineNum];
for(int i=0;i<lineNum;i++)
{
result[i] = LF;
} return result;
} //------------------------下划线----------------------------- /**
* 绘制下划线(1点宽)
* @return
*/
public static byte[] underlineWithOneDotWidthOn()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 45;
result[2] = 1;
return result;
} /**
* 绘制下划线(2点宽)
* @return
*/
public static byte[] underlineWithTwoDotWidthOn()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 45;
result[2] = 2;
return result;
} /**
* 取消绘制下划线
* @return
*/
public static byte[] underlineOff()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 45;
result[2] = 0;
return result;
} //------------------------加粗----------------------------- /**
* 选择加粗模式
* @return
*/
public static byte[] boldOn()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 69;
result[2] = 0xF;
return result;
} /**
* 取消加粗模式
* @return
*/
public static byte[] boldOff()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 69;
result[2] = 0;
return result;
} //------------------------对齐----------------------------- /**
* 左对齐
* @return
*/
public static byte[] alignLeft()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 97;
result[2] = 0;
return result;
} /**
* 居中对齐
* @return
*/
public static byte[] alignCenter()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 97;
result[2] = 1;
return result;
} /**
* 右对齐
* @return
*/
public static byte[] alignRight()
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 97;
result[2] = 2;
return result;
} /**
* 水平方向向右移动col列
* @param col
* @return
*/
public static byte[] set_HT_position( byte col )
{
byte[] result = new byte[4];
result[0] = ESC;
result[1] = 68;
result[2] = col;
result[3] = 0;
return result;
}
//------------------------字体变大----------------------------- /**
* 字体变大为标准的n倍
* @param num
* @return
*/
public static byte[] fontSizeSetBig(int num)
{
byte realSize = 0;
switch (num)
{
case 1:
realSize = 0;break;
case 2:
realSize = 17;break;
case 3:
realSize = 34;break;
case 4:
realSize = 51;break;
case 5:
realSize = 68;break;
case 6:
realSize = 85;break;
case 7:
realSize = 102;break;
case 8:
realSize = 119;break;
}
byte[] result = new byte[3];
result[0] = 29;
result[1] = 33;
result[2] = realSize;
return result;
} //------------------------字体变小----------------------------- /**
* 字体取消倍宽倍高
* @param num
* @return
*/
public static byte[] fontSizeSetSmall(int num)
{
byte[] result = new byte[3];
result[0] = ESC;
result[1] = 33; return result;
} //------------------------切纸----------------------------- /**
* 进纸并全部切割
* @return
*/
public static byte[] feedPaperCutAll()
{
byte[] result = new byte[4];
result[0] = GS;
result[1] = 86;
result[2] = 65;
result[3] = 0;
return result;
} /**
* 进纸并切割(左边留一点不切)
* @return
*/
public static byte[] feedPaperCutPartial()
{
byte[] result = new byte[4];
result[0] = GS;
result[1] = 86;
result[2] = 66;
result[3] = 0;
return result;
} //------------------------切纸-----------------------------
public static byte[] byteMerger(byte[] byte_1, byte[] byte_2){
byte[] byte_3 = new byte[byte_1.length+byte_2.length];
System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
return byte_3;
} public static byte[] byteMerger(byte[][] byteList){ int length = 0;
for(int i=0;i<byteList.length;i++)
{
length += byteList[i].length;
}
byte[] result = new byte[length]; int index = 0;
for(int i=0;i<byteList.length;i++)
{
byte[] nowByte = byteList[i];
for(int k=0;k<byteList[i].length;k++)
{
result[index] = nowByte[k];
index++;
}
}
for(int i =0;i<index;i++)
{
CommonUtils.LogWuwei("", "result["+i+"] is "+result[i]);
}
return result;
} }

工具库包括字体加粗、字体放大缩小、切纸、换行等基本操作,还有就是对byte数组的拼接,byte数组的拼接有很多方式,只实现了一种方式

效果图:

简单的代码解析:

public byte[] clientPaper()
{ try {
byte[] next2Line = printerCmdUtils.nextLine(2);
byte[] title = "出餐单(午餐)**万通中心店".getBytes("gb2312"); byte[] boldOn = printerCmdUtils.boldOn();
byte[] fontSize2Big = printerCmdUtils.fontSizeSetBig(3);
byte[] center= printerCmdUtils.alignCenter();
byte[] Focus = "网 507".getBytes("gb2312");
byte[] boldOff = printerCmdUtils.boldOff();
byte[] fontSize2Small = printerCmdUtils.fontSizeSetSmall(3); byte[] left= printerCmdUtils.alignLeft();
byte[] orderSerinum = "订单编号:11234".getBytes("gb2312");
boldOn = printerCmdUtils.boldOn();
byte[] fontSize1Big = printerCmdUtils.fontSizeSetBig(2);
byte[] FocusOrderContent = "韭菜鸡蛋饺子-小份(单)".getBytes("gb2312");
boldOff = printerCmdUtils.boldOff();
byte[] fontSize1Small = printerCmdUtils.fontSizeSetSmall(2); next2Line = printerCmdUtils.nextLine(2); byte[] priceInfo = "应收:22元 优惠:2.5元 ".getBytes("gb2312");
byte[] nextLine = printerCmdUtils.nextLine(1); byte[] priceShouldPay = "实收:19.5元".getBytes("gb2312");
nextLine = printerCmdUtils.nextLine(1); byte[] takeTime = "取餐时间:2015-02-13 12:51:59".getBytes("gb2312");
nextLine = printerCmdUtils.nextLine(1);
byte[] setOrderTime = "下单时间:2015-02-13 12:35:15".getBytes("gb2312"); byte[] tips_1 = "微信关注\"**\"自助下单每天免1元".getBytes("gb2312");
nextLine = printerCmdUtils.nextLine(1);
byte[] tips_2 = "饭后点评再奖5毛".getBytes("gb2312");
nextLine = printerCmdUtils.nextLine(1); byte[] breakPartial = printerCmdUtils.feedPaperCutPartial(); byte[][] cmdBytes= {
title,nextLine,
center,boldOn,fontSize2Big,Focus,boldOff,fontSize2Small,next2Line,
left,orderSerinum,nextLine,
center,boldOn,fontSize1Big,FocusOrderContent,boldOff,fontSize1Small,nextLine,
left,next2Line,
priceInfo,nextLine,
priceShouldPay,next2Line,
takeTime,nextLine,
setOrderTime,next2Line,
center,tips_1,nextLine,
center,tips_2,next2Line,
breakPartial
}; return printerCmdUtils.byteMerger(cmdBytes); } catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

字节码拼接过程如下:

  public static byte[] byteMerger(byte[][] byteList){  

             int length = 0;
for(int i=0;i<byteList.length;i++)
{
length += byteList[i].length;
}
byte[] result = new byte[length]; int index = 0;
for(int i=0;i<byteList.length;i++)
{
byte[] nowByte = byteList[i];
for(int k=0;k<byteList[i].length;k++)
{
result[index] = nowByte[k];
index++;
}
}
for(int i =0;i<index;i++)
{
CommonUtils.LogWuwei("", "result["+i+"] is "+result[i]);
}
return result;
}

将上步得到的字节码通过可写流写入套接字,这时小票打印机就会打印对应的内容。

1、demo链接地址如下:

http://pan.baidu.com/s/1eQ9y8mQ

2、参考文章

Java 实现 POS 打印机无驱打印

小票打印机ESC/POS命令集

android 控制POS机图文打印(二)

18、ESC/POS指令集在android设备上使用实例(通过socket)的更多相关文章

  1. 在ios android设备上使用 Protobuf (使用dll方式)

    http://game.ceeger.com/forum/read.php?tid=13479 如果你的工程可以以.Net 2.0 subset模式运行,请看这个帖子中的方法. 地址:http://g ...

  2. (转)在ios android设备上使用 Protobuf (使用dll方式)

    自:http://game.ceeger.com/forum/read.php?tid=13479 如果你的工程可以以.Net 2.0 subset模式运行,请看这个帖子中的方法. 地址:http:/ ...

  3. 非root Android设备上Tcpdump的实现

    通常我们在Android应用中执行某个命令时会使用"Runtime.getRuntime().exec("命令路径")"这种方式,但是当我们执行抓包操作时,使用 ...

  4. 如何查看Android设备上的分区信息

    Android设备上,一般都会存在一块eMMC存储芯片来存放系统和用户数据,甚至部分的引导程序. 一般设备出厂时,各个厂商都会将这块存储芯片分成很多的分区,每个分区内存放不同的内容.具体分区的布局每个 ...

  5. android设备上运行i-jetty服务

    android设备上运行i-jetty服务: 1) i-jetty安装 本人小菜一个,i-jetty源码有好几个文件,不知道怎么运行起来,于是找了一个现成可运行的i-jetty工程(感谢这位同学的分享 ...

  6. Android设备上的逐像素碰撞检测

    介绍 我正在我的Android设备上开发一款游戏,不用说,因为我想要接触到尽可能多的用户,我做到了 省略了硬件加速.因此,我需要编写能够在大多数设备上运行的最快的代码.我从一个简单的表面视图开始 并使 ...

  7. Android设备上i-jetty环境的搭建-手机上的web服务器

    本文主要跟大家分享如何将一台Android设备打造成一个web服务器使用. 编译i-jetty 1.将源码download下来,http://code.google.com/p/i-jetty/dow ...

  8. 如何通过Chrome远程调试android设备上的Web网站

    网上的帖子很多,但很多都是老版本的,试过了,根本不管用,花了一天时间,终于在本机试验通过了,特记录下来,以备用.有需要的朋友也可以参考.先上一张图,看看PC端chrome上调试的效果: 左边是手机的模 ...

  9. 在android设备上调试ionic应用

    方法1: ionic run android -l -c 将会在console中输出日志信息 方法2: (1).使用usb连接android设备,并打开android设备的调试功能 (2).在chro ...

随机推荐

  1. mvc路由设置参数配置类似于url重写

    1.新建的mvc项目中Global.asax 2.在另外一个控制器中的视图中 3. 4.

  2. POJ C程序设计进阶 编程题#3: 发票统计

    来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 有一个小型的报账系统,它有如 ...

  3. 未能加载文件或程序集“Oracle.Web, Version=2.112.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342”或它的某一个依赖项

    当前系统环境描述: Win7x64+VS2012+IIS7 当前情况描述: 发布Web服务,在浏览的时候出现以下问题:未能加载文件或程序集“Oracle.Web, Version=2.112.1.0, ...

  4. 分享:php 上传图片的代码

    转自:http://www.jbxue.com/article/6379.html php 上传图片的代码,很简单,实现了基本的文件类型.文件大小的检测,并实现了基本的水印与缩略功能,比较适合初学的朋 ...

  5. LotusPhp入口文件解析

    LotusPhp也是单入口的框架,可以根据需要开启多个应用实例 例如前台页面可以用index.php作为入口文件,后台可以用admin.php作为入口文件,多个应用实例可以共享应用配置和类库或者根本每 ...

  6. CodeBlocks背景主题的设置

    来自:http://blog.csdn.net/gzshun/article/details/8294305 找了好几个CodeBlocks的背景色,都不太如人意.感觉下面这个还不错,所以转来给大家分 ...

  7. 自定义DatePicker,年月日,不显示其中某几项

    经过源码研究:该结构主要包含三个NumberPicker: private final NumberPicker mDayPicker; private final NumberPicker mMon ...

  8. PHP+MYSQL会员系统的开发实例教程

    本文通过一个简单的实例完成了完整的PHP+MySQL会员系统功能.是非常实用的一个应用.具体实现步骤如下: 一.会员系统的原理: 登陆-->判断-->保持状态(Cookie或Session ...

  9. Delphi 的运算符列表

    分类 运算符 操作 操作数 结果类型 范例 算术运算符 + 加 整数,实数 整数,实数 X + Y - 减 整数,实数 整数,实数 Result - 1 * 乘 整数,实数 整数,实数 P * Int ...

  10. 02-线性结构2 Reversing Linked List

    由于最近学的是线性结构,且因数组需开辟的空间太大.因此这里用的是纯链表实现的这个链表翻转. Given a constant K and a singly linked list L, you are ...