一、前言

之前做过USB打印机,但是现在需求变了,不是使用收银台进行打印机的连接了,而是使用手机与打印机进行打印。手机又无法像收银机一样直接使用USB直接与打印机直接连接进行打印。所以只能使用蓝牙打印机或者wifi打印机了,但是项目的需求中需要使用到语音播报的功能,配备的是蓝牙音箱,故只剩下了wifi打印机了。因为之前使用过佳博的打印机,所以也就直接推荐公司买了佳博的wifi打印机。一直想整理下写一篇博文记录一下,但是一直没有时间,也就不了了之了,趁着现在需求少一点,赶紧撸一个,不多说,直接开撸。

二、佳博打印机配置教程

在上一篇博文硬件系列(一)----------WIFI打印机之使用socket进行打印机搜索中,介绍了wifi打印机的搜索,在这里就不多说了,想了解的就去看另外一篇博文吧。

2.1、配置文件配置

<uses-permission android:name="android.permission.INTERNET" />
<!--wifi打印机权限-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.hardware.usb.accessory" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permissionandroid:name="android.permission.WRITE_SETTINGS"tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-feature android:name="android.hardware.usb.host" />
<serviceandroid:name="com.gprinter.service.GpPrintService"android:enabled="true"android:exported="true"android:label="GpPrintService"><intent-filter><action android:name="com.gprinter.aidl.GpPrintService" /></intent-filter>
</service>
<service android:name="com.gprinter.service.AllService" />

2.2、添加aidl文件

新建包,包名为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);
}       

2.3、启动并绑定 启动并绑定PrinterPrintService服务

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 {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mGpService = GpService.Stub.asInterface(service);}@Overridepublic 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);// bindServiceisBind = 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 blocke1.printStackTrace();}}/*** 后台控制打印格式方式打印测试** @param arg*/public void printFormat(String arg) {Map<String, Object> styleMap = new HashMap<>();styleMap.put("<center>", "CENTER");styleMap.put("<center_bold>", "CENTER_BOLD");styleMap.put("<title>", "TITLE");styleMap.put("<left>", "LEFT");styleMap.put("<left_bold>", "LEFT_BOLD");styleMap.put("<right>", "RIGHT");styleMap.put("<right_bold>", "RIGHT_BOLD");styleMap.put("<bold>", "BOLD");Stack stack = new Stack<String>();StringBuffer sb = new StringBuffer();int pos = 0;boolean flag;int start = 0;int end = 0;String type = "";List<String> typeList = new ArrayList<>();List<String> 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<String> type, List<String> 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<Byte> 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 blocke.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() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case 0:LogUtil.e("打印成功");ToastUtil.show("打印成功");break;default:break;}}};
}

2.4、BroadCastReceiver类

/*** @author Freak* @date 2019/8/13.*/public class BroadCastReceiver extends BroadcastReceiver {private static final int REQUEST_PRINT_RECEIPT = 0xfc;@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();LogUtil.e("Action-->" + action);// GpCom.ACTION_DEVICE_REAL_STATUS 为广播的IntentFilterif (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);}}}
}

2.4、打印测试方法

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() {@Overridepublic void run() {mHandler.sendEmptyMessage(2);}}, 100);count++;}break;//连接成功case 3:count = 0;ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(new Runnable() {@Overridepublic void run() {App.getPrinterUtilInstance().printFormat("<center_bold>打印测试</center_bold>" +"<left>测试金额:66686.3</left>");}});break;default:break;}
}
/*** 查找打印Handel、检查打印机状态Handel*/
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {@Overridepublic 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可以在下载中进行下载。

硬件系列(二)-------------wifi打印机之佳博wifi打印机踩坑之路相关推荐

  1. 59、佳博wifi打印机怎么配置

    1.去这里下载配置软件(注意,需要再windows下进行)http://pan.baidu.com/s/1bn1y4FX,并解压安装程序 2.连上wifi打印机的热点,比如说佳博打印机的默认为Gpri ...

  2. 佳博 TSC打印机 TSPL指令开发

    如何在电脑上使用C# 调用佳博 TSC打印机指令控制打印 踩了不少坑 跟大家分享下开发需要注意的地方 1. 佳博和TSC的 BARCODE 指令有出入,TSC多了一个参数,直接用佳博的打印是扫码不出二 ...

  3. Uniapp Android 佳博 小票打印机 插件

    Uniapp Android 佳博 小票打印机 插件 Uniapp Android 佳博小票打印机插件:  支持图片.条型码.二维码 打印. 1. 实例化插件 const gp= uni.requir ...

  4. 【Android】Android 集成佳博80打印机打印票据

    文章目录 [Android]Android 集成佳博80打印机打印票据 1.集成佳博80打印机依赖 2.规范调用接口 3.使用到的相关对象以及工具类 4.MainActivity初始化接口 5.Uni ...

  5. android通过USB连接佳博80打印机

    GitHub项目地址 条件:1安卓主板上有USB口,2,rom内置了打印驱动 不行就用其他方式或者换主板吧(本人当初使用的工控主板坑得不要不要的) 本文介绍的是使用USB方式 佳博提供两个函数打印 1 ...

  6. android 佳博蓝牙打印机功能开发

    蓝牙自动连接已配对设备 private void connectBluetooth(){BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.ge ...

  7. 佳博usb打印机开钱箱

    以58mm热敏打印机为例 1, 安装好打印机驱动程序.点击光盘58mm Series-Driver-DRV58CN V4.51G直接安装. 2, 点击电脑之开始-控制面板-打印机和传真-选中打印机驱动 ...

  8. Lasso回归系列一:用LASSO回归做特征筛选踩坑记

    用LASSO回归做特征筛选使用踩坑记 什么时候应该用LASSO回归进行特征筛选?使用时容易踩的坑你都避开了吗?Lasso回归的原理(请看我的另一篇博客: Lasso回归系列二:Lasso回归/岭回归的 ...

  9. Android WiFi 权限、广播、连接、踩坑相关记录

    emmm-最近项目首页重构,UI重新弄,逻辑拆分重新写,变成我来写了-写完了,踩了好几个坑,好几个都忘记了,赶紧记一下防止都忘记了- 1.权限请求- 既然是WiFi连接,当然首先考虑到的是打开WiFi ...

最新文章

  1. WCF Data Service文章列表
  2. Android keymaster的介绍和总结
  3. Linux下的进程概论与编程二(进程控制)
  4. 我们渴望和平freeeim
  5. Qt文档阅读笔记-Q_ENUM官方解析及实例
  6. anaconda的python文件打包失败的问题解决方案
  7. 玻尿酸市场价格有很多,你是赚了还是亏了?
  8. Katalon Recorder 自动录制 Selenium 爬虫脚本
  9. MPQ文档布局分析[转帖]
  10. pgAdmin III 使用图解
  11. c语言汉字怎么编码,【C语言学习】C语言汉字编码。。。C语言中汉字的输入
  12. 基于扩展卡尔曼滤波的多传感器融合定位
  13. ps 利用马赛克滤镜制作方格背景
  14. php 判断后缀名,PHP 文件类型判断代码
  15. c++常用源代码以及常用库查找
  16. 高职计算机自主招生面试题,高职自主招生面试题
  17. c语言3个数最大公约数和最小公倍数,初学c语言【3】欧几里得算法求最小公倍数和最大公约数...
  18. 讲解基于verilog的4-2压缩器和3-2压缩器的实现方式,实现华莱士树(Wallace Tree)
  19. Java高级开发0-1项目实战-青鸟商城-Day02
  20. 春雨文化锦绣潇湘艺术研讨新闻发布会圆满举办

热门文章

  1. Java截取字符串中指定字符串之后的字符串
  2. 解析SNS社区产品架构模型,互联网营销
  3. NUXT.JS使用GEETEST极验验证
  4. TSO、GSO介绍与实现
  5. HDU-3234 Exclusive-OR 异或带权并查集
  6. JS异步加载及解决方式
  7. 2048小游戏逻辑代码(易懂)
  8. android4.4.4壁纸,基于4.4.4的dido OS 5.0系统
  9. Glide 的简单使用
  10. 钟形曲线 matlab_打破钟形曲线:在同一个海洋中脱颖而出