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

一、前言

之前做过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-permission
    android: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-permission
    android: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" />
<service
    android: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 {
        @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<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 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;
            }
        }
    };
}

2.4、BroadCastReceiver类

/**
 * @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);
            }
        }
    }
}

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() {
                    @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(
                            "<center_bold>打印测试</center_bold>" +
                                    "<left>测试金额:66686.3</left>"
                    );
                }
            });
            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可以在下载中进行下载。

 

 

 

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值