您的位置:首页 > 移动开发 > Android开发

Android 热敏打印机打印二维码

2015-10-21 10:01 489 查看
[align=center] 最近项目需要研究下Android通过usbhost和蓝牙连接热敏打印机打印小票,收集了一下资料参考,感觉这块技术比较乱的,每家打印机都有自己的SDK,但其实底层的原理差不多,做个稳定兼容多个品牌热敏打印机的APP还是有难度的。[/align][align=left]
[/align][align=left]
  昨天晚上说抽时间来写一篇关于Android 热敏打印机打印二维码和图片的文章,所幸在下班之前把它给写了,和大家分享吧。我的是Android机器有内置热敏打印机的,我是把apk跑在我的Android机器上的,操作程序打印的。[/align][align=center]
[/align][align=center]  一、打印机的型号[/align][align=center]
[/align][align=center]  RP-POS80S或RP-POS80P或RP-POS80CS或RP-POS80CP打印机 高速热敏打印机[/align][align=center]  打印方式:直接热敏打印[/align][align=center]  打印密度:640点/行[/align][align=center]  打印纸宽:80mm[/align][align=center]  有效打印宽度:72mm[/align][align=center]  最小走纸距离:0.125mm[/align][align=center]  打印字符[/align][align=center]  ACSII码字符集:12×24点[/align][align=center]  国标一、二级汉字字库:24×24点[/align][align=center]  采用命令集:ESC/POS打印命令集[/align]
  二、打印位图命令

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

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


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

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Matrix;

import android.graphics.Rect;

import android.util.Log;

/**

* 将图片转化为二进制

* @author nsz

* 2015年1月30日

*/

public class PicFromPrintUtils {

public void init(){

// Gray = 0.29900 * R + 0.58700 * G + 0.11400 * B

}

/*************************************************************************

* 我们的热敏打印机是RP-POS80S或RP-POS80P或RP-POS80CS或RP-POS80CP打印机

* 360*360的图片,8个字节(8个像素点)是一个二进制,将二进制转化为十进制数值

* y轴:24个像素点为一组,即360就是15组(0-14)

* x轴:360个像素点(0-359)

* 里面的每一组(24*360),每8个像素点为一个二进制,(每组有3个,3*8=24)

**************************************************************************/

/**

* 把一张Bitmap图片转化为打印机可以打印的bit(将图片压缩为360*360)

* 效率很高(相对于下面)

* @param bit

* @return

*/

public static byte[] draw2PxPoint(Bitmap bit) {

byte[] data = new byte[16290];

int k = 0;

for (int j = 0; j < 15; j++) {

data[k++] = 0x1B;

data[k++] = 0x2A;

data[k++] = 33; // m=33时,选择24点双密度打印,分辨率达到200DPI。

data[k++] = 0x68;

data[k++] = 0x01;

for (int i = 0; i < 360; i++) {

for (int m = 0; m < 3; m++) {

for (int n = 0; n < 8; n++) {

byte b = px2Byte(i, j * 24 + m * 8 + n, bit);

data[k] += data[k] + b;

}

k++;

}

}

data[k++] = 10;

}

return data;

}

/**

* 把一张Bitmap图片转化为打印机可以打印的bit

* @param bit

* @return

*/

public static byte[] pic2PxPoint(Bitmap bit){

long start = System.currentTimeMillis();

byte[] data = new byte[16290];

int k = 0;

for (int i = 0; i < 15; i++) {

data[k++] = 0x1B;

data[k++] = 0x2A;

data[k++] = 33; // m=33时,选择24点双密度打印,分辨率达到200DPI。

data[k++] = 0x68;

data[k++] = 0x01;

for (int x = 0; x < 360; x++) {

for (int m = 0; m < 3; m++) {

byte[] by = new byte[8];

for (int n = 0; n < 8; n++) {

byte b = px2Byte(x, i * 24 + m * 8 +7-n, bit);

by
= b;

}

data[k] = (byte) changePointPx1(by);

k++;

}

}

data[k++] = 10;

}

long end = System.currentTimeMillis();

long str = end - start;

Log.i("TAG", "str:" + str);

return data;

}

/**

* 图片二值化,黑色是1,白色是0

* @param x 横坐标

* @param y 纵坐标

* @param bit 位图

* @return

*/

public static byte px2Byte(int x, int y, Bitmap bit) {

byte b;

int pixel = bit.getPixel(x, y);

int red = (pixel & 0x00ff0000) >> 16; // 取高两位

int green = (pixel & 0x0000ff00) >> 8; // 取中两位

int blue = pixel & 0x000000ff; // 取低两位

int gray = RGB2Gray(red, green, blue);

if ( gray < 128 ){

b = 1;

} else {

b = 0;

}

return b;

}

/**

* 图片灰度的转化

* @param r

* @param g

* @param b

* @return

*/

private static int RGB2Gray(int r, int g, int b){

int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b); //灰度转化公式

return gray;

}

/**

* 对图片进行压缩(去除透明度)

* @param bitmapOrg

*/

public static Bitmap compressPic(Bitmap bitmapOrg) {

// 获取这个图片的宽和高

int width = bitmapOrg.getWidth();

int height = bitmapOrg.getHeight();

// 定义预转换成的图片的宽度和高度

int newWidth = 360;

int newHeight = 360;

Bitmap targetBmp = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);

Canvas targetCanvas = new Canvas(targetBmp);

targetCanvas.drawColor(0xffffffff);

targetCanvas.drawBitmap(bitmapOrg, new Rect(0, 0, width, height), new Rect(0, 0, newWidth, newHeight), null);

return targetBmp;

}

/**

* 对图片进行压缩(不去除透明度)

* @param bitmapOrg

*/

public static Bitmap compressBitmap(Bitmap bitmapOrg) {

// 加载需要操作的图片,这里是一张图片

// Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.alipay);

// 获取这个图片的宽和高

int width = bitmapOrg.getWidth();

int height = bitmapOrg.getHeight();

// 定义预转换成的图片的宽度和高度

int newWidth = 360;

int newHeight = 360;

// 计算缩放率,新尺寸除原始尺寸

float scaleWidth = ((float) newWidth) / width;

float scaleHeight = ((float) newHeight) / height;

// 创建操作图片用的matrix对象

Matrix matrix = new Matrix();

// 缩放图片动作

matrix.postScale(scaleWidth, scaleHeight);

// 创建新的图片

Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width,height, matrix, true);

// 将上面创建的Bitmap转换成Drawable对象,使得其可以使用在ImageView, ImageButton中

// BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);

return resizedBitmap;

}

/**

* 将[1,0,0,1,0,0,0,1]这样的二进制转为化十进制的数值(效率更高)

* @param arry

* @return

*/

public static int changePointPx1(byte[] arry){

int v = 0;

for (int j = 0; j <arry.length; j++) {

if( arry[j] == 1) {

v = v | 1 << j;

}

}

return v;

}

/**

* 将[1,0,0,1,0,0,0,1]这样的二进制转为化十进制的数值

* @param arry

* @return

*/

public byte changePointPx(byte[] arry){

byte v = 0;

for (int i = 0; i < 8; i++) {

v += v + arry[i];

}

return v;

}

/**

* 得到位图的某个点的像素值

* @param bitmap

* @return

*/

public byte[] getPicPx(Bitmap bitmap){

int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];// 保存所有的像素的数组,图片宽×高

bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

for (int i = 0; i < pixels.length; i++) {

int clr = pixels[i];

int red = (clr & 0x00ff0000) >> 16; // 取高两位

int green = (clr & 0x0000ff00) >> 8; // 取中两位

int blue = clr & 0x000000ff; // 取低两位

System.out.println("r=" + red + ",g=" + green + ",b=" + blue);

}

return null;

}

}
复制代码
下面楼层继续...

package com.woyou.util;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.security.InvalidParameterException;

import java.text.DecimalFormat;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Locale;

import android.content.Context;

import android_serialport_api.SerialPort;

/**

* 打印机辅助

*

* @author nsz 2015年1月30日

*/

public class PrintUtil {

final static int BUFFER_SIZE = 4096;

/**

* 对一个byte[] 进行打印

* @param printText

* @return

* add by yidie

*/

public static boolean printBytes(byte[] printText) {

boolean returnValue = true;

try {

OutputStream mOutputStream = getSerialPort().getOutputStream();

mOutputStream.write(printText);

} catch (Exception ex) {

returnValue = false;

}

return returnValue;

}

/**

* "\n" 就是换行

* @param paramString

* @return

* add by yidie

*/

public static boolean printString(String paramString) {

return printBytes(getGbk(paramString));

}

/***************************************************************************

* add by yidie 2012-01-10 功能:设置打印绝对位置 参数: int 在当前行,定位光标位置,取值范围0至576点 说明:

* 在字体常规大小下,每汉字24点,英文字符12点 如位于第n个汉字后,则position=24*n

* 如位于第n个半角字符后,则position=12*n

****************************************************************************/

public static byte[] setCusorPosition(int position) {

byte[] returnText = new byte[4]; // 当前行,设置绝对打印位置 ESC $ bL bH

returnText[0] = 0x1B;

returnText[1] = 0x24;

returnText[2] = (byte) (position % 256);

returnText[3] = (byte) (position / 256);

return returnText;

}

/**

* 设置打印机的行高

* @param h

* @return

*/

public static byte[] setLineHeight(byte h) {

byte[] returnText = new byte[] { 0x1B, 0x33, h }; // 切纸; 1B 33 n

return returnText;

}

public static byte[] setDefaultLineHeight() {

byte[] returnText = new byte[] { 0x1B, 0x32 }; // 切纸; 1B 32

return returnText;

}

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

ByteArrayOutputStream outStream = new ByteArrayOutputStream();

byte[] data = new byte[BUFFER_SIZE];

int count = -1;

while ((count = in.read(data, 0, BUFFER_SIZE)) != -1)

outStream.write(data, 0, count);

data = null;

return outStream.toByteArray();

}

/**

* 打印我有外卖的logo

* @param c

*/

public static void printLogo(Context c) {

PrintUtil.printBytes(PrintUtil.setLineHeight((byte) 0));

InputStream is = c.getClass().getResourceAsStream("/assets/bill.bin");

byte[] b;

try {

b = InputStreamTOByte(is);

PrintUtil.printBytes(b);

PrintUtil.printBytes(PrintUtil.setDefaultLineHeight());

} catch (Exception e) {

e.printStackTrace();

}

}

public static byte[] getLogo(Context c) {

InputStream is = c.getClass().getResourceAsStream("/assets/bill.bin");

byte[] b;

try {

b = InputStreamTOByte(is);

return b;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

* 得到店铺logo

* @param c

* @param bit

* @return

*/

public static byte[] getLogo(Context c, byte[] bit) {

InputStream is = c.getClass().getResourceAsStream("/assets/bill.bin");

byte[] b = bit;

try {

b = InputStreamTOByte(is);

return b;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

public static byte[] getLogo(byte[] bs) {

byte[] b;

try {

b = bs;

return b;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

* 支付打印(二维码)

* @param b

* @param money

* @return

* @throws InvalidParameterException

* @throws SecurityException

* @throws IOException

*/

public static boolean printAlipayTitle(byte[] b, String money)

throws InvalidParameterException, SecurityException, IOException {

int iNum = 0;

byte[] tempBuffer = new byte[1000];

byte[] oldText = setAlignCenter('2');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('4');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setBold(true);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("支付凭证\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setAlignCenter('2');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('3');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setBold(true);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("您共消费了" + money + "元\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setAlignCenter('2');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('3');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setBold(true);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("请扫码支付\n\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

SerialPort mSerialPort = getSerialPort();

OutputStream mOutputStream = mSerialPort.getOutputStream();

try {

mOutputStream.write(tempBuffer);

printBytes(b);

printString("\n\n\n");

printBytes(CutPaper());

} catch (IOException e) {

e.printStackTrace();

return false;

}

return true;

}

/***************************************************************************

* add by yidie 2012-01-10 功能:订单打印 参数: String 订单短号 OrderDetail 打印内容,包含

* GoodsInfo[] String 打印标题

****************************************************************************/

public static boolean printOrder(Context c, byte[] b)

throws InvalidParameterException, SecurityException, IOException {

DecimalFormat dcmFmt = new DecimalFormat("0.00");

int iNum = 0, i;

byte[] tempBuffer = new byte[8000];

String stTmp = "";

byte[] oldText = setAlignCenter('2');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getLogo(c, b);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setAlignCenter('2');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('4');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setBold(true);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setAlignCenter('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setCusorPosition(324);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

String strTime = new SimpleDateFormat("yyyy-MM-dd HH:mm",

Locale.SIMPLIFIED_CHINESE).format(new Date());

oldText = getGbk(strTime + "打印\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setBold(false);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("----------------------------------------------\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('3');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk(" 商品名称 单价 数量 金额\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("----------------------------------------------\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('3');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setAlignCenter('2');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("\n感谢使用[我有外卖]订餐,24小时服务热线 4008519517\n\n\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = CutPaper();

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

SerialPort mSerialPort = getSerialPort();

OutputStream mOutputStream = mSerialPort.getOutputStream();

try {

mOutputStream.write(tempBuffer);

} catch (IOException e) {

e.printStackTrace();

return false;

}

return true;

}

/***************************************************************************

* add by yidie 2012-01-12 功能:报表打印 参数: String 打印标题,如“月报表:2013-01”

* ReportUserSale 打印内容,包含 UserSaleInfo[]

****************************************************************************/

public static boolean printReportUser() throws InvalidParameterException,

SecurityException, IOException {

int iNum = 0;

String stTmp = "";

byte[] tempBuffer = new byte[8000];

SerialPort mSerialPort = getSerialPort();

OutputStream mOutputStream = mSerialPort.getOutputStream();

byte[] oldText = setAlignCenter('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('3');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setCusorPosition(324);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

String strTime = new SimpleDateFormat("yyyy-MM-dd HH:mm",

Locale.SIMPLIFIED_CHINESE).format(new Date());

oldText = getGbk(strTime + "打印\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setAlignCenter('2');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('4');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setBold(true);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("\n\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setAlignCenter('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setBold(false);

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = setWH('1');

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("   用户        售出数量 售出金额\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = getGbk("----------------------------------------------\n");

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

oldText = CutPaper();

System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

iNum += oldText.length;

try {

mOutputStream.write(tempBuffer);

} catch (IOException e) {

e.printStackTrace();

return false;

}

return true;

}

/***************************************************************************

* add by yidie 2012-01-12 功能:报表打印 参数: String 打印标题,如“月报表:2013-01” ReportSale

* 打印内容,包含 SaleInfo[]

****************************************************************************/

private static SerialPort mSerialPort = null;

public static SerialPort getSerialPort() throws SecurityException,

IOException, InvalidParameterException {

if (mSerialPort == null) {

String spFile = null;

String model = MainBoardUtil.getModel(); // android.os.Build.MODEL.toLowerCase();

if (model.contains(Constants.MAIN_BOARD_SMDKV210)) {

spFile = "/dev/s3c2410_serial0";

} else if (model.contains(Constants.MAIN_BOARD_RK30)) {

spFile = "/dev/ttyS1";

} else if (model.contains(Constants.MAIN_BOARD_C500)) {

spFile = "/dev/ttyS1";

} else {

throw new IOException("unknow hardware!");

}

int baudrate = 115200;

boolean flagCon = true;

File myFile = new File(spFile);

/* Open the serial port */

mSerialPort = new SerialPort(myFile, baudrate, 0, flagCon);

}

return mSerialPort;

}

public static void closeSerialPort() {

if (mSerialPort != null) {

mSerialPort.close();

mSerialPort = null;

}

}

public static byte[] getGbk(String stText) {

byte[] returnText = null;

try {

returnText = stText.getBytes("GBK"); // 必须放在try内才可以

} catch (Exception ex) {

;

}

return returnText;

}

public static byte[] setWH(char dist) {

byte[] returnText = new byte[3]; // GS ! 11H 倍宽倍高

returnText[0] = 0x1D;

returnText[1] = 0x21;

switch (dist) // 1-无;2-倍宽;3-倍高; 4-倍宽倍高

{

case '2':

returnText[2] = 0x10;

break;

case '3':

returnText[2] = 0x01;

break;

case '4':

returnText[2] = 0x11;

break;

default:

returnText[2] = 0x00;

break;

}

return returnText;

}

/**

* 打印的对齐方式

* @param dist

* @return

*/

public static byte[] setAlignCenter(char dist) {

byte[] returnText = new byte[3]; // 对齐 ESC a

returnText[0] = 0x1B;

returnText[1] = 0x61;

switch (dist) // 1-左对齐;2-居中对齐;3-右对齐

{

case '2':

returnText[2] = 0x01;

break;

case '3':

returnText[2] = 0x02;

break;

default:

returnText[2] = 0x00;

break;

}

return returnText;

}

public static byte[] setBold(boolean dist) {

byte[] returnText = new byte[3]; // 加粗 ESC E

returnText[0] = 0x1B;

returnText[1] = 0x45;

if (dist) {

returnText[2] = 0x01; // 表示加粗

} else {

returnText[2] = 0x00;

}

return returnText;

}

public static byte[] PrintBarcode(String stBarcode) {

int iLength = stBarcode.length() + 4;

byte[] returnText = new byte[iLength];

returnText[0] = 0x1D;

returnText[1] = 'k';

returnText[2] = 0x45;

returnText[3] = (byte) stBarcode.length(); // 条码长度;

System.arraycopy(stBarcode.getBytes(), 0, returnText, 4,

stBarcode.getBytes().length);

return returnText;

}

/**

* 切纸

* @return

*/

public static byte[] CutPaper() {

byte[] returnText = new byte[] { 0x1D, 0x56, 0x42, 0x00 }; // 切纸; GS V

// 66D 0D

return returnText;

}

}

复制代码package com.woyou.woyoupay;

import java.io.IOException;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;

import org.json.JSONException;

import org.json.JSONObject;

import android.app.Activity;

import android.app.ProgressDialog;

import android.content.Intent;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.drawable.Drawable;

import android.os.Bundle;

import android.text.Html;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.Window;

import android.widget.ImageView;

import android.widget.TextView;

import com.anjoyo.net.AsyncHttpClient;

import com.anjoyo.net.JsonHttpResponseHandler;

import com.anjoyo.net.RequestParams;

import com.woyou.R;

import com.woyou.bean.ScanCodeRes;

import com.woyou.util.Constants;

import com.woyou.util.PicFromPrintUtils;

import com.woyou.util.PrintUtil;

import com.woyou.util.ThreadPoolManager;

public class Print2DCodeAct extends Activity implements OnClickListener {

private static final String TAG = "Print2DCodeAct";

TextView back, print, motifiscan;

TextView oId, money, price;

ImageView printImg;

ProgressDialog dialog;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_print2dcode);

initView();

}

String extra;

private void initView() {

Intent intent = getIntent();

extra = intent.getStringExtra("money");

back = (TextView) this.findViewById(R.id.back);

oId = (TextView) this.findViewById(R.id.order_id);

back.setOnClickListener(this);

motifiscan = (TextView) this.findViewById(R.id.motifiscan);

print = (TextView) this.findViewById(R.id.print_image);

printImg = (ImageView) this.findViewById(R.id.print_two_image);

money = (TextView) this.findViewById(R.id.money);

print.setOnClickListener(this);

motifiscan.setOnClickListener(this);

money.setText(Html.fromHtml("¥<big>" + extra + "</big>"));

//显示图片

// Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(), R.drawable.alipay);

// Bitmap bitmap = compressPic(bitmapOrg);

// image_alipy.setImageBitmap(bitmap);

//请求数据

getData();

}

private void showDialog() {

if (dialog == null) {

dialog = new ProgressDialog(this);

dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

dialog.setCancelable(true);

dialog.setMessage("正在加载中,请稍候...");

}

dialog.show();

}

private void hideDialog() {

runOnUiThread(new Runnable() {

@Override

public void run() {

if (dialog != null) {

dialog.dismiss();

}

}

});

}

@Override

protected void onResume() {

super.onResume();

Constants.ACTIVITY_INSTANCE = Print2DCodeAct.this;

}

List<ScanCodeRes> list = new ArrayList<ScanCodeRes>();

Bitmap compressPic = null;

String big_pic_url;

String pic_url;

String small_pic_url;

private void getData() {

float f = Float.parseFloat(extra) * 100;

int inte = (int) f;

long parseLong = Long.parseLong(String.valueOf(inte));

String sign = Constants.md5("100512354" + "150039203" + Constants.KEY);

String url = "http://api.coupon.dev.wosai.cn/Upay/alipayQrCodeOffline";

AsyncHttpClient client = new AsyncHttpClient();

RequestParams params = new RequestParams();

params.put("store_own_order_id", "1234");

params.put("subject", "喔噻体验商品");

params.put("total_fee", parseLong+"");

params.put("wosai_store_id", "100512354");

params.put("wosai_app_id", "150039203");

params.put("sign", sign);

params.put("notify_url", "http://www.woyouwaimai.com/get"); //推送支付成功的通知

Log.i(TAG, url + params);

client.get(url, params, new JsonHttpResponseHandler() {

@Override

public void onStart() {

super.onStart();

showDialog();

}

@Override

public void onSuccess(JSONObject response) {

super.onSuccess(response);

try {

String code = response.getString("code");

String msg = response.getString("msg");

Log.i(TAG, "code:" + code);

Log.i(TAG, "msg:" + msg);

if ("10000".equals(code)) {

JSONObject data = response.getJSONObject("data");

String order_sn = data.getString("order_sn");

String wosai_store_id = data.getString("wosai_store_id");

int status = data.getInt("status");

String ctime = data.getString("ctime");

JSONObject order_pay_detail = data.getJSONObject("order_pay_detail");

String order_detail = data.getString("order_detail");

String pay_way = data.getString("pay_way");

long total_fee = data.getLong("total_fee");

String is_success = order_pay_detail.getString("is_success");

JSONObject responses = order_pay_detail.getJSONObject("response");

String sign = order_pay_detail.getString("sign");

String sign_type = order_pay_detail.getString("sign_type");

JSONObject alipay = responses.getJSONObject("alipay");

big_pic_url = alipay.getString("big_pic_url");

String out_trade_no = alipay.getString("out_trade_no");

pic_url = alipay.getString("pic_url");

String qr_code = alipay.getString("qr_code");

String result_code = alipay.getString("result_code");

small_pic_url = alipay.getString("small_pic_url");

String voucher_type = alipay.getString("voucher_type");

Log.i(TAG, "big_pic_url:" + big_pic_url);

Log.i(TAG, "pic_url:" + pic_url);

Log.i(TAG, "small_pic_url:" + small_pic_url);

ScanCodeRes res = new ScanCodeRes();

res.setOrder_sn(order_sn);

res.setWosai_store_id(wosai_store_id);

res.setStatus(status);

res.setCtime(ctime);

res.setIs_success(is_success);

res.setOrder_detail(order_detail);

res.setTotal_fee(total_fee);

res.setPay_way(pay_way);

list.add(res);

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

}

} catch (JSONException e) {

e.printStackTrace();

hideDialog();

}

}

@Override

public void onFinish() {

super.onFinish();

ThreadPoolManager.getInstance().executeTask(new Runnable() {

@Override

public void run() {

try {

Bitmap bitmap = BitmapFactory.decodeStream(new URL(pic_url).openStream());

compressPic = PicFromPrintUtils.compressPic(bitmap);

}catch (IOException e) {

e.printStackTrace();

}

runOnUiThread(new Runnable() {

@Override

public void run() {

printImg.setImageBitmap(compressPic);

print2Code(compressPic);

hideDialog();

}

});

}

});

}

});

}

//打印二维码

private void print2Code(Bitmap bitmap){

final byte[] bs = PicFromPrintUtils.draw2PxPoint(bitmap);

ThreadPoolManager.getInstance().executeTask(new Runnable() {

@Override

public void run() {

try {

PrintUtil.printAlipayTitle(bs, extra);

} catch (Exception e) {

e.printStackTrace();

}

}

});

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.print_image:

if ( compressPic != null ){

print2Code(compressPic);

}

break;

case R.id.back:

finish();

break;

case R.id.motifiscan:

Intent intent = new Intent(this, HomeAct.class);

intent.putExtra("money", extra);

startActivity(intent);

break;

}

}

public Drawable loadImageFromNetwork(String urladdr) {

Drawable drawable = null;

try {

drawable = Drawable.createFromStream(new URL(urladdr).openStream(),"image.jpg");

} catch (IOException e) {

Log.d("test", e.getMessage());

}

if (drawable == null) {

Log.d("test", "null drawable");

} else {

Log.d("test", "not null drawable");

}

return drawable;

}

// 计算图片的缩放值

public static int calculateInSampleSize(BitmapFactory.Options options,

int reqWidth, int reqHeight) {

final int height = options.outHeight;

final int width = options.outWidth;

int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

final int heightRatio = Math.round((float) height

/ (float) reqHeight);

final int widthRatio = Math.round((float) width / (float) reqWidth);

inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

}

return inSampleSize;

}

}

复制代码

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

原文 http://www.eoeandroid.com/thread-564903-1-1.html?_dsign=50a25db8
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 热敏打印机