最近在做小票打印这块,项目需求是蓝牙和WiFi两种都要实现,开始做的时候也是一脸懵,然后网上找了一些代码,看了好多博主的文章,最后自己把这些都综合到一起0.0,结果还好成功了
先看看图吧,蓝牙和WiFi打印出的都是一样的,毕竟都是同一个工具类(打印机型号 爱宝POS-80C 、 资江 ZJ-80)
先来看看WiFi打印(旁边的色块是打印纸自带的,我也很无奈)
首先在你的activity里触发点击事件
right = (TextView) findViewById(R.id.right);//点击WiFi打印 right.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { pos(); } }); //调用打印的方法
private void pos() {
// 开启一个子线程
new Thread() {
public void run() {
try { //打印机网口IP 打印机端口号 编码方式
pos = new Pos(Preference.instance(PayTypeActivity.this).getIPAddress(), Integer.parseInt(Preference.instance(PayTypeActivity.this).getPost_IDs()), "gbk");
//初始化打印机
pos.initPos();
if (!TextUtils.isEmpty(objBean.getHead_img())){
pos.printLocation(1);
bitmap = pos.compressPic(returnBitMap(objBean.getHead_img()));
pos.draw2PxPoint(bitmap);
}
pos.printLocation(1);
pos.bold(true);
pos.printTabSpace(2);
pos.printWordSpace(1);
pos.printTextNewLine(objBean.getShop_name());
pos.printLocation(0);
pos.printTextNewLine("----------------------------------------------");
pos.bold(false);
pos.printTextNewLine("订 单 号:"+objBean.getSn());
pos.printTextNewLine("用 户 名:"+objBean.getMember());
pos.printTextNewLine("订单日期:"+objBean.getCreate_time());
pos.printTextNewLine("支付方式:"+objBean.getPay_way());
pos.printTextNewLine("订单折扣:"+objBean.getDiscount());
pos.printTextNewLine("订单备注:"+objBean.getRemarks());
pos.printLine(2);
pos.printText("货号 尺码 颜色 数量 小计");
pos.printLocation(20, 1);
pos.printTextNewLine("----------------------------------------------");
for (ParentBean foods : foodsBean) {
pos.printTextNewLine(foods.getGoods_name()+" "+foods.getCode_number()+" "+foods.getColour()+" "+foods.getNum()+" "+foods.getPay_back());
pos.printLocation(20, 1);
}
pos.printTextNewLine("----------------------------------------------");
pos.printLocation(0);
pos.printLine(1);
pos.printTextNewLine("订单总数:"+objBean.getNums());
pos.printTextNewLine("应收金额:"+objBean.getActual_pay());
pos.printTextNewLine("优惠金额:"+objBean.getDiscount_pay());
pos.printTextNewLine("实收金额:"+objBean.getPay());
pos.printLine(2);
// //打印二维码 -- 如果提供了二维码的地址则用该方法
// pos.qrCode(objBean.getQr_code());
//打印二维码的图片 -- 如果提供了二维码的截图则用该方法
if (!TextUtils.isEmpty(objBean.getQr_code())){
pos.printLocation(1);
Qbitmap = pos.compressPic(returnBitMap(objBean.getQr_code()));//url 转换为bitmap
pos.draw2PxPoint(Qbitmap);
}
//切纸
pos.feedAndCut();
pos.closeIOAndSocket();
pos = null;
} catch (UnknownHostException e) {
e.printStackTrace();
showToast(e.toString());
Log.d("tag", "错误信息1:" + e.toString());
} catch (IOException e) {
e.printStackTrace();
showToast(e.toString());
Log.d("tag", "错误信息2:" + e.toString());
}
}
}.start();
}
//将图片url转换为bitmap
public Bitmap returnBitMap(String url) {
URL myFileUrl = null;
Bitmap bitmap = null;
try {
myFileUrl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
再来看看调用的工具类(蓝牙和WiFi共用一个,只是初始化方式不同)
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class Pos {
//定义编码方式
private static String encoding = null;
private Socket sock = null;
// 通过socket流进行读写
private OutputStream socketOut = null;
private OutputStreamWriter writer = null;
/**
* 初始化Pos实例
*
* @param ip 打印机IP
* @param port 打印机端口号
* @param encoding 编码
* @throws IOException
*/
public Pos(String ip, int port, String encoding) throws IOException {
sock = new Socket(ip, port);
socketOut = new DataOutputStream(sock.getOutputStream());
this.encoding = encoding;
writer = new OutputStreamWriter(socketOut, encoding);
}
//蓝牙初始化
public Pos(OutputStream outputStream, String encoding) throws IOException {
writer = new OutputStreamWriter(outputStream, encoding);
socketOut = outputStream;
initPrinter();
}
public void print(byte[] bs) throws IOException {
socketOut.write(bs);
}
public void printRawBytes(byte[] bytes) throws IOException {
socketOut.write(bytes);
socketOut.flush();
}
/**
* 初始化打印机
*
* @throws IOException
*/
public void initPrinter() throws IOException {
socketOut.write(0x1B);
socketOut.write(0x40);
socketOut.flush();
}
/**
* 关闭IO流和Socket
*
* @throws IOException
*/
public void closeIOAndSocket() throws IOException {
writer.close();
socketOut.close();
sock.close();
}
/**
* 打印二维码
*
* @param qrData 二维码的内容
* @throws IOException
*/
public void qrCode(String qrData) throws IOException {
int moduleSize = 8;
int length = qrData.getBytes(encoding).length;
//打印二维码矩阵
writer.write(0x1D);// init
writer.write("(k");// adjust height of barcode
writer.write(length + 3); // pl
writer.write(0); // ph
writer.write(49); // cn
writer.write(80); // fn
writer.write(48); //
writer.write(qrData);
writer.write(0x1D);
writer.write("(k");
writer.write(3);
writer.write(0);
writer.write(49);
writer.write(69);
writer.write(48);
writer.write(0x1D);
writer.write("(k");
writer.write(3);
writer.write(0);
writer.write(49);
writer.write(67);
writer.write(moduleSize);
writer.write(0x1D);
writer.write("(k");
writer.write(3); // pl
writer.write(0); // ph
writer.write(49); // cn
writer.write(81); // fn
writer.write(48); // m
writer.flush();
}
/**
* 进纸并全部切割
*
* @return
* @throws IOException
*/
public void feedAndCut() throws IOException {
writer.write(0x1D);
writer.write(86);
writer.write(65);
// writer.write(0);
//切纸前走纸多少
writer.write(100);
writer.flush();
//另外一种切纸的方式
// byte[] bytes = {29, 86, 0};
// socketOut.write(bytes);
}
/**
* 打印换行
*
* @return length 需要打印的空行数
* @throws IOException
*/
public void printLine(int lineNum) throws IOException {
for (int i = 0; i < lineNum; i++) {
writer.write("\n");
}
writer.flush();
}
/**
* 打印换行(只换一行)
*
* @throws IOException
*/
protected void printLine() throws IOException {
writer.write("\n");
writer.flush();
}
/**
* 打印空白(一个Tab的位置,约4个汉字)
*
* @param length 需要打印空白的长度,
* @throws IOException
*/
public void printTabSpace(int length) throws IOException {
for (int i = 0; i < length; i++) {
writer.write("\t");
}
writer.flush();
}
/**
* 打印空白(一个汉字的位置)
*
* @param length 需要打印空白的长度,
* @throws IOException
*/
public void printWordSpace(int length) throws IOException {
for (int i = 0; i < length; i++) {
writer.write(" ");
}
writer.flush();
}
/**
* 打印位置调整
*
* @param position 打印位置 0:居左(默认) 1:居中 2:居右
* @throws IOException
*/
public void printLocation(int position) throws IOException {
writer.write(0x1B);
writer.write(97);
writer.write(position);
writer.flush();
}
/**
* 绝对打印位置
*
* @throws IOException
*/
public void printLocation(int light, int weight) throws IOException {
writer.write(0x1B);
writer.write(0x24);
writer.write(light);
writer.write(weight);
writer.flush();
}
/**
* 打印文字
*
* @param text
* @throws IOException
*/
public void printText(String text) throws IOException {
String s = text;
byte[] content = s.getBytes("gbk");
socketOut.write(content);
socketOut.flush();
}
/**
* 新起一行,打印文字
*
* @param text
* @throws IOException
*/
public void printTextNewLine(String text) throws IOException {
//换行
writer.write("\n");
writer.flush();
String s = text;
byte[] content = s.getBytes("gbk");
socketOut.write(content);
socketOut.flush();
}
/**
* 初始化打印机
*
* @throws IOException
*/
public void initPos() throws IOException {
writer.write(0x1B);
writer.write(0x40);
writer.flush();
}
/**
* 加粗
*
* @param flag false为不加粗
* @return
* @throws IOException
*/
public void bold(boolean flag) throws IOException {
if (flag) {
//常规粗细
writer.write(0x1B);
writer.write(69);
writer.write(0xF);
writer.flush();
} else {
//加粗
writer.write(0x1B);
writer.write(69);
writer.write(0);
writer.flush();
}
}
/**
* 对图片进行压缩(去除透明度)
*
* @param
*/
public static Bitmap compressPic(Bitmap bitmap) {
// 获取这个图片的宽和高
int width = bitmap.getWidth();
int height = bitmap.getHeight();
// 指定调整后的宽度和高度
int newWidth = 200;
int newHeight = 200;
Bitmap targetBmp = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
Canvas targetCanvas = new Canvas(targetBmp);
targetCanvas.drawColor(0xffffffff);
targetCanvas.drawBitmap(bitmap, new Rect(0, 0, width, height), new Rect(0, 0, newWidth, newHeight), null);
return targetBmp;
}
/**
* 灰度图片黑白化,黑色是1,白色是0
*
* @param x 横坐标
* @param y 纵坐标
* @param bit 位图
* @return
*/
public static byte px2Byte(int x, int y, Bitmap bit) {
if (x < bit.getWidth() && y < bit.getHeight()) {
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;
}
return 0;
}
/**
* 图片灰度的转化
*/
private static int RGB2Gray(int r, int g, int b) {
int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b); //灰度转化公式
return gray;
}
/*************************************************************************
* 假设一个240*240的图片,分辨率设为24, 共分10行打印
* 每一行,是一个 240*24 的点阵, 每一列有24个点,存储在3个byte里面。
* 每个byte存储8个像素点信息。因为只有黑白两色,所以对应为1的位是黑色,对应为0的位是白色
**************************************************************************/
/**
* 把一张Bitmap图片转化为打印机可以打印的字节流
*
* @param bmp
* @return
*/
public void draw2PxPoint(Bitmap bmp) throws IOException {
//用来存储转换后的 bitmap 数据。为什么要再加1000,这是为了应对当图片高度无法
//整除24时的情况。比如bitmap 分辨率为 240 * 250,占用 7500 byte,
//但是实际上要存储11行数据,每一行需要 24 * 240 / 8 =720byte 的空间。再加上一些指令存储的开销,
//所以多申请 1000byte 的空间是稳妥的,不然运行时会抛出数组访问越界的异常。
int size = bmp.getWidth() * bmp.getHeight() / 8 + 1000;
byte[] data = new byte[size];
int k = 0;
//设置行距为0的指令
data[k++] = 0x1B;
data[k++] = 0x33;
data[k++] = 0x00;
// 逐行打印
for (int j = 0; j < bmp.getHeight() / 24f; j++) {
//打印图片的指令
data[k++] = 0x1B;
data[k++] = 0x2A;
data[k++] = 33;
data[k++] = (byte) (bmp.getWidth() % 256); //nL
data[k++] = (byte) (bmp.getWidth() / 256); //nH
//对于每一行,逐列打印
for (int i = 0; i < bmp.getWidth(); i++) {
//每一列24个像素点,分为3个字节存储
for (int m = 0; m < 3; m++) {
//每个字节表示8个像素点,0表示白色,1表示黑色
for (int n = 0; n < 8; n++) {
byte b = px2Byte(i, j * 24 + m * 8 + n, bmp);
data[k] += data[k] + b;
}
k++;
}
}
data[k++] = 10;//换行
}
socketOut.write(data);
socketOut.flush();
}
}
WiFi打印小票到此基本上就可以了
下面开始我们的蓝牙打印
蓝牙打印的话首先就要有权限
//蓝牙权限
再来看看蓝牙相关的布局
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_height="48dp"
android:background="@color/colorGrayTertiary"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:text="选择一个已配对的打印设备 (请确保打印机和平板的蓝牙已开通)"
android:textColor="@color/textColorSecondary"
android:textSize="14sp" />
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/colorWhite"
android:choiceMode="singleChoice"
android:divider="@android:drawable/divider_horizontal_bright" />
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
android:text="测试打印机连接" />
接着具体看看代码里面怎么实现的,包括蓝牙的一些检索和设置
public class PrinterSettingActivity extends BasePrintActivity implements View.OnClickListener{
private Root root;
private String result;
private ObjBean obj;
private ObjBean objBean;
private List
private List
ListView mLvPairedDevices;
Button mBtnSetting;
Button mBtnTest;
Button mBtnPrint;
DeviceListAdapter mAdapter;
int mSelectedPosition = -1;
final static int TASK_TYPE_CONNECT = 1;
final static int TASK_TYPE_PRINT = 2;
private String id;
private Pos pos;
private OutputStream mOutputStream = null;
private Bitmap head_bitmap;
private Bitmap code_bitmap;
private LinearLayout back;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_printer_setting);
id = getIntent().getStringExtra("id");
setTitle("蓝牙打印");
initViews();
print();//获取小票数据
}
private void print() {
HttpUtil.ticket(this, id, new HttpUtil.KWiListener() {
@Override
public void onResult(int ret, Object msg) {
Log.d("tag", "打印小票: " + msg.toString());
Gson gson = new Gson();
String jsonString = msg.toString();
root = gson.fromJson(jsonString, Root.class);
result = root.getResult().getResultCode();
if (result.equals("0")) {
objBean = root.getObj();
foodsBean = objBean.getParent();
} else {
ToastUtil.show(root.getResult().getResultMessage());
}
}
});
}
@Override
protected void onResume() {
super.onResume();
fillAdapter();
}
private void initViews() {
back = (LinearLayout) findViewById(R.id.back);
back.setOnClickListener(this);
mLvPairedDevices = (ListView) findViewById(R.id.lv_paired_devices);
mBtnSetting = (Button) findViewById(R.id.btn_goto_setting);
mBtnTest = (Button) findViewById(R.id.btn_test_conntect);
mBtnPrint = (Button) findViewById(R.id.btn_print);
mLvPairedDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
mSelectedPosition = position;
mAdapter.notifyDataSetChanged();
}
});
mBtnSetting.setOnClickListener(this);
mBtnTest.setOnClickListener(this);
mBtnPrint.setOnClickListener(this);
mAdapter = new DeviceListAdapter(this);
mLvPairedDevices.setAdapter(mAdapter);
}
/**
* 从所有已配对设备中找出打印设备并显示
*/
private void fillAdapter() {
//推荐使用 BluetoothUtil.getPairedPrinterDevices()
List
mAdapter.clear();
mAdapter.addAll(printerDevices);
refreshButtonText(printerDevices);
}
private void refreshButtonText(List
if (printerDevices.size() > 0) {
mBtnSetting.setText("配对更多设备");
} else {
mBtnSetting.setText("还未配对打印机,去设置");
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_goto_setting:
startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
break;
case R.id.btn_test_conntect:
connectDevice(TASK_TYPE_CONNECT);
break;
case R.id.btn_print:
connectDevice(TASK_TYPE_PRINT);
break;
case R.id.back:
finish();
break;
default:
break;
}
}
private void connectDevice(int taskType){
if(mSelectedPosition >= 0){
BluetoothDevice device = mAdapter.getItem(mSelectedPosition);
if(device!= null)
super.connectDevice(device, taskType);
}else{
Toast.makeText(this, "还未选择打印设备", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onConnected(BluetoothSocket socket, int taskType) {
switch (taskType){
case TASK_TYPE_PRINT:
if(socket != null&&socket.isConnected()){
pos(socket);
}
break;
}
}
private void pos(final BluetoothSocket socket) {
// 开启一个子线程
new Thread() {
public void run() {
try {
//初始化打印机
pos = new Pos(socket.getOutputStream(),"GBK");
if (!TextUtils.isEmpty(objBean.getHead_img())){
pos.printLocation(1);
head_bitmap = pos.compressPic(returnBitMap(objBean.getHead_img()));
pos.draw2PxPoint(head_bitmap);
}
pos.printLocation(1);
pos.bold(true);
pos.printTabSpace(2);
pos.printWordSpace(1);
pos.printTextNewLine(objBean.getShop_name());
pos.printLocation(0);
pos.printTextNewLine("----------------------------------------------");
pos.bold(false);
pos.printTextNewLine("订 单 号:"+objBean.getSn());
pos.printTextNewLine("用 户 名:"+objBean.getMember());
pos.printTextNewLine("订单日期:"+objBean.getCreate_time());
pos.printTextNewLine("支付方式:"+objBean.getPay_way());
pos.printTextNewLine("订单折扣:"+objBean.getDiscount());
pos.printTextNewLine("订单备注:"+objBean.getRemarks());
pos.printLine(2);
pos.printText("货号 尺码 颜色 数量 小计");
pos.printLocation(20, 1);
pos.printTextNewLine("----------------------------------------------");
for (ParentBean foods : foodsBean) {
pos.printTextNewLine(foods.getGoods_name()+" "+foods.getCode_number()+" "+foods.getColour()+" "+foods.getNum()+" "+foods.getPay_back());
pos.printLocation(20, 1);
}
pos.printTextNewLine("----------------------------------------------");
pos.printLocation(0);
pos.printLine(1);
pos.printTextNewLine("订单总数:"+objBean.getNums());
pos.printTextNewLine("应收金额:"+objBean.getActual_pay());
pos.printTextNewLine("优惠金额:"+objBean.getDiscount_pay());
pos.printTextNewLine("实收金额:"+objBean.getPay());
pos.printLine(2);
//打印二维码 -- 如果提供了二维码的地址则用该方法
// pos.qrCode(objBean.getQr_code());
//打印二维码的图片 -- 如果提供了二维码的截图则用该方法
if (!TextUtils.isEmpty(objBean.getQr_code())){
pos.printLocation(1);
code_bitmap = pos.compressPic(returnBitMap(objBean.getQr_code()));
pos.draw2PxPoint(code_bitmap);
}
pos.printLine(4);
//切纸
pos.feedAndCut();
// pos.closeIOAndSocket();
pos = null;
} catch (UnknownHostException e) {
Log.d("tag", "错误信息1:" + e.toString());
} catch (IOException e) {
Log.d("tag", "错误信息2:" + e.toString());
}
}
}.start();
}
class DeviceListAdapter extends ArrayAdapter
public DeviceListAdapter(Context context) {
super(context, 0);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
BluetoothDevice device = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_bluetooth_device, parent, false);
}
TextView tvDeviceName = (TextView) convertView.findViewById(R.id.tv_device_name);
CheckBox cbDevice = (CheckBox) convertView.findViewById(R.id.cb_device);
tvDeviceName.setText(device.getName());
cbDevice.setChecked(position == mSelectedPosition);
return convertView;
}
}
public Bitmap returnBitMap(String url) {
URL myFileUrl = null;
Bitmap bitmap = null;
try {
myFileUrl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
}
R.layout.item_bluetooth_device的布局如下:
android:layout_height="48dp"
android:paddingLeft="@dimen/common_margin"
android:paddingRight="@dimen/common_margin">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="蓝牙打印机"
android:textColor="@color/textColorPrimary"
android:textSize="14sp" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:textSize="14sp" />
最后还是打印小票的方法 pos(socket);这个方法和之前WiFi方法基本一致,只是初始化不一样
private void pos(final BluetoothSocket socket) {
// 开启一个子线程
new Thread() {
public void run() {
try {
//初始化打印机
pos = new Pos(socket.getOutputStream(),"GBK");
if (!TextUtils.isEmpty(objBean.getHead_img())){
pos.printLocation(1);
head_bitmap = pos.compressPic(returnBitMap(objBean.getHead_img()));
pos.draw2PxPoint(head_bitmap);
}
pos.printLocation(1);
pos.bold(true);
pos.printTabSpace(2);
pos.printWordSpace(1);
pos.printTextNewLine(objBean.getShop_name());
pos.printLocation(0);
pos.printTextNewLine("----------------------------------------------");
pos.bold(false);
pos.printTextNewLine("订 单 号:"+objBean.getSn());
pos.printTextNewLine("用 户 名:"+objBean.getMember());
pos.printTextNewLine("订单日期:"+objBean.getCreate_time());
pos.printTextNewLine("支付方式:"+objBean.getPay_way());
pos.printTextNewLine("订单备注:"+objBean.getRemarks());
pos.printLine(2);
pos.printText("货号 尺码 颜色 数量 小计");
pos.printLocation(20, 1);
pos.printTextNewLine("----------------------------------------------");
for (ParentBean foods : foodsBean) {
pos.printTextNewLine(foods.getGoods_name()+" "+foods.getCode_number()+" "+foods.getColour()+" "+foods.getNum()+" "+foods.getPay_back());
pos.printLocation(20, 1);
}
pos.printTextNewLine("----------------------------------------------");
pos.printLocation(0);
pos.printLine(1);
pos.printTextNewLine("总数:"+objBean.getNums());
pos.printTextNewLine("合计:"+objBean.getPay());
pos.printLine(2);
//打印二维码 -- 如果提供了二维码的地址则用该方法
// pos.qrCode(objBean.getQr_code());
//打印二维码的图片 -- 如果提供了二维码的截图则用该方法
if (!TextUtils.isEmpty(objBean.getQr_code())){
pos.printLocation(1);
code_bitmap = pos.compressPic(returnBitMap(objBean.getQr_code()));//returnBitmap方法和上面WiFi的一样
pos.draw2PxPoint(code_bitmap);
}
pos.printLine(4);
//切纸
pos.feedAndCut();
// pos.closeIOAndSocket();
pos = null;
} catch (UnknownHostException e) {
Log.d("tag", "错误信息1:" + e.toString());
} catch (IOException e) {
Log.d("tag", "错误信息2:" + e.toString());
}
}
}.start();
}
到此的话基本两种方式都可以了,我用两台打印机试过都没问题
下载地址:https://download.csdn.net/download/u011056653/10567104