http://www.it165.net/pro/html/201503/35460.html
网上关于通过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、套入模板,打印小票
难点在于小票的排版的实现,我做了个工具库,如下:
001.
1
package
com;
002.
2
003.
3
004.
4
005.
5
public
class
printerCmdUtils {
006.
6
007.
7
public
static
final
byte
ESC =
27
;
//换码
008.
8
public
static
final
byte
FS =
28
;
//文本分隔符
009.
9
public
static
final
byte
GS =
29
;
//组分隔符
010.
10
public
static
final
byte
DLE =
16
;
//数据连接换码
011.
11
public
static
final
byte
EOT =
4
;
//传输结束
012.
12
public
static
final
byte
ENQ =
5
;
//询问字符
013.
13
public
static
final
byte
SP =
32
;
//空格
014.
14
public
static
final
byte
HT =
9
;
//横向列表
015.
15
public
static
final
byte
LF =
10
;
//打印并换行(水平定位)
016.
16
public
static
final
byte
CR =
13
;
//归位键
017.
17
public
static
final
byte
FF =
12
;
//走纸控制(打印并回到标准模式(在页模式下) )
018.
18
public
static
final
byte
CAN =
24
;
//作废(页模式下取消打印数据 )
019.
19
020.
20
021.
21
022.
22
//------------------------打印机初始化-----------------------------
023.
23
024.
24
025.
25
/**
026.
26 * 打印机初始化
027.
27 * @return
028.
28 */
029.
29
public
static
byte
[] init_printer()
030.
30
{
031.
31
byte
[] result =
new
byte
[
2
];
032.
32
result[
0
] = ESC;
033.
33
result[
1
] =
64
;
034.
34
return
result;
035.
35
}
036.
36
037.
37
038.
38
//------------------------换行-----------------------------
039.
39
040.
40
041.
41
/**
042.
42 * 换行
043.
43 * @param lineNum要换几行
044.
44 * @return
045.
45 */
046.
46
public
static
byte
[] nextLine(
int
lineNum)
047.
47
{
048.
48
byte
[] result =
new
byte
[lineNum];
049.
49
for
(
int
i=
0
;i<lineNum;i++)
050.
50
{
051.
51
result[i] = LF;
052.
52
}
053.
53
054.
54
return
result;
055.
55
}
056.
56
057.
57
058.
58
//------------------------下划线-----------------------------
059.
59
060.
60
061.
61
/**
062.
62 * 绘制下划线(1点宽)
063.
63 * @return
064.
64 */
065.
65
public
static
byte
[] underlineWithOneDotWidthOn()
066.
66
{
067.
67
byte
[] result =
new
byte
[
3
];
068.
68
result[
0
] = ESC;
069.
69
result[
1
] =
45
;
070.
70
result[
2
] =
1
;
071.
71
return
result;
072.
72
}
073.
73
074.
74
075.
75
/**
076.
76 * 绘制下划线(2点宽)
077.
77 * @return
078.
78 */
079.
79
public
static
byte
[] underlineWithTwoDotWidthOn()
080.
80
{
081.
81
byte
[] result =
new
byte
[
3
];
082.
82
result[
0
] = ESC;
083.
83
result[
1
] =
45
;
084.
84
result[
2
] =
2
;
085.
85
return
result;
086.
86
}
087.
87
088.
88
089.
89
/**
090.
90 * 取消绘制下划线
091.
91 * @return
092.
92 */
093.
93
public
static
byte
[] underlineOff()
094.
94
{
095.
95
byte
[] result =
new
byte
[
3
];
096.
96
result[
0
] = ESC;
097.
97
result[
1
] =
45
;
098.
98
result[
2
] =
0
;
099.
99
return
result;
100.
100
}
101.
101
102.
102
103.
103
//------------------------加粗-----------------------------
104.
104
105.
105
106.
106
/**
107.
107 * 选择加粗模式
108.
108 * @return
109.
109 */
110.
110
public
static
byte
[] boldOn()
111.
111
{
112.
112
byte
[] result =
new
byte
[
3
];
113.
113
result[
0
] = ESC;
114.
114
result[
1
] =
69
;
115.
115
result[
2
] =
0xF
;
116.
116
return
result;
117.
117
}
118.
118
119.
119
120.
120
/**
121.
121 * 取消加粗模式
122.
122 * @return
123.
123 */
124.
124
public
static
byte
[] boldOff()
125.
125
{
126.
126
byte
[] result =
new
byte
[
3
];
127.
127
result[
0
] = ESC;
128.
128
result[
1
] =
69
;
129.
129
result[
2
] =
0
;
130.
130
return
result;
131.
131
}
132.
132
133.
133
134.
134
//------------------------对齐-----------------------------
135.
135
136.
136
137.
137
/**
138.
138 * 左对齐
139.
139 * @return
140.
140 */
141.
141
public
static
byte
[] alignLeft()
142.
142
{
143.
143
byte
[] result =
new
byte
[
3
];
144.
144
result[
0
] = ESC;
145.
145
result[
1
] =
97
;
146.
146
result[
2
] =
0
;
147.
147
return
result;
148.
148
}
149.
149
150.
150
151.
151
/**
152.
152 * 居中对齐
153.
153 * @return
154.
154 */
155.
155
public
static
byte
[] alignCenter()
156.
156
{
157.
157
byte
[] result =
new
byte
[
3
];
158.
158
result[
0
] = ESC;
159.
159
result[
1
] =
97
;
160.
160
result[
2
] =
1
;
161.
161
return
result;
162.
162
}
163.
163
164.
164
165.
165
/**
166.
166 * 右对齐
167.
167 * @return
168.
168 */
169.
169
public
static
byte
[] alignRight()
170.
170
{
171.
171
byte
[] result =
new
byte
[
3
];
172.
172
result[
0
] = ESC;
173.
173
result[
1
] =
97
;
174.
174
result[
2
] =
2
;
175.
175
return
result;
176.
176
}
177.
177
178.
178
179.
179
/**
180.
180 * 水平方向向右移动col列
181.
181 * @param col
182.
182 * @return
183.
183 */
184.
184
public
static
byte
[] set_HT_position(
byte
col )
185.
185
{
186.
186
byte
[] result =
new
byte
[
4
];
187.
187
result[
0
] = ESC;
188.
188
result[
1
] =
68
;
189.
189
result[
2
] = col;
190.
190
result[
3
] =
0
;
191.
191
return
result;
192.
192
}
193.
193
//------------------------字体变大-----------------------------
194.
194
195.
195
196.
196
/**
197.
197 * 字体变大为标准的n倍
198.
198 * @param num
199.
199 * @return
200.
200 */
201.
201
public
static
byte
[] fontSizeSetBig(
int
num)
202.
202
{
203.
203
byte
realSize =
0
;
204.
204
switch
(num)
205.
205
{
206.
206
case
1
:
207.
207
realSize =
0
;
break
;
208.
208
case
2
:
209.
209
realSize =
17
;
break
;
210.
210
case
3
:
211.
211
realSize =
34
;
break
;
212.
212
case
4
:
213.
213
realSize =
51
;
break
;
214.
214
case
5
:
215.
215
realSize =
68
;
break
;
216.
216
case
6
:
217.
217
realSize =
85
;
break
;
218.
218
case
7
:
219.
219
realSize =
102
;
break
;
220.
220
case
8
:
221.
221
realSize =
119
;
break
;
222.
222
}
223.
223
byte
[] result =
new
byte
[
3
];
224.
224
result[
0
] =
29
;
225.
225
result[
1
] =
33
;
226.
226
result[
2
] = realSize;
227.
227
return
result;
228.
228
}
229.
229
230.
230
231.
231
//------------------------字体变小-----------------------------
232.
232
233.
233
234.
234
/**
235.
235 * 字体取消倍宽倍高
236.
236 * @param num
237.
237 * @return
238.
238 */
239.
239
public
static
byte
[] fontSizeSetSmall(
int
num)
240.
240
{
241.
241
byte
[] result =
new
byte
[
3
];
242.
242
result[
0
] = ESC;
243.
243
result[
1
] =
33
;
244.
244
245.
245
return
result;
246.
246
}
247.
247
248.
248
249.
249
//------------------------切纸-----------------------------
250.
250
251.
251
252.
252
/**
253.
253 * 进纸并全部切割
254.
254 * @return
255.
255 */
256.
256
public
static
byte
[] feedPaperCutAll()
257.
257
{
258.
258
byte
[] result =
new
byte
[
4
];
259.
259
result[
0
] = GS;
260.
260
result[
1
] =
86
;
261.
261
result[
2
] =
65
;
262.
262
result[
3
] =
0
;
263.
263
return
result;
264.
264
}
265.
265
266.
266
267.
267
/**
268.
268 * 进纸并切割(左边留一点不切)
269.
269 * @return
270.
270 */
271.
271
public
static
byte
[] feedPaperCutPartial()
272.
272
{
273.
273
byte
[] result =
new
byte
[
4
];
274.
274
result[
0
] = GS;
275.
275
result[
1
] =
86
;
276.
276
result[
2
] =
66
;
277.
277
result[
3
] =
0
;
278.
278
return
result;
279.
279
}
280.
280
281.
281
282.
282
//------------------------切纸-----------------------------
283.
283
public
static
byte
[] byteMerger(
byte
[] byte_1,
byte
[] byte_2){
284.
284
byte
[] byte_3 =
new
byte
[byte_1.length+byte_2.length];
285.
285
System.arraycopy(byte_1,
0
, byte_3,
0
, byte_1.length);
286.
286
System.arraycopy(byte_2,
0
, byte_3, byte_1.length, byte_2.length);
287.
287
return
byte_3;
288.
288
}
289.
289
290.
290
291.
291
public
static
byte
[] byteMerger(
byte
[][] byteList){
292.
292
293.
293
int
length =
0
;
294.
294
for
(
int
i=
0
;i<byteList.length;i++)
295.
295
{
296.
296
length += byteList[i].length;
297.
297
}
298.
298
byte
[] result =
new
byte
[length];
299.
299
300.
300
int
index =
0
;
301.
301
for
(
int
i=
0
;i<byteList.length;i++)
302.
302
{
303.
303
byte
[] nowByte = byteList[i];
304.
304
for
(
int
k=
0
;k<byteList[i].length;k++)
305.
305
{
306.
306
result[index] = nowByte[k];
307.
307
index++;
308.
308
}
309.
309
}
310.
310
for
(
int
i =
0
;i<index;i++)
311.
311
{
312.
312
CommonUtils.LogWuwei(
''
,
'result['
+i+
'] is '
+result[i]);
313.
313
}
314.
314
return
result;
315.
315
}
316.
316
317.
317
318.
318
319.
319
}
工具库包括字体加粗、字体放大缩小、切纸、换行等基本操作,还有就是对byte数组的拼接,byte数组的拼接有很多方式,只实现了一种方式
效果图:
简单的代码解析:
01.
public
byte
[] clientPaper()
02.
{
03.
04.
try
{
05.
byte
[] next2Line = printerCmdUtils.nextLine(
2
);
06.
byte
[] title =
'出餐单(午餐)**万通中心店'
.getBytes(
'gb2312'
);
07.
08.
byte
[] boldOn = printerCmdUtils.boldOn();
09.
byte
[] fontSize2Big = printerCmdUtils.fontSizeSetBig(
3
);
10.
byte
[] center= printerCmdUtils.alignCenter();
11.
byte
[] Focus =
'网 507'
.getBytes(
'gb2312'
);
12.
byte
[] boldOff = printerCmdUtils.boldOff();
13.
byte
[] fontSize2Small = printerCmdUtils.fontSizeSetSmall(
3
);
14.
15.
byte
[] left= printerCmdUtils.alignLeft();
16.
byte
[] orderSerinum =
'订单编号:11234'
.getBytes(
'gb2312'
);
17.
boldOn = printerCmdUtils.boldOn();
18.
byte
[] fontSize1Big = printerCmdUtils.fontSizeSetBig(
2
);
19.
byte
[] FocusOrderContent =
'韭菜鸡蛋饺子-小份(单)'
.getBytes(
'gb2312'
);
20.
boldOff = printerCmdUtils.boldOff();
21.
byte
[] fontSize1Small = printerCmdUtils.fontSizeSetSmall(
2
);
22.
23.
24.
next2Line = printerCmdUtils.nextLine(
2
);
25.
26.
byte
[] priceInfo =
'应收:22元 优惠:2.5元 '
.getBytes(
'gb2312'
);
27.
byte
[] nextLine = printerCmdUtils.nextLine(
1
);
28.
29.
byte
[] priceShouldPay =
'实收:19.5元'
.getBytes(
'gb2312'
);
30.
nextLine = printerCmdUtils.nextLine(
1
);
31.
32.
byte
[] takeTime =
'取餐时间:2015-02-13 12:51:59'
.getBytes(
'gb2312'
);
33.
nextLine = printerCmdUtils.nextLine(
1
);
34.
byte
[] setOrderTime =
'下单时间:2015-02-13 12:35:15'
.getBytes(
'gb2312'
);
35.
36.
byte
[] tips_1 =
'微信关注'
**
'自助下单每天免1元'
.getBytes(
'gb2312'
);
37.
nextLine = printerCmdUtils.nextLine(
1
);
38.
byte
[] tips_2 =
'饭后点评再奖5毛'
.getBytes(
'gb2312'
);
39.
nextLine = printerCmdUtils.nextLine(
1
);
40.
41.
byte
[] breakPartial = printerCmdUtils.feedPaperCutPartial();
42.
43.
byte
[][] cmdBytes= {
44.
title,nextLine,
45.
center,boldOn,fontSize2Big,Focus,boldOff,fontSize2Small,next2Line,
46.
left,orderSerinum,nextLine,
47.
center,boldOn,fontSize1Big,FocusOrderContent,boldOff,fontSize1Small,nextLine,
48.
left,next2Line,
49.
priceInfo,nextLine,
50.
priceShouldPay,next2Line,
51.
takeTime,nextLine,
52.
setOrderTime,next2Line,
53.
center,tips_1,nextLine,
54.
center,tips_2,next2Line,
55.
breakPartial
56.
};
57.
58.
return
printerCmdUtils.byteMerger(cmdBytes);
59.
60.
}
catch
(UnsupportedEncodingException e) {
61.
// TODO Auto-generated catch block
62.
e.printStackTrace();
63.
}
64.
return
null
;
65.
}
字节码拼接过程如下:
01.
1
public
static
byte
[] byteMerger(
byte
[][] byteList){
02.
2
03.
3
int
length =
0
;
04.
4
for
(
int
i=
0
;i<byteList.length;i++)
05.
5
{
06.
6
length += byteList[i].length;
07.
7
}
08.
8
byte
[] result =
new
byte
[length];
09.
9
10.
10
int
index =
0
;
11.
11
for
(
int
i=
0
;i<byteList.length;i++)
12.
12
{
13.
13
byte
[] nowByte = byteList[i];
14.
14
for
(
int
k=
0
;k<byteList[i].length;k++)
15.
15
{
16.
16
result[index] = nowByte[k];
17.
17
index++;
18.
18
}
19.
19
}
20.
20
for
(
int
i =
0
;i<index;i++)
21.
21
{
22.
22
CommonUtils.LogWuwei(
''
,
'result['
+i+
'] is '
+result[i]);
23.
23
}
24.
24
return
result;
25.
25
}
将上步得到的字节码通过可写流写入套接字,这时小票打印机就会打印对应的内容。
1、demo链接地址如下:
http://pan.baidu.com/s/1eQ9y8mQ