18、ESC/POS指令集在android设备上使用实例(通过socket)

网上关于通过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、套入模板,打印小票

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

  1 package com;
  2
  3
  4
  5 public class printerCmdUtils {
  6
  7     public static final byte ESC = 27;//换码
  8     public static final byte FS = 28;//文本分隔符
  9     public static final byte GS = 29;//组分隔符
 10     public static final byte DLE = 16;//数据连接换码
 11     public static final byte EOT = 4;//传输结束
 12     public static final byte ENQ = 5;//询问字符
 13     public static final byte SP = 32;//空格
 14     public static final byte HT = 9;//横向列表
 15     public static final byte LF = 10;//打印并换行(水平定位)
 16     public static final byte CR = 13;//归位键
 17     public static final byte FF = 12;//走纸控制(打印并回到标准模式(在页模式下) )
 18     public static final byte CAN = 24;//作废(页模式下取消打印数据 )
 19
 20
 21
 22 //------------------------打印机初始化-----------------------------
 23
 24
 25     /**
 26      * 打印机初始化
 27      * @return
 28      */
 29     public static byte[] init_printer()
 30     {
 31         byte[] result = new byte[2];
 32         result[0] = ESC;
 33         result[1] = 64;
 34         return result;
 35     }
 36
 37
 38 //------------------------换行-----------------------------
 39
 40
 41     /**
 42      * 换行
 43      * @param lineNum要换几行
 44      * @return
 45      */
 46     public static byte[] nextLine(int lineNum)
 47     {
 48             byte[] result = new byte[lineNum];
 49             for(int i=0;i<lineNum;i++)
 50             {
 51                 result[i] = LF;
 52             }
 53
 54             return result;
 55     }
 56
 57
 58 //------------------------下划线-----------------------------
 59
 60
 61     /**
 62      * 绘制下划线(1点宽)
 63      * @return
 64      */
 65     public static byte[] underlineWithOneDotWidthOn()
 66     {
 67             byte[] result = new byte[3];
 68         result[0] = ESC;
 69         result[1] = 45;
 70         result[2] = 1;
 71         return result;
 72     }
 73
 74
 75     /**
 76      * 绘制下划线(2点宽)
 77      * @return
 78      */
 79     public static byte[] underlineWithTwoDotWidthOn()
 80     {
 81             byte[] result = new byte[3];
 82         result[0] = ESC;
 83         result[1] = 45;
 84         result[2] = 2;
 85         return result;
 86     }
 87
 88
 89     /**
 90      * 取消绘制下划线
 91      * @return
 92      */
 93     public static byte[] underlineOff()
 94     {
 95             byte[] result = new byte[3];
 96         result[0] = ESC;
 97         result[1] = 45;
 98         result[2] = 0;
 99         return result;
100     }
101
102
103 //------------------------加粗-----------------------------
104
105
106     /**
107      * 选择加粗模式
108      * @return
109      */
110     public static byte[] boldOn()
111     {
112             byte[] result = new byte[3];
113         result[0] = ESC;
114         result[1] = 69;
115         result[2] = 0xF;
116         return result;
117     }
118
119
120     /**
121      * 取消加粗模式
122      * @return
123      */
124     public static byte[] boldOff()
125     {
126             byte[] result = new byte[3];
127         result[0] = ESC;
128         result[1] = 69;
129         result[2] = 0;
130         return result;
131     }
132
133
134 //------------------------对齐-----------------------------
135
136
137     /**
138      * 左对齐
139      * @return
140      */
141     public static byte[] alignLeft()
142     {
143             byte[] result = new byte[3];
144         result[0] = ESC;
145         result[1] = 97;
146         result[2] = 0;
147         return result;
148     }
149
150
151     /**
152      * 居中对齐
153      * @return
154      */
155     public static byte[] alignCenter()
156     {
157             byte[] result = new byte[3];
158         result[0] = ESC;
159         result[1] = 97;
160         result[2] = 1;
161         return result;
162     }
163
164
165     /**
166      * 右对齐
167      * @return
168      */
169     public static byte[] alignRight()
170     {
171             byte[] result = new byte[3];
172         result[0] = ESC;
173         result[1] = 97;
174         result[2] = 2;
175         return result;
176     }
177
178
179     /**
180      * 水平方向向右移动col列
181      * @param col
182      * @return
183      */
184     public static byte[] set_HT_position( byte col )
185     {
186         byte[] result = new byte[4];
187         result[0] = ESC;
188         result[1] = 68;
189         result[2] = col;
190         result[3] = 0;
191         return result;
192     }
193 //------------------------字体变大-----------------------------
194
195
196     /**
197      * 字体变大为标准的n倍
198      * @param num
199      * @return
200      */
201     public static byte[] fontSizeSetBig(int num)
202     {
203             byte realSize = 0;
204             switch (num)
205             {
206             case 1:
207                 realSize = 0;break;
208             case 2:
209                 realSize = 17;break;
210             case 3:
211                 realSize = 34;break;
212             case 4:
213                 realSize = 51;break;
214             case 5:
215                 realSize = 68;break;
216             case 6:
217                 realSize = 85;break;
218             case 7:
219                 realSize = 102;break;
220             case 8:
221                 realSize = 119;break;
222             }
223             byte[] result = new byte[3];
224             result[0] = 29;
225             result[1] = 33;
226             result[2] = realSize;
227             return result;
228     }
229
230
231 //------------------------字体变小-----------------------------
232
233
234     /**
235      * 字体取消倍宽倍高
236      * @param num
237      * @return
238      */
239     public static byte[] fontSizeSetSmall(int num)
240     {
241             byte[] result = new byte[3];
242             result[0] = ESC;
243             result[1] = 33;
244
245         return result;
246     }
247
248
249 //------------------------切纸-----------------------------
250
251
252     /**
253      * 进纸并全部切割
254      * @return
255      */
256     public static byte[] feedPaperCutAll()
257     {
258              byte[] result = new byte[4];
259          result[0] = GS;
260          result[1] = 86;
261          result[2] = 65;
262          result[3] = 0;
263          return result;
264     }
265
266
267     /**
268      * 进纸并切割(左边留一点不切)
269      * @return
270      */
271     public static byte[] feedPaperCutPartial()
272     {
273              byte[] result = new byte[4];
274          result[0] = GS;
275          result[1] = 86;
276          result[2] = 66;
277          result[3] = 0;
278          return result;
279     }
280
281
282 //------------------------切纸-----------------------------
283     public static byte[] byteMerger(byte[] byte_1, byte[] byte_2){
284         byte[] byte_3 = new byte[byte_1.length+byte_2.length];
285         System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
286         System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
287         return byte_3;
288     }
289
290
291     public static byte[] byteMerger(byte[][] byteList){
292
293             int length = 0;
294         for(int i=0;i<byteList.length;i++)
295         {
296                 length += byteList[i].length;
297         }
298         byte[] result = new byte[length];
299
300         int index = 0;
301         for(int i=0;i<byteList.length;i++)
302         {
303                 byte[] nowByte = byteList[i];
304                 for(int k=0;k<byteList[i].length;k++)
305                 {
306                     result[index] = nowByte[k];
307                     index++;
308                 }
309         }
310         for(int i =0;i<index;i++)
311         {
312                 CommonUtils.LogWuwei("", "result["+i+"] is "+result[i]);
313         }
314         return result;
315     }
316
317
318
319 }

工具库包括字体加粗、字体放大缩小、切纸、换行等基本操作,还有就是对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;
    }

字节码拼接过程如下:

 1  public static byte[] byteMerger(byte[][] byteList){
 2
 3             int length = 0;
 4         for(int i=0;i<byteList.length;i++)
 5         {
 6                 length += byteList[i].length;
 7         }
 8         byte[] result = new byte[length];
 9
10         int index = 0;
11         for(int i=0;i<byteList.length;i++)
12         {
13                 byte[] nowByte = byteList[i];
14                 for(int k=0;k<byteList[i].length;k++)
15                 {
16                     result[index] = nowByte[k];
17                     index++;
18                 }
19         }
20         for(int i =0;i<index;i++)
21         {
22                 CommonUtils.LogWuwei("", "result["+i+"] is "+result[i]);
23         }
24         return result;
25     }  

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

1、demo链接地址如下:

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

2、参考文章

Java 实现 POS 打印机无驱打印

java 合并两个byte数组

时间: 2024-10-27 11:57:33

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

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

自:http://game.ceeger.com/forum/read.php?tid=13479 如果你的工程可以以.Net 2.0 subset模式运行,请看这个帖子中的方法. 地址:http://game.ceeger.com/forum/read.php?tid=14359&fid=27 如果只能以.Net 2.0下运行,就可以继续往下看了. ============================================================= protobuf是go

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

http://game.ceeger.com/forum/read.php?tid=13479 如果你的工程可以以.Net 2.0 subset模式运行,请看这个帖子中的方法. 地址:http://game.ceeger.com/forum/read.php?tid=14359&fid=27 如果只能以.Net 2.0下运行,就可以继续往下看了. ============================================================= protobuf是goog

一款Android设备上的智能路由器软件:手机服务站

现在智能电视和盒子的配置越来越高,体验越来越好,那么我们除了用它看看电视电影,打打游戏外,还能干什么呢?它占据着客厅的重要位置,是不是可以做点其他的事情? 例如: 1.用它代替无线路由器给我们的手持设备或笔记本共享网络可以吗? 2.能不能把它做成服务器,用来保存一些不方便或者不需要上传到网络云盘里的文件呢? 3.再或者我想建立一个私人的网站,记录家里的点点滴滴,这些,都可以吗? 4.就算以上都可以做,那我管理起来会不会不方便? 所以,在此向各位推荐一个Android软件来解决以上几个问题,而且还

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

本文主要跟大家分享如何将一台Android设备打造成一个web服务器使用. 编译i-jetty 1.将源码download下来,http://code.google.com/p/i-jetty/downloads/list 2.解压文件,进入pom.xml所在目录,执行命令:mvncleaninstall,参照(http://code.google.com/p/i-jetty/wiki/BuildInstructions) 执行过程中,出现了异常导致失败,是生成classes.dex时内存溢出的

查看Android设备上的分区信息

Android设备上,一般都会存在一块eMMC存储芯片来存放系统和用户数据,甚至部分的引导程序. 一般设备出厂时,各个厂商都会将这块存储芯片分成很多的分区,每个分区内存放不同的内容.具体分区的布局每个厂商或者芯片供应商都会不一样. 可以通过下面的命令来查看目前系统中到底有多少分区:(项目车机上) cat /proc/partitions 如果想知道每个挂载到文件系统上的分区大小和使用情况的信息,可以像普通Linux一样使用:df -h 不过df命令只显示了在文件系统上的挂载点,并没有显示对应的块

在android设备上添加thttpd及CGI

============问题描述============ 我想在android系统上添加一个WEB服务,可以使用pc机上的浏览器对于设备的一些参数进行设置.现在选定 httpd+CGI+Sqlite3.但是不知道怎样将httpd+CGI编译并加载到android系统上.请不吝赐教.谢谢. ============解决方案1============ 请问一下:移动端能使用CGI接口么 ============解决方案2============ 你app上设置设备的参数具体是设置什么参数呀,难道不需

Android设备上opencv开发图像格式

Windows的图像格式和Android移动设备上的图像格式存在差异,使得处理存在一些问题!简单来讲 Camera得到的数据是:YUV,而在移动端设备上显示的数据又是:RGBA, 但是C++程序中处理的数据又是RGB.因此需要做数据的转换.具体的操作示意图如下:                                                             0. 使用前的准备. Camera的使用需要先在AndroidManifest.xml 文件当中加入camera的权

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

网上的帖子很多,但很多都是老版本的,试过了,根本不管用,花了一天时间,终于在本机试验通过了,特记录下来,以备用.有需要的朋友也可以参考.先上一张图,看看PC端chrome上调试的效果: 左边是手机的模拟操作器,右边是大家熟悉的开发人员工具,也可以在手机上操作,PC端左边屏幕会同步到手机上的界面. 下面再说一下环境配置: 1.手机端,我手机是华为荣耀4,android4.4.4,很旧的手机了,大家别笑话,但不影响本次试验.安装chrome版本为58.0.3029.83: 2.PC端,win7 64

在android设备上调试ionic应用

方法1: ionic run android -l -c 将会在console中输出日志信息 方法2: (1).使用usb连接android设备,并打开android设备的调试功能 (2).在chrome浏览器的地址栏中输入 chrome://inspect/#devices,此时会在浏览器中看到连接的设备 (3).点击chrome页面上的inspect按钮,将会弹出开发者模式窗口,可以看到应用程序的日志信息. 如图: