之前做过USB打印机,但是现在需求变了,不是使用收银台进行打印机的连接了,而是使用手机与打印机进行打印。手机又无法像收银机一样直接使用USB直接与打印机直接连接进行打印。所以只能使用蓝牙打印机或者wifi打印机了,但是项目的需求中需要使用到语音播报的功能,配备的是蓝牙音箱,故只剩下了wifi打印机了。因为之前使用过佳博的打印机,所以也就直接推荐公司买了佳博的wifi打印机。一直想整理下写一篇博文记录一下,但是一直没有时间,也就不了了之了,趁着现在需求少一点,赶紧撸一个,不多说,直接开撸。
在上一篇博文硬件系列(一)----------WIFI打印机之使用socket进行打印机搜索中,介绍了wifi打印机的搜索,在这里就不多说了,想了解的就去看另外一篇博文吧。
新建包,包名为com.gprinter.aidl,向包中添加文件,文件名为GpService.aidl内容为:注意,包名要一样哦!!!如下图所示
package com.gprinter.aidl;
interface GpService{
int openPort(int PrinterId,int PortType,String DeviceName,int PortNumber);
void closePort(int PrinterId);
int getPrinterConnectStatus(int PrinterId);
int printeTestPage(int PrinterId);
void queryPrinterStatus(int PrinterId,int Timesout,int requestCode);
int getPrinterCommandType(int PrinterId);
int sendEscCommand(int PrinterId, String b64);
int sendLabelCommand(int PrinterId, String b64);
void isUserExperience(boolean userExperience);
String getClientID();
int setServerIP(String ip, int port);
}
PrinterPrintService我就一起放在打印工具类里面了,如下:
/**
* @author Freak
* @date 2019/8/13.
*/
public class PrinterUtil {
private PrinterServiceConnection conn;
private BroadCastReceiver mBroadcastReceiver;
private GpService mGpService;
private Context context;
private boolean isBind;
class PrinterServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mGpService = GpService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("ServiceConnection", "onServiceDisconnected() called");
mGpService = null;
}
}
public PrinterUtil(Context context) {
this.context = context;
mBroadcastReceiver = new BroadCastReceiver();
connection();
doRegisterReceiver();
}
/**
* 连接 开启服务
*
* @param
*/
private void connection() {
LogUtil.e("开启打印服务");
conn = new PrinterServiceConnection();
Intent intent = new Intent(context, GpPrintService.class);
// bindService
isBind = context.bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
/**
* 注册广播
*
* @param
*/
public void doRegisterReceiver() {
// 注册实时状态查询广播
context.registerReceiver(mBroadcastReceiver, new IntentFilter(GpCom.ACTION_DEVICE_REAL_STATUS));
/**
* 票据模式下,可注册该广播,在需要打印内容的最后加入addQueryPrinterStatus(),在打印完成后会接收到
* action为GpCom.ACTION_DEVICE_STATUS的广播,特别用于连续打印,
* 可参照该sample中的sendReceiptWithResponse方法与广播中的处理
**/
context.registerReceiver(mBroadcastReceiver, new IntentFilter(GpCom.ACTION_RECEIPT_RESPONSE));
/**
* 标签模式下,可注册该广播,在需要打印内容的最后加入addQueryPrinterStatus(RESPONSE_MODE mode)
* ,在打印完成后会接收到,action为GpCom.ACTION_LABEL_RESPONSE的广播,特别用于连续打印,
* 可参照该sample中的sendLabelWithResponse方法与广播中的处理
**/
context.registerReceiver(mBroadcastReceiver, new IntentFilter(GpCom.ACTION_LABEL_RESPONSE));
}
/**
* 连接打印机
*/
public void connectToDevice(String ip, int port) {
int rel = 0;
try {
rel = mGpService.openPort(0, 3, ip, port);
LogUtil.e("开始连接");
} catch (RemoteException e) {
e.printStackTrace();
}
GpCom.ERROR_CODE r = GpCom.ERROR_CODE.values()[rel];
if (r == GpCom.ERROR_CODE.SUCCESS) {
LogUtil.e("打印机连接成功");
} else {
LogUtil.e("连接失败原因--》" + GpCom.getErrorText(r));
}
LogUtil.e("打印机连接状态--》" + GpCom.getErrorText(r));
}
/**
* 断开连接、关闭端口
*/
public void disConnectToDevice() {
try {
mGpService.closePort(0);
LogUtil.e("关闭端口");
} catch (RemoteException e) {
e.printStackTrace();
}
}
/***
* 查询打印机连接状态
*/
public void checkPrintLinStatus() {
try {
int printStatus = mGpService.getPrinterConnectStatus(0);
switch (printStatus) {
case 0:
LogUtil.e("连接断开");
break;
case 1:
LogUtil.e("监听状态");
break;
case 2:
LogUtil.e("正在连接");
break;
case 3:
LogUtil.e("已连接");
break;
default:
break;
}
} catch (RemoteException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
/**
* 后台控制打印格式方式打印测试
*
* @param arg
*/
public void printFormat(String arg) {
Map styleMap = new HashMap<>();
styleMap.put("", "CENTER");
styleMap.put("", "CENTER_BOLD");
styleMap.put("", "TITLE");
styleMap.put("", "LEFT");
styleMap.put("", "LEFT_BOLD");
styleMap.put("", "RIGHT");
styleMap.put("", "RIGHT_BOLD");
styleMap.put("", "BOLD");
Stack stack = new Stack();
StringBuffer sb = new StringBuffer();
int pos = 0;
boolean flag;
int start = 0;
int end = 0;
String type = "";
List typeList = new ArrayList<>();
List printTextList = new ArrayList<>();
while (arg.length() > pos) {
flag = true;
if (arg.charAt(pos) == '<') {
for (Object key : styleMap.keySet()) {
if (arg.length() > (pos + key.toString().length()) && arg.substring(pos, pos + key.toString().length()).equals(key)) {
type = styleMap.get(key).toString();
stack.push(styleMap.get(key));
pos += key.toString().length();
start = pos;
flag = false;
break;
}
}
if (flag) {
pos = arg.indexOf('>', pos) + 1;
if (!stack.isEmpty()) {
int length = stack.lastElement().toString().length();
end = pos - length - 4;
typeList.add(type);
printTextList.add(arg.substring(start, end + 1));
stack.pop();
}
}
} else {
sb.append(arg.charAt(pos));
pos++;
}
}
Logger.e(sb.toString());
typeList.add("end");
printTextList.add("-------------------------------");
startPrint(typeList, printTextList);
}
public void startPrint(List type, List printText) {
EscCommand escCommand = new EscCommand();
escCommand.addInitializePrinter();
for (int i = 0; i < type.size(); i++) {
if ("CENTER_BOLD".equals(type.get(i))) {
//设置打印居中
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
//设置加粗
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.ON, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
//是否加重
escCommand.addTurnDoubleStrikeOnOrOff(EscCommand.ENABLE.ON);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 1);
} else if ("TITLE".equals(type.get(i))) {
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
//设置不加粗
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.ON, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 2);
} else if ("CENTER".equals(type.get(i))) {
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
//设置不加粗
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 1);
} else if ("LEFT".equals(type.get(i))) {
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
//设置不加粗
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 1);
} else if ("LEFT_BOLD".equals(type.get(i))) {
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
//设置不加粗
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.ON, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
//是否加重
escCommand.addTurnDoubleStrikeOnOrOff(EscCommand.ENABLE.ON);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 1);
} else if ("RIGHT".equals(type.get(i))) {
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.RIGHT);
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 1);
} else if ("RIGHT_BOLD".equals(type.get(i))) {
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.RIGHT);
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.ON, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
escCommand.addTurnDoubleStrikeOnOrOff(EscCommand.ENABLE.ON);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 1);
} else if ("END".equals(type.get(i))) {
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 2);
} else {
escCommand.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
escCommand.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
escCommand.addText(printText.get(i));
escCommand.addPrintAndFeedLines((byte) 1);
}
}
escCommand.addPrintAndLineFeed();
// 加入查询打印机状态,打印完成后,此时会接收到GpCom.ACTION_DEVICE_STATUS广播
escCommand.addQueryPrinterStatus();
// 发送数据
Vector data = escCommand.getCommand();
byte[] bytes = GpUtils.ByteTo_byte(data);
String sss = Base64.encodeToString(bytes, Base64.DEFAULT);
int rs;
try {
rs = mGpService.sendEscCommand(0, sss);
GpCom.ERROR_CODE r = GpCom.ERROR_CODE.values()[rs];
if (r != GpCom.ERROR_CODE.SUCCESS) {
disConnectToDevice();
} else {
disConnectToDevice();
mHandler.sendEmptyMessage(0);
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void printerOnDestroy() {
if (conn != null) {
// unBindService
//解决14254 java.lang.IllegalArgumentException Service not registered错误 此错误在执行解绑成功之后在进行解绑导致的错误
if (isBind) {
context.unbindService(conn);
context.unregisterReceiver(mBroadcastReceiver);
isBind = false;
LogUtil.e("解绑服务");
}
}
}
/**
* 查询打印机状态并返回
*
* @return
*/
public int isLin() {
int printStatus = 0;
try {
printStatus = mGpService.getPrinterConnectStatus(0);
} catch (RemoteException e) {
e.printStackTrace();
}
return printStatus;
}
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
LogUtil.e("打印成功");
ToastUtil.show("打印成功");
break;
default:
break;
}
}
};
}
/**
* @author Freak
* @date 2019/8/13.
*/
public class BroadCastReceiver extends BroadcastReceiver {
private static final int REQUEST_PRINT_RECEIPT = 0xfc;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
LogUtil.e("Action-->" + action);
// GpCom.ACTION_DEVICE_REAL_STATUS 为广播的IntentFilter
if (action.equals(GpCom.ACTION_DEVICE_REAL_STATUS)) {
// 业务逻辑的请求码,对应哪里查询做什么操作
int requestCode = intent.getIntExtra(GpCom.EXTRA_PRINTER_REQUEST_CODE, -1);
// 判断请求码,是则进行业务操作
if (requestCode == REQUEST_PRINT_RECEIPT) {
int status = intent.getIntExtra(GpCom.EXTRA_PRINTER_REAL_STATUS, 16);
String str;
if (status == GpCom.STATE_NO_ERR) {
str = "打印机正常";
} else {
str = "打印机 ";
if ((byte) (status & GpCom.STATE_OFFLINE) > 0) {
str += "脱机";
}
if ((byte) (status & GpCom.STATE_PAPER_ERR) > 0) {
str += "缺纸";
}
if ((byte) (status & GpCom.STATE_COVER_OPEN) > 0) {
str += "打印机开盖";
}
if ((byte) (status & GpCom.STATE_ERR_OCCURS) > 0) {
str += "打印机出错";
}
if ((byte) (status & GpCom.STATE_TIMES_OUT) > 0) {
str += "查询超时";
}
}
LogUtil.e("打印机状态--》" + str);
ToastUtil.show(str);
}
}
}
}
public void checkLinStatusBeforePrint(final String ip, final int port) {
int mLin = App.getPrinterUtilInstance().isLin();
LogUtil.e("连接返回状态--》" + mLin);
switch (mLin) {
//连接断开
case 0:
mHandler.sendEmptyMessage(0);
break;
//监听状态
case 1:
break;
//正在连接,延迟一秒再次查询状态
case 2:
//延迟1秒后再检查连接状态
if (count > 20) {
ToastUtil.show("无法连接打印机,请检查打印机是否正常工作,稍后重试");
} else {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(2);
}
}, 100);
count++;
}
break;
//连接成功
case 3:
count = 0;
ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(new Runnable() {
@Override
public void run() {
App.getPrinterUtilInstance().printFormat(
"打印测试 " +
"测试金额:66686.3 "
);
}
});
break;
default:
break;
}
}
/**
* 查找打印Handel、检查打印机状态Handel
*/
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//断开连接
case 0:
//sp文件保存的是否开启打印
boolean isOpenPrinter = SharedPreferencesUtils.getBoolean(getActivity(), SharedPreferencesUtils.Printer_Open_Status);
if (isOpenPrinter) {
if (TextUtils.isEmpty(getIpAddress())) {
ToastUtil.show("请先设置打印机ip地址");
} else {
App.getPrinterUtilInstance().connectToDevice(getIpAddress(), 9100);
checkLinStatusBeforePrint(getIpAddress(), 9100);
}
} else {
ToastUtil.show("打印机未打开,请到打印机设置中打开打印机");
}
break;
//搜索结束
case 1:
setSharedPreferencesIpAddress();
break;
//正在连接
case 2:
//sp文件保存的是否开启打印
boolean mIsOpenPrinter = SharedPreferencesUtils.getBoolean(getActivity(), SharedPreferencesUtils.Printer_Open_Status);
if (mIsOpenPrinter) {
if (TextUtils.isEmpty(getIpAddress())) {
ToastUtil.show("请先设置打印机ip地址");
} else {
checkLinStatusBeforePrint(getIpAddress(), 9100);
}
} else {
ToastUtil.show("打印机未打开,请到打印机设置中打开打印机");
}
break;
case 4:
ToastUtil.show("连接成功");
break;
case 5:
mPrinterSettingAdapter.setNewData(mList);
break;
case 6:
ToastUtil.show("连接失败");
break;
default:
break;
}
}
};
private void setSharedPreferencesIpAddress() {
for (int i = 0; i < mList.size(); i++) {
if (mList.get(i).isSelect()) {
SharedPreferencesUtils.save(getActivity(), SharedPreferencesUtils.Printer_IP_Address, mList.get(i).getIp());
} else {
SharedPreferencesUtils.save(getActivity(), SharedPreferencesUtils.Printer_IP_Address, "");
}
}
}
到此,佳博wifi打印机的打印就完成了,当然,这个是使用sdk进行打印的,sdk可以在下载中进行下载。