最近项目需要研究下Android通过usbhost和蓝牙连接热敏打印机打印小票,收集了一下资料参考,感觉这块技术比较乱的,每家打印机都有自己的SDK,但其实底层的原理差不多,做个稳定兼容多个品牌热敏打印机的APP还是有难度的。

  昨天晚上说抽时间来写一篇关于Android 热敏打印机打印二维码和图片的文章,所幸在下班之前把它给写了,和大家分享吧。我的是Android机器有内置热敏打印机的,我是把apk跑在我的Android机器上的,操作程序打印的。

  一、打印机的型号
  RP-POS80S或RP-POS80P或RP-POS80CS或RP-POS80CP打印机 高速热敏打印机   打印方式:直接热敏打印   打印密度:640点/行   打印纸宽:80mm   有效打印宽度:72mm   最小走纸距离:0.125mm   打印字符   ACSII码字符集:12×24点   国标一、二级汉字字库:24×24点   采用命令集:ESC/POS打印命令集
  二、打印位图命令

ESC *m nL nH d1...dk [名称] 选择位图模式 [格式] ASCII码 ESC* m nL nH d1...dk 十六进制码 1B 2A m nL nH d1...dk 十进制码 2742 m nL nH d1...dk [范围] m= 0, 1, 32, 33 0 £ nL£ 255 0 £ nH£ 3 0 £ d£ 255


[描述]用 m选择位图的模式,位图的点数由 nL和 nH指定,如下所示:
m 模式 垂直方向 水平方向
点数 点密度 点密度 数据个数 (K)
0 8-点 单密度 8 67.7 dpi 101.6 dpi nL+ nH´ 256
1 8-点 双密度 8 67.7 dpi 203.2 dpi nL+ nH´ 256
32 24-点 单密度 24 203.2 dpi 101.6 dpi (nL+ nH ´ 256) ´3
33 24-点 双密度 24 203.2 dpi 203.2 dpi (nL+ nH ´ 256) ´3

Dpi:每25.4毫米{1英寸}打印点数

[注意] ·如果 m的值超出了指定的范围,那么nL和之后的数据被当作常规数据处理。 · nL和 nH表示水平方向上位图中的点数。通过nL+ nH´ 256计算出点数。 · 如果位图数据输入超出了一行上能被打印的点数,那么超出的数据被忽略。 · d表示位图数据。设置相应的位为 1去打印某点,或设置为 0以不打印某点。 · 如果用 GS LGSW设置的打印范围的宽度比用ESC *命令 发送的数据所要求的宽度小时,则对有问题的行执行下列操作(但是打印不能超出最大可打印范围):
① 打印区域的宽度向右扩展以去适应数据量。 ② 如果步骤①不能为数据提供足够的宽度,那么左边缘就被减少以去适应数据。对于在单密度模式(m= 0, 32)中的数据的每一位,打印机打印两个点:对于在双密度模式(m= 1, 33)中的数据的每一位,打印机打印一个点。在计算一行中能打印的数据量时,这些必须要考虑。
· 在打印一个位图之后,打印机返回常规数据处理模式。 · 这个命令不被打印模式(粗体、重叠、下划线、字符大小、或反白打印)影响, 除非是颠倒打印模式。 · 下图描述了图象数据与被打印的点之间的关系。
8-点位图被选定时

三、思路
因为所做的是打印图片(或者是二维码) ,先发送一个请求,从网络下载图片或者是二维码,得到这张图片过后,进行压缩到你想要的大小,在对压缩后的图片进行二值化,即黑白化,但是图片本身会有个α的值(即透明度)的问题,如果不进行处理的话,即使是黑白化的图片,得到图片的像素点也不是很精确。对于去透明度处理过后,在对这张图的每个最标点去像素值,即xxxXxxx大的图片,会有xxx X xxx个像素点。求出每个像素点的r、g、b的值,通过换算公式进行换算,得到一个像素值(0-255之间)。 如果是0-128是黑色,129-255是白色(非黑即白化),这样每个点的像素值就可以确定了。
因为我的热敏打印机是24*24的,所以会是24个像素点为一组,假设我把图片压缩为360*360像素的大小,就会有15组(纵向的15行,横坐标还是360)。一组的有24*360的像素点,因为8位是一个字节,这样24个像素点可以分为3组,每8位组成一个字节,每个像素点不是0就是1(之前已经非黑即白过),这样会得到一个byte数组,如:byte[] b1 = {1, 0, 0, 1, 0, 0, 0, 1}; 在将这样的数组换成十进制的数值int v1;这样就会得到3*15*360个的int 值,在将这些int的值和打印机的打印头命令拼接起来,组成一个byte[] 数组,就可以打印了。
四、注意
1.热敏打印机是一行一行的打印,所以每一行又得加上打印的头命令,我的打印机头命令是5个,所以byte[]数组的长度会是3*15*360+5*15
2.大家看好自己打印机的打印密度,比如我的是24*24的,所以我剪裁图片的大小会是24的倍数,360*360.大家最好也剪裁成相应的倍数,这样计算会方便点,不然的话,要对空白区域进行白色补缺。
贴代码
  1. package com.woyou.util;

  2. import android.graphics.Bitmap;
  3. import android.graphics.Canvas;
  4. import android.graphics.Matrix;
  5. import android.graphics.Rect;
  6. import android.util.Log;

  7. /**
  8. * 将图片转化为二进制
  9. * @author nsz
  10. * 2015年1月30日
  11. */
  12. public class PicFromPrintUtils {


  13. public void init(){
  14. // Gray = 0.29900 * R + 0.58700 * G + 0.11400 * B
  15. }

  16. /*************************************************************************
  17. * 我们的热敏打印机是RP-POS80S或RP-POS80P或RP-POS80CS或RP-POS80CP打印机
  18. * 360*360的图片,8个字节(8个像素点)是一个二进制,将二进制转化为十进制数值
  19. * y轴:24个像素点为一组,即360就是15组(0-14)
  20. * x轴:360个像素点(0-359)
  21. * 里面的每一组(24*360),每8个像素点为一个二进制,(每组有3个,3*8=24)
  22. **************************************************************************/
  23. /**
  24. * 把一张Bitmap图片转化为打印机可以打印的bit(将图片压缩为360*360)
  25. * 效率很高(相对于下面)
  26. * @param bit
  27. * @return
  28. */
  29. public static byte[] draw2PxPoint(Bitmap bit) {
  30. byte[] data = new byte[16290];
  31. int k = 0;
  32. for (int j = 0; j < 15; j++) {
  33. data[k++] = 0x1B;
  34. data[k++] = 0x2A;
  35. data[k++] = 33; // m=33时,选择24点双密度打印,分辨率达到200DPI。
  36. data[k++] = 0x68;
  37. data[k++] = 0x01;
  38. for (int i = 0; i < 360; i++) {
  39. for (int m = 0; m < 3; m++) {
  40. for (int n = 0; n < 8; n++) {
  41. byte b = px2Byte(i, j * 24 + m * 8 + n, bit);
  42. data[k] += data[k] + b;
  43. }
  44. k++;
  45. }
  46. }
  47. data[k++] = 10;
  48. }
  49. return data;
  50. }

  51. /**
  52. * 把一张Bitmap图片转化为打印机可以打印的bit
  53. * @param bit
  54. * @return
  55. */
  56. public static byte[] pic2PxPoint(Bitmap bit){
  57. long start = System.currentTimeMillis();
  58. byte[] data = new byte[16290];
  59. int k = 0;
  60. for (int i = 0; i < 15; i++) {
  61. data[k++] = 0x1B;
  62. data[k++] = 0x2A;
  63. data[k++] = 33; // m=33时,选择24点双密度打印,分辨率达到200DPI。
  64. data[k++] = 0x68;
  65. data[k++] = 0x01;
  66. for (int x = 0; x < 360; x++) {
  67. for (int m = 0; m < 3; m++) {
  68. byte[]by = new byte[8];
  69. for (int n = 0; n < 8; n++) {
  70. byte b = px2Byte(x, i * 24 + m * 8 +7-n, bit);
  71. by[n] = b;
  72. }
  73. data[k] = (byte) changePointPx1(by);
  74. k++;
  75. }
  76. }
  77. data[k++] = 10;
  78. }
  79. long end = System.currentTimeMillis();
  80. long str = end - start;
  81. Log.i("TAG", "str:" + str);
  82. return data;
  83. }

  84. /**
  85. * 图片二值化,黑色是1,白色是0
  86. * @param x横坐标
  87. * @param y 纵坐标
  88. * @param bit 位图
  89. * @return
  90. */
  91. public static byte px2Byte(int x, int y, Bitmap bit) {
  92. byte b;
  93. int pixel = bit.getPixel(x, y);
  94. int red = (pixel & 0x00ff0000) >> 16; // 取高两位
  95. int green = (pixel & 0x0000ff00) >> 8; // 取中两位
  96. int blue = pixel & 0x000000ff; // 取低两位
  97. int gray = RGB2Gray(red, green, blue);
  98. if ( gray < 128 ){
  99. b = 1;
  100. } else {
  101. b = 0;
  102. }
  103. return b;
  104. }

  105. /**
  106. * 图片灰度的转化
  107. * @param r
  108. * @param g
  109. * @param b
  110. * @return
  111. */
  112. private static int RGB2Gray(int r, int g, int b){
  113. int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b);//灰度转化公式
  114. returngray;
  115. }

  116. /**
  117. * 对图片进行压缩(去除透明度)
  118. * @param bitmapOrg
  119. */
  120. public static Bitmap compressPic(Bitmap bitmapOrg) {
  121. // 获取这个图片的宽和高
  122. int width = bitmapOrg.getWidth();
  123. int height = bitmapOrg.getHeight();
  124. // 定义预转换成的图片的宽度和高度
  125. int newWidth = 360;
  126. int newHeight = 360;
  127. Bitmap targetBmp = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
  128. Canvas targetCanvas = new Canvas(targetBmp);
  129. targetCanvas.drawColor(0xffffffff);
  130. targetCanvas.drawBitmap(bitmapOrg, new Rect(0, 0, width, height), new Rect(0, 0, newWidth, newHeight), null);
  131. return targetBmp;
  132. }


  133. /**
  134. * 对图片进行压缩(不去除透明度)
  135. * @param bitmapOrg
  136. */
  137. public static Bitmap compressBitmap(Bitmap bitmapOrg) {
  138. // 加载需要操作的图片,这里是一张图片
  139. // Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.alipay);
  140. // 获取这个图片的宽和高
  141. int width = bitmapOrg.getWidth();
  142. int height = bitmapOrg.getHeight();
  143. // 定义预转换成的图片的宽度和高度
  144. int newWidth = 360;
  145. int newHeight = 360;
  146. // 计算缩放率,新尺寸除原始尺寸
  147. float scaleWidth = ((float) newWidth) / width;
  148. float scaleHeight = ((float) newHeight) / height;
  149. // 创建操作图片用的matrix对象
  150. Matrix matrix = new Matrix();
  151. // 缩放图片动作
  152. matrix.postScale(scaleWidth, scaleHeight);
  153. // 创建新的图片
  154. Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width,height, matrix, true);
  155. // 将上面创建的Bitmap转换成Drawable对象,使得其可以使用在ImageView, ImageButton中
  156. // BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
  157. return resizedBitmap;
  158. }

  159. /**
  160. * 将[1,0,0,1,0,0,0,1]这样的二进制转为化十进制的数值(效率更高)
  161. * @param arry
  162. * @return
  163. */
  164. public static int changePointPx1(byte[] arry){
  165. int v = 0;
  166. for (int j = 0; j <arry.length; j++) {
  167. if( arry[j] == 1) {
  168. v = v | 1 << j;
  169. }
  170. }
  171. return v;
  172. }

  173. /**
  174. * 将[1,0,0,1,0,0,0,1]这样的二进制转为化十进制的数值
  175. * @param arry
  176. * @return
  177. */
  178. public byte changePointPx(byte[] arry){
  179. byte v = 0;
  180. for (int i = 0; i < 8; i++) {
  181. v += v + arry[i];
  182. }
  183. return v;
  184. }

  185. /**
  186. * 得到位图的某个点的像素值
  187. * @param bitmap
  188. * @return
  189. */
  190. public byte[] getPicPx(Bitmap bitmap){
  191. int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];// 保存所有的像素的数组,图片宽×高
  192. bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
  193. for (int i = 0; i < pixels.length; i++) {
  194. int clr = pixels[i];
  195. int red = (clr & 0x00ff0000) >> 16; // 取高两位
  196. int green = (clr & 0x0000ff00) >> 8; // 取中两位
  197. int blue = clr & 0x000000ff; // 取低两位
  198. System.out.println("r=" + red + ",g=" + green + ",b=" + blue);
  199. }
  200. return null;
  201. }

  202. }
复制代码

下面楼层继续...


  1. package com.woyou.util;

  2. import java.io.ByteArrayOutputStream;
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.security.InvalidParameterException;
  8. import java.text.DecimalFormat;
  9. import java.text.SimpleDateFormat;
  10. import java.util.Date;
  11. import java.util.Locale;

  12. import android.content.Context;
  13. import android_serialport_api.SerialPort;

  14. /**
  15. * 打印机辅助
  16. *
  17. * @author nsz 2015年1月30日
  18. */
  19. public class PrintUtil {
  20. final static int BUFFER_SIZE = 4096;

  21. /**
  22. * 对一个byte[] 进行打印
  23. * @param printText
  24. * @return
  25. * add by yidie
  26. */
  27. public static boolean printBytes(byte[] printText) {
  28. boolean returnValue = true;
  29. try {
  30. OutputStream mOutputStream = getSerialPort().getOutputStream();
  31. mOutputStream.write(printText);
  32. } catch (Exception ex) {
  33. returnValue = false;
  34. }
  35. return returnValue;
  36. }

  37. /**
  38. * "\n" 就是换行
  39. * @param paramString
  40. * @return
  41. * add by yidie
  42. */
  43. public static boolean printString(String paramString) {
  44. return printBytes(getGbk(paramString));
  45. }

  46. /***************************************************************************
  47. * add by yidie 2012-01-10 功能:设置打印绝对位置 参数: int 在当前行,定位光标位置,取值范围0至576点 说明:
  48. * 在字体常规大小下,每汉字24点,英文字符12点 如位于第n个汉字后,则position=24*n
  49. * 如位于第n个半角字符后,则position=12*n
  50. ****************************************************************************/

  51. public static byte[] setCusorPosition(int position) {
  52. byte[] returnText = new byte[4]; // 当前行,设置绝对打印位置 ESC $ bL bH
  53. returnText[0] = 0x1B;
  54. returnText[1] = 0x24;
  55. returnText[2] = (byte) (position % 256);
  56. returnText[3] = (byte) (position / 256);
  57. return returnText;
  58. }

  59. /**
  60. * 设置打印机的行高
  61. * @param h
  62. * @return
  63. */
  64. public static byte[] setLineHeight(byte h) {
  65. byte[] returnText = new byte[] { 0x1B, 0x33, h }; // 切纸; 1B 33 n
  66. return returnText;
  67. }

  68. public static byte[] setDefaultLineHeight() {
  69. byte[] returnText = new byte[] { 0x1B, 0x32 }; // 切纸; 1B 32
  70. return returnText;
  71. }

  72. public static byte[] InputStreamTOByte(InputStream in) throws IOException {

  73. ByteArrayOutputStream outStream = new ByteArrayOutputStream();
  74. byte[] data = new byte[BUFFER_SIZE];
  75. int count = -1;
  76. while ((count = in.read(data, 0, BUFFER_SIZE)) != -1)
  77. outStream.write(data, 0, count);

  78. data = null;
  79. return outStream.toByteArray();
  80. }

  81. /**
  82. * 打印我有外卖的logo
  83. * @param c
  84. */
  85. public static void printLogo(Context c) {
  86. PrintUtil.printBytes(PrintUtil.setLineHeight((byte) 0));
  87. InputStream is = c.getClass().getResourceAsStream("/assets/bill.bin");
  88. byte[] b;
  89. try {
  90. b = InputStreamTOByte(is);
  91. PrintUtil.printBytes(b);
  92. PrintUtil.printBytes(PrintUtil.setDefaultLineHeight());
  93. } catch (Exception e) {
  94. e.printStackTrace();
  95. }
  96. }

  97. public static byte[] getLogo(Context c) {
  98. InputStream is = c.getClass().getResourceAsStream("/assets/bill.bin");
  99. byte[] b;
  100. try {
  101. b = InputStreamTOByte(is);
  102. return b;
  103. } catch (Exception e) {
  104. e.printStackTrace();
  105. }
  106. return null;
  107. }

  108. /**
  109. * 得到店铺logo
  110. * @param c
  111. * @param bit
  112. * @return
  113. */
  114. public static byte[] getLogo(Context c, byte[] bit) {
  115. InputStream is = c.getClass().getResourceAsStream("/assets/bill.bin");
  116. byte[] b = bit;
  117. try {
  118. b = InputStreamTOByte(is);
  119. return b;
  120. } catch (Exception e) {
  121. e.printStackTrace();
  122. }
  123. return null;
  124. }

  125. public static byte[] getLogo(byte[] bs) {
  126. byte[] b;
  127. try {
  128. b = bs;
  129. return b;
  130. } catch (Exception e) {
  131. e.printStackTrace();
  132. }
  133. return null;
  134. }

  135. /**
  136. * 支付打印(二维码)
  137. * @param b
  138. * @param money
  139. * @return
  140. * [url=home.php?mod=space&uid=2643633]@throws[/url] InvalidParameterException
  141. * @throws SecurityException
  142. * @throws IOException
  143. */
  144. public static boolean printAlipayTitle(byte[] b, String money)
  145. throws InvalidParameterException, SecurityException, IOException {

  146. int iNum = 0;
  147. byte[] tempBuffer = new byte[1000];

  148. byte[]oldText = setAlignCenter('2');
  149. System.arraycopy(oldText, 0,tempBuffer,iNum,oldText.length);
  150. iNum += oldText.length;
  151. oldText = setWH('4');
  152. System.arraycopy(oldText, 0, tempBuffer,iNum,oldText.length);
  153. iNum += oldText.length;
  154. oldText = setBold(true);
  155. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  156. iNum += oldText.length;
  157. oldText = getGbk("支付凭证\n");
  158. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  159. iNum += oldText.length;

  160. oldText = getGbk("\n");
  161. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  162. iNum += oldText.length;

  163. oldText = setAlignCenter('2');
  164. System.arraycopy(oldText, 0,tempBuffer,iNum,oldText.length);
  165. iNum += oldText.length;
  166. oldText = setWH('3');
  167. System.arraycopy(oldText, 0, tempBuffer,iNum,oldText.length);
  168. iNum += oldText.length;
  169. oldText = setBold(true);
  170. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  171. iNum += oldText.length;
  172. oldText = getGbk("您共消费了" + money + "元\n");
  173. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  174. iNum += oldText.length;

  175. oldText = getGbk("\n");
  176. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  177. iNum += oldText.length;

  178. oldText = setAlignCenter('2');
  179. System.arraycopy(oldText, 0,tempBuffer,iNum,oldText.length);
  180. iNum += oldText.length;
  181. oldText = setWH('3');
  182. System.arraycopy(oldText, 0, tempBuffer,iNum,oldText.length);
  183. iNum += oldText.length;
  184. oldText = setBold(true);
  185. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  186. iNum += oldText.length;
  187. oldText = getGbk("请扫码支付\n\n");
  188. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  189. iNum += oldText.length;

  190. SerialPort mSerialPort = getSerialPort();
  191. OutputStream mOutputStream = mSerialPort.getOutputStream();
  192. try {
  193. mOutputStream.write(tempBuffer);
  194. printBytes(b);
  195. printString("\n\n\n");
  196. printBytes(CutPaper());
  197. } catch (IOException e) {
  198. e.printStackTrace();
  199. return false;
  200. }
  201. return true;
  202. }

  203. /***************************************************************************
  204. * add by yidie 2012-01-10 功能:订单打印 参数: String 订单短号 OrderDetail 打印内容,包含
  205. * GoodsInfo[] String 打印标题
  206. ****************************************************************************/

  207. public static boolean printOrder(Context c, byte[] b)
  208. throws InvalidParameterException, SecurityException, IOException {

  209. DecimalFormat dcmFmt = new DecimalFormat("0.00");
  210. int iNum = 0, i;

  211. byte[] tempBuffer = new byte[8000];
  212. String stTmp = "";

  213. byte[] oldText = setAlignCenter('2');
  214. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  215. iNum += oldText.length;

  216. oldText = getLogo(c, b);
  217. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  218. iNum += oldText.length;

  219. oldText = setWH('1');
  220. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  221. iNum += oldText.length;

  222. oldText = getGbk("\n");
  223. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  224. iNum += oldText.length;

  225. oldText = setAlignCenter('2');
  226. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  227. iNum += oldText.length;

  228. oldText = setWH('4');
  229. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  230. iNum += oldText.length;

  231. oldText = setBold(true);
  232. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  233. iNum += oldText.length;

  234. oldText = setWH('1');
  235. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  236. iNum += oldText.length;

  237. oldText = getGbk("\n");
  238. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  239. iNum += oldText.length;

  240. oldText = setAlignCenter('1');
  241. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  242. iNum += oldText.length;

  243. oldText = setCusorPosition(324);
  244. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  245. iNum += oldText.length;

  246. String strTime = new SimpleDateFormat("yyyy-MM-dd HH:mm",
  247. Locale.SIMPLIFIED_CHINESE).format(new Date());
  248. oldText = getGbk(strTime + "打印\n");
  249. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  250. iNum += oldText.length;

  251. oldText = setBold(false);
  252. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  253. iNum += oldText.length;

  254. oldText = getGbk("----------------------------------------------\n");
  255. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  256. iNum += oldText.length;

  257. oldText = setWH('3');
  258. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  259. iNum += oldText.length;

  260. oldText = getGbk(" 商品名称 单价 数量 金额\n");
  261. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  262. iNum += oldText.length;

  263. oldText = getGbk("----------------------------------------------\n");
  264. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  265. iNum += oldText.length;

  266. oldText = setWH('3');
  267. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  268. iNum += oldText.length;

  269. oldText = setAlignCenter('2');
  270. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  271. iNum += oldText.length;

  272. oldText = setWH('1');
  273. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  274. iNum += oldText.length;

  275. oldText = getGbk("\n感谢使用[我有外卖]订餐,24小时服务热线 4008519517\n\n\n");
  276. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  277. iNum += oldText.length;

  278. oldText = CutPaper();
  279. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  280. iNum += oldText.length;

  281. SerialPort mSerialPort = getSerialPort();
  282. OutputStream mOutputStream = mSerialPort.getOutputStream();
  283. try {
  284. mOutputStream.write(tempBuffer);
  285. } catch (IOException e) {
  286. e.printStackTrace();
  287. return false;
  288. }
  289. return true;
  290. }

  291. /***************************************************************************
  292. * add by yidie 2012-01-12 功能:报表打印 参数: String 打印标题,如“月报表:2013-01”
  293. * ReportUserSale 打印内容,包含 UserSaleInfo[]
  294. ****************************************************************************/

  295. public static boolean printReportUser() throws InvalidParameterException,
  296. SecurityException, IOException {

  297. int iNum = 0;
  298. String stTmp = "";

  299. byte[] tempBuffer = new byte[8000];
  300. SerialPort mSerialPort = getSerialPort();
  301. OutputStream mOutputStream = mSerialPort.getOutputStream();

  302. byte[] oldText = setAlignCenter('1');
  303. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  304. iNum += oldText.length;

  305. oldText = setWH('3');
  306. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  307. iNum += oldText.length;

  308. oldText = setCusorPosition(324);
  309. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  310. iNum += oldText.length;

  311. String strTime = new SimpleDateFormat("yyyy-MM-dd HH:mm",
  312. Locale.SIMPLIFIED_CHINESE).format(new Date());
  313. oldText = getGbk(strTime + "打印\n");
  314. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  315. iNum += oldText.length;

  316. oldText = setWH('1');
  317. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  318. iNum += oldText.length;

  319. oldText = setAlignCenter('2');
  320. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  321. iNum += oldText.length;

  322. oldText = setWH('4');
  323. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  324. iNum += oldText.length;

  325. oldText = setBold(true);
  326. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  327. iNum += oldText.length;

  328. oldText = setWH('1');
  329. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  330. iNum += oldText.length;

  331. oldText = getGbk("\n\n");
  332. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  333. iNum += oldText.length;

  334. oldText = setAlignCenter('1');
  335. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  336. iNum += oldText.length;

  337. oldText = setBold(false);
  338. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  339. iNum += oldText.length;

  340. oldText = setWH('1');
  341. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  342. iNum += oldText.length;

  343. oldText = getGbk("   用户       售出数量 售出金额\n");
  344. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  345. iNum += oldText.length;

  346. oldText = getGbk("----------------------------------------------\n");
  347. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  348. iNum += oldText.length;

  349. oldText = CutPaper();
  350. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);
  351. iNum += oldText.length;
  352. try {
  353. mOutputStream.write(tempBuffer);
  354. } catch (IOException e) {
  355. e.printStackTrace();
  356. return false;
  357. }

  358. return true;
  359. }

  360. /***************************************************************************
  361. * add by yidie 2012-01-12 功能:报表打印 参数: String 打印标题,如“月报表:2013-01” ReportSale
  362. * 打印内容,包含 SaleInfo[]
  363. ****************************************************************************/

  364. private static SerialPort mSerialPort = null;

  365. public static SerialPort getSerialPort() throws SecurityException,
  366. IOException, InvalidParameterException {
  367. if (mSerialPort == null) {
  368. String spFile = null;
  369. String model = MainBoardUtil.getModel(); // android.os.Build.MODEL.toLowerCase();
  370. if (model.contains(Constants.MAIN_BOARD_SMDKV210)) {
  371. spFile = "/dev/s3c2410_serial0";
  372. } else if (model.contains(Constants.MAIN_BOARD_RK30)) {
  373. spFile = "/dev/ttyS1";
  374. } else if (model.contains(Constants.MAIN_BOARD_C500)) {
  375. spFile = "/dev/ttyS1";
  376. } else {
  377. throw new IOException("unknow hardware!");
  378. }

  379. int baudrate = 115200;
  380. boolean flagCon = true;

  381. File myFile = new File(spFile);

  382. /* Open the serial port */
  383. mSerialPort = new SerialPort(myFile, baudrate, 0, flagCon);
  384. }
  385. return mSerialPort;
  386. }

  387. public static void closeSerialPort() {
  388. if (mSerialPort != null) {
  389. mSerialPort.close();
  390. mSerialPort = null;
  391. }
  392. }

  393. public static byte[] getGbk(String stText) {
  394. byte[] returnText = null;
  395. try {
  396. returnText = stText.getBytes("GBK"); // 必须放在try内才可以
  397. } catch (Exception ex) {
  398. ;
  399. }
  400. return returnText;
  401. }

  402. public static byte[] setWH(char dist) {
  403. byte[] returnText = new byte[3]; // GS ! 11H 倍宽倍高
  404. returnText[0] = 0x1D;
  405. returnText[1] = 0x21;

  406. switch (dist) // 1-无;2-倍宽;3-倍高; 4-倍宽倍高
  407. {
  408. case '2':
  409. returnText[2] = 0x10;
  410. break;
  411. case '3':
  412. returnText[2] = 0x01;
  413. break;
  414. case '4':
  415. returnText[2] = 0x11;
  416. break;
  417. default:
  418. returnText[2] = 0x00;
  419. break;
  420. }

  421. return returnText;
  422. }

  423. /**
  424. * 打印的对齐方式
  425. * @param dist
  426. * @return
  427. */
  428. public static byte[] setAlignCenter(char dist) {
  429. byte[] returnText = new byte[3]; // 对齐 ESC a
  430. returnText[0] = 0x1B;
  431. returnText[1] = 0x61;

  432. switch (dist) // 1-左对齐;2-居中对齐;3-右对齐
  433. {
  434. case '2':
  435. returnText[2] = 0x01;
  436. break;
  437. case '3':
  438. returnText[2] = 0x02;
  439. break;
  440. default:
  441. returnText[2] = 0x00;
  442. break;
  443. }
  444. return returnText;
  445. }

  446. public static byte[] setBold(boolean dist) {
  447. byte[] returnText = new byte[3]; // 加粗 ESC E
  448. returnText[0] = 0x1B;
  449. returnText[1] = 0x45;

  450. if (dist) {
  451. returnText[2] = 0x01; // 表示加粗
  452. } else {
  453. returnText[2] = 0x00;
  454. }
  455. return returnText;
  456. }

  457. public static byte[] PrintBarcode(String stBarcode) {
  458. int iLength = stBarcode.length() + 4;
  459. byte[] returnText = new byte[iLength];

  460. returnText[0] = 0x1D;
  461. returnText[1] = 'k';
  462. returnText[2] = 0x45;
  463. returnText[3] = (byte) stBarcode.length(); // 条码长度;

  464. System.arraycopy(stBarcode.getBytes(), 0, returnText, 4,
  465. stBarcode.getBytes().length);

  466. return returnText;
  467. }

  468. /**
  469. * 切纸
  470. * @return
  471. */
  472. public static byte[] CutPaper() {
  473. byte[] returnText = new byte[] { 0x1D, 0x56, 0x42, 0x00 }; // 切纸; GS V
  474. // 66D 0D
  475. return returnText;
  476. }
  477. }
复制代码
  1. package com.woyou.woyoupay;

  2. import java.io.IOException;
  3. import java.net.URL;
  4. import java.util.ArrayList;
  5. import java.util.List;

  6. import org.json.JSONException;
  7. import org.json.JSONObject;

  8. import android.app.Activity;
  9. import android.app.ProgressDialog;
  10. import android.content.Intent;
  11. import android.graphics.Bitmap;
  12. import android.graphics.BitmapFactory;
  13. import android.graphics.drawable.Drawable;
  14. import android.os.Bundle;
  15. import android.text.Html;
  16. import android.util.Log;
  17. import android.view.View;
  18. import android.view.View.OnClickListener;
  19. import android.view.Window;
  20. import android.widget.ImageView;
  21. import android.widget.TextView;

  22. import com.anjoyo.net.AsyncHttpClient;
  23. import com.anjoyo.net.JsonHttpResponseHandler;
  24. import com.anjoyo.net.RequestParams;
  25. import com.woyou.R;
  26. import com.woyou.bean.ScanCodeRes;
  27. import com.woyou.util.Constants;
  28. import com.woyou.util.PicFromPrintUtils;
  29. import com.woyou.util.PrintUtil;
  30. import com.woyou.util.ThreadPoolManager;

  31. public class Print2DCodeAct extends Activity implements OnClickListener {
  32. private static final String TAG = "Print2DCodeAct";
  33. TextView back, print, motifiscan;
  34. TextView oId, money, price;
  35. ImageView printImg;
  36. ProgressDialog dialog;

  37. @Override
  38. protected void onCreate(Bundle savedInstanceState) {
  39. super.onCreate(savedInstanceState);
  40. requestWindowFeature(Window.FEATURE_NO_TITLE);
  41. setContentView(R.layout.activity_print2dcode);
  42. initView();
  43. }

  44. String extra;
  45. private void initView() {
  46. Intent intent = getIntent();
  47. extra = intent.getStringExtra("money");
  48. back = (TextView) this.findViewById(R.id.back);
  49. oId = (TextView) this.findViewById(R.id.order_id);
  50. back.setOnClickListener(this);
  51. motifiscan = (TextView) this.findViewById(R.id.motifiscan);
  52. print = (TextView) this.findViewById(R.id.print_image);
  53. printImg = (ImageView) this.findViewById(R.id.print_two_image);
  54. money = (TextView) this.findViewById(R.id.money);
  55. print.setOnClickListener(this);
  56. motifiscan.setOnClickListener(this);
  57. money.setText(Html.fromHtml("¥<big>" + extra + "</big>"));

  58. //显示图片
  59. // Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(), R.drawable.alipay);
  60. // Bitmap bitmap = compressPic(bitmapOrg);
  61. // image_alipy.setImageBitmap(bitmap);

  62. //请求数据
  63. getData();
  64. }

  65. private void showDialog() {
  66. if (dialog == null) {
  67. dialog = new ProgressDialog(this);
  68. dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
  69. dialog.setCancelable(true);
  70. dialog.setMessage("正在加载中,请稍候...");
  71. }
  72. dialog.show();
  73. }
  74. private void hideDialog() {
  75. runOnUiThread(new Runnable() {

  76. @Override
  77. public void run() {
  78. if (dialog != null) {
  79. dialog.dismiss();
  80. }
  81. }
  82. });
  83. }



  84. @Override
  85. protected void onResume() {
  86. super.onResume();
  87. Constants.ACTIVITY_INSTANCE = Print2DCodeAct.this;
  88. }

  89. List<ScanCodeRes> list = new ArrayList<ScanCodeRes>();
  90. Bitmap compressPic = null;
  91. String big_pic_url;
  92. String pic_url;
  93. String small_pic_url;
  94. private void getData() {
  95. float f = Float.parseFloat(extra) * 100;
  96. int inte = (int) f;
  97. long parseLong = Long.parseLong(String.valueOf(inte));

  98. String sign = Constants.md5("100512354" + "150039203" + Constants.KEY);
  99. String url = "http://api.coupon.dev.wosai.cn/Upay/alipayQrCodeOffline";
  100. AsyncHttpClient client = new AsyncHttpClient();
  101. RequestParams params = new RequestParams();
  102. params.put("store_own_order_id", "1234");
  103. params.put("subject", "喔噻体验商品");
  104. params.put("total_fee", parseLong+"");
  105. params.put("wosai_store_id", "100512354");
  106. params.put("wosai_app_id", "150039203");
  107. params.put("sign", sign);
  108. params.put("notify_url", "http://www.woyouwaimai.com/get"); //推送支付成功的通知
  109. Log.i(TAG, url + params);

  110. client.get(url, params, new JsonHttpResponseHandler() {
  111. @Override
  112. public void onStart() {
  113. super.onStart();
  114. showDialog();
  115. }
  116. @Override
  117. public void onSuccess(JSONObject response) {
  118. super.onSuccess(response);
  119. try {
  120. String code = response.getString("code");
  121. String msg = response.getString("msg");
  122. Log.i(TAG, "code:" + code);
  123. Log.i(TAG, "msg:" + msg);
  124. if ("10000".equals(code)) {
  125. JSONObject data = response.getJSONObject("data");
  126. String order_sn = data.getString("order_sn");
  127. String wosai_store_id = data.getString("wosai_store_id");
  128. int status = data.getInt("status");
  129. String ctime = data.getString("ctime");
  130. JSONObject order_pay_detail = data.getJSONObject("order_pay_detail");
  131. String order_detail = data.getString("order_detail");
  132. String pay_way = data.getString("pay_way");
  133. long total_fee = data.getLong("total_fee");

  134. String is_success = order_pay_detail.getString("is_success");
  135. JSONObject responses = order_pay_detail.getJSONObject("response");
  136. String sign = order_pay_detail.getString("sign");
  137. String sign_type = order_pay_detail.getString("sign_type");

  138. JSONObject alipay = responses.getJSONObject("alipay");
  139. big_pic_url = alipay.getString("big_pic_url");
  140. String out_trade_no = alipay.getString("out_trade_no");
  141. pic_url = alipay.getString("pic_url");
  142. String qr_code = alipay.getString("qr_code");
  143. String result_code = alipay.getString("result_code");
  144. small_pic_url = alipay.getString("small_pic_url");
  145. String voucher_type = alipay.getString("voucher_type");
  146. Log.i(TAG, "big_pic_url:" + big_pic_url);
  147. Log.i(TAG, "pic_url:" + pic_url);
  148. Log.i(TAG, "small_pic_url:" + small_pic_url);

  149. ScanCodeRes res = new ScanCodeRes();
  150. res.setOrder_sn(order_sn);
  151. res.setWosai_store_id(wosai_store_id);
  152. res.setStatus(status);
  153. res.setCtime(ctime);
  154. res.setIs_success(is_success);
  155. res.setOrder_detail(order_detail);
  156. res.setTotal_fee(total_fee);
  157. res.setPay_way(pay_way);
  158. list.add(res);

  159. Constants.memoryCache.put(Constants.SCAN_CODE_RESULT, list);

  160. }
  161. } catch (JSONException e) {
  162. e.printStackTrace();
  163. hideDialog();
  164. }
  165. }

  166. @Override
  167. public void onFinish() {
  168. super.onFinish();
  169. ThreadPoolManager.getInstance().executeTask(new Runnable() {
  170. @Override
  171. public void run() {
  172. try {
  173. Bitmap bitmap = BitmapFactory.decodeStream(new URL(pic_url).openStream());
  174. compressPic = PicFromPrintUtils.compressPic(bitmap);
  175. }catch (IOException e) {
  176. e.printStackTrace();
  177. }
  178. runOnUiThread(new Runnable() {

  179. @Override
  180. public void run() {
  181. printImg.setImageBitmap(compressPic);
  182. print2Code(compressPic);
  183. hideDialog();
  184. }
  185. });

  186. }
  187. });
  188. }

  189. });
  190. }

  191. //打印二维码
  192. private void print2Code(Bitmap bitmap){
  193. final byte[] bs = PicFromPrintUtils.draw2PxPoint(bitmap);
  194. ThreadPoolManager.getInstance().executeTask(new Runnable() {
  195. @Override
  196. public void run() {
  197. try {
  198. PrintUtil.printAlipayTitle(bs, extra);
  199. } catch (Exception e) {
  200. e.printStackTrace();
  201. }
  202. }
  203. });
  204. }

  205. @Override
  206. public void onClick(View v) {
  207. switch (v.getId()) {
  208. case R.id.print_image:
  209. if ( compressPic != null ){
  210. print2Code(compressPic);
  211. }
  212. break;

  213. case R.id.back:
  214. finish();
  215. break;

  216. case R.id.motifiscan:
  217. Intent intent = new Intent(this, HomeAct.class);
  218. intent.putExtra("money", extra);
  219. startActivity(intent);
  220. break;
  221. }
  222. }

  223. public Drawable loadImageFromNetwork(String urladdr) {
  224. Drawable drawable = null;
  225. try {
  226. drawable = Drawable.createFromStream(new URL(urladdr).openStream(),"image.jpg");
  227. } catch (IOException e) {
  228. Log.d("test", e.getMessage());
  229. }
  230. if (drawable == null) {
  231. Log.d("test", "null drawable");
  232. } else {
  233. Log.d("test", "not null drawable");
  234. }
  235. return drawable;
  236. }

  237. // 计算图片的缩放值
  238. public static int calculateInSampleSize(BitmapFactory.Options options,
  239. int reqWidth, int reqHeight) {
  240. final int height = options.outHeight;
  241. final int width = options.outWidth;
  242. int inSampleSize = 1;
  243. if (height > reqHeight || width > reqWidth) {
  244. final int heightRatio = Math.round((float) height
  245. / (float) reqHeight);
  246. final int widthRatio = Math.round((float) width / (float) reqWidth);
  247. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
  248. }
  249. return inSampleSize;
  250. }

  251. }
复制代码

代码不是很全,只上了一些核心的代码,因为这是公司的项目,不适合把工程贴上来,忘大家见谅。中间会有一些简单的算法,是为提高效率用的,代码的整合力度也不是很好,大家将就点吧。



原文

http://www.eoeandroid.com/thread-564903-1-1.html?_dsign=50a25db8

更多相关文章

  1. Android开发人员需要具备的知识(很全)!
  2. Android(安卓)WindowManager与窗口管理
  3. android开发 - 圆角和边框
  4. android 图片处理 resize 探秘(图片缩放、压缩问题)
  5. Android:微软的金钱机器(更新)
  6. Android系统信息获取 之十四:获取WIFI热点相关信息
  7. Android(安卓)获取手机存储信息详解(内存,外存等)
  8. Android视频图片缩略图的获取
  9. android click 和onTouch 事件处理机制 (转)

随机推荐

  1. Android平台开发-Android(安卓)keypad ma
  2. Android单元测试之Local unit tests(下)
  3. Android内存管理、监测剖析
  4. android开发每日汇总【2011-12-6】
  5. android:visibility属性
  6. running Android(安卓)Studio on Windows
  7. EditText 的常用属性与解释
  8. android 使用Intent传递数据之剪切板
  9. Android2.2 API 中文文档系列(4) —— Mani
  10. android 开源和一些博客总结