MUI蓝牙打印(Android)

来源:互联网 发布:李云龙 赵刚 知乎 编辑:程序博客网 时间:2024/06/06 08:25

MUI蓝牙打印(Android)


使用MUI开发手机APP时使用蓝牙打印功能可能较少使用,MUI官方并为集成蓝牙打印功能,而且似乎对iPhone蓝牙打印的类库支持也不够完善。忙完一阶段后回顾下之前的工作,想想蓝牙打印功能折腾了够长时间了,写这篇文章既是自己做个总结,也希望能给遇到同样为蓝牙打印功能挣扎的人带来一点帮助。

感谢以下几篇文章给予的帮助。

  • Android 蓝牙连接 ESC/POS 热敏打印机打印(ESC/POS指令篇)
  • 安卓Native.js蓝牙连接票据打印机完整代码已测试修改

    以下打印的代码中使用了一些NativeJS的方法,如果对NativeJS没有了解的朋友,建议自行Google一下。我们直接上代码。

页面HTML

<!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <meta name="apple-mobile-web-app-capable" content="yes">        <meta name="apple-mobile-web-app-status-bar-style" content="black">        <!--标准mui.css-->        <link rel="stylesheet" href="../../css/mui.min.css">        <link rel="stylesheet" href="../../css/wg-common.css">        <link rel="stylesheet" href="../../css/iconfont.css">        <!--App自定义的css-->        <link rel="stylesheet" type="text/css" href="../../css/app.css" />        <title></title>    </head>    <style>        .wg-info-title {            background-color: white;            color: #007AFF;        }        .mui-btn {            font-size: 16px;            padding: 8px;            margin: 3px;        }    </style>    <body>        <header class="mui-bar mui-bar-nav" style="padding-top: 2px;">            <div style="float: left;padding-right: 8px;">                <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>            </div>            <h1 id="title" class="mui-title">打印</h1>            <div style="float: right;padding-right: 8px;">                <a class="mui-icon mui-icon-refreshempty" id="btnRefresh"></a>            </div>        </header>        <div class="mui-content mui-content-padded">            <h5 class="mui-content-padded">点击设备开始连接</h5>            <ul id="list1" class="mui-table-view mui-table-view-chevron">            </ul>            <br />            <h5 class="mui-content-padded">点击设备开始打印</h5>            <ul id="list2" class="mui-table-view mui-table-view-chevron">            </ul>        </div>    </body></html>

页面JS代码

// 导入的java包        var Context, BluetoothAdapter, BluetoothDevice;        // 蓝牙服务与适配        var BManager, BAdapter, BluetoothSocket, mDevice, receiver;        var mMain, mUUID;        var vlist1 = document.getElementById('list1'); //注册容器用来显示未配对设备        var vlist2 = document.getElementById('list2'); //注册容器用来显示未配对设备        var buttonRefresh = document.getElementById('btnRefresh');        document.addEventListener('plusready', function(event) {            var self = plus.webview.currentWebview();            // 打开蓝牙设备并扫描            if (mui.os.android) {                // 打开蓝牙                openAndroidBluetooth();                // 设置延时,防止蓝牙未完全开启时调用                CommonUtil.WaitFor(                    function() {                        return BAdapter.isEnabled();                    },                    function() {                        // 获取已连接设备列表                        getConnectedDevices();                    },                    3000);            }        });        // 刷新(重新扫描)        buttonRefresh.addEventListener('tap', function(event) {            buttonRefresh.disabled = true;            if (mui.os.android) {                // 扫描                searchDevices();            }            buttonRefresh.disabled = false;        });        // list1/list2的监听事件只能用on绑定,如果使用        //              li2.addEventListener('tap', function(event) {        //                  print(li2.getAttribute('id'));        //              });        // 会导致打印时socket超时,具体原因不明        mui('#list1').on('tap', 'li', function() {            connect(this.id);        })        mui('#list2').on('tap', 'li', function() {            print(this.id);        })        /**         *打开蓝牙(Android)          */        function openAndroidBluetooth() {            mMain = plus.android.runtimeMainActivity();            Context = plus.android.importClass("android.content.Context");            BManager = mMain.getSystemService(Context.BLUETOOTH_SERVICE);            plus.android.importClass(BManager); //引入相关的method函数            BAdapter = BManager.getAdapter();            plus.android.importClass(BAdapter); //引入相关的method函数,这样之后才会有isEnabled函数支持            if (!BAdapter.isEnabled()) {                BAdapter.enable();            }        }        /**         * 获取已配对的蓝牙设备列表         */        function getConnectedDevices() {            //          var main = plus.android.runtimeMainActivity();            //          var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");            //          var BAdapter = BluetoothAdapter.getDefaultAdapter(); //获得本机蓝牙适配器            if (!BAdapter.isEnabled()) {                plus.nativeUI.toast('请先打开蓝牙');                return;            }            var lists = BAdapter.getBondedDevices(); //获取配对的设备列表            plus.android.importClass(lists);            var iterator = lists.iterator();            plus.android.importClass(iterator);            var vlist2 = document.getElementById('list2'); //注册容器用来显示未配对设备            while (iterator.hasNext()) {                var d = iterator.next();                plus.android.importClass(d);                var li2 = genLi(d);                vlist2.appendChild(li2);            }        }        /**         *扫描蓝牙设备          */        function searchDevices() {            //console.log("开始搜索设备");            if (!BAdapter.isEnabled()) {                plus.nativeUI.toast('请先打开蓝牙');                return;            }            plus.nativeUI.showWaiting('正在搜索设备,请稍后...', {                back: 'none' // 可取值"none"表示截获处理返回键,但不做任何响应;"close"表示截获处理返回键并关闭等待框;"transmit"表示不截获返回键,向后传递给Webview窗口继续处理(与未显示等待框的情况一致)。             });            vlist1.innerHTML = ''; //清空容器            vlist2.innerHTML = ''; //清空容器            // 初始化蓝牙广播接收器             initReceiver();            // 开启搜索            BAdapter.startDiscovery();            // 初始化广播信息过滤            initIntentFilter();        }        function initReceiver() {            BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");            var bdevice = new BluetoothDevice();            receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {                onReceive: function(context, intent) { //实现onReceiver回调函数                    plus.android.importClass(intent); //通过intent实例引入intent类,方便以后的‘.’操作                    //console.log(intent.getAction()); //获取action                    if (intent.getAction() == "android.bluetooth.adapter.action.DISCOVERY_FINISHED") {                        mMain.unregisterReceiver(receiver); //取消监听                        //console.log("搜索结束")                        plus.nativeUI.closeWaiting();                    } else {                        BleDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                        //                      console.log(JSON.stringify(BluetoothDevice));                        //                      console.log(JSON.stringify(BleDevice));                        //判断是否配对                        if (BleDevice.getBondState() == bdevice.BOND_NONE) {                            //console.log("未配对蓝牙设备:" + BleDevice.getName() + '    ' + BleDevice.getAddress());                            if (!document.getElementById(BleDevice.getAddress())) { //判断防止重复添加                                var li1 = genLi(BleDevice);                                vlist1.appendChild(li1);                            }                        } else {                            if (!document.getElementById(BleDevice.getAddress())) { //判断防止重复添加                                //console.log("已配对蓝牙设备:" + BleDevice.getName() + '    ' + BleDevice.getAddress());                                var li2 = genLi(BleDevice);                                vlist2.appendChild(li2);                            }                        }                    }                }            });        }        function initIntentFilter() {            // 设置广播信息过滤              var IntentFilter = plus.android.importClass('android.content.IntentFilter');            var filter = new IntentFilter();            filter.addAction(BluetoothDevice.ACTION_FOUND);            filter.addAction(BAdapter.ACTION_DISCOVERY_STARTED);            filter.addAction(BAdapter.ACTION_DISCOVERY_FINISHED);            filter.addAction(BAdapter.ACTION_STATE_CHANGED);            // 注册广播接收器,接收并处理搜索结果              mMain.registerReceiver(receiver, filter);        }        function connect(mac_address) {            // 查找蓝牙设备            var unConnected = BAdapter.getRemoteDevice(mac_address);            if (unConnected) {                try {                    if (BleDevice.createBond()) { //配对命令.createBond()                        //console.log("配对成功");                    }                } catch (e) {                    //TODO handle the exception                    mui.alert('连接到设备失败');                }            }        }        //mac_address:打印机的mac地址        function print(mac_address, str) {            if (!mac_address) {                mui.toast('请选择蓝牙打印机');                return;            }            if (mDevice == null) {                //              mMain = plus.android.runtimeMainActivity();                //              BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");                //              BAdapter = BluetoothAdapter.getDefaultAdapter();                UUID = plus.android.importClass("java.util.UUID");                mUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");                mDevice = BAdapter.getRemoteDevice(mac_address);                plus.android.importClass(mDevice);                BluetoothSocket = mDevice.createInsecureRfcommSocketToServiceRecord(mUUID);            }            plus.android.importClass(BluetoothSocket);            if (!BluetoothSocket.isConnected()) {                //console.log('检测到设备未连接,尝试连接....');                try {                    BluetoothSocket.connect();                } catch (e) {                    //TODO handle the exception                    mui.alert('连接超时');                    return;                }            }            // 防止蓝牙未完成连接时调用打印            CommonUtil.WaitFor(                function() { // 等待条件                    return BluetoothSocket.isConnected();                },                function() { // 回调方法                    if (!BluetoothSocket.isConnected()) {                        plus.nativeUI.toast('请连接打印机');                        return;                    }                    printTest();                    //printPictureTest();                }, 3000);        }        function printTest() {            // 初始化PintUtil            PrintUtil.init(BluetoothSocket);            // 以下测试打印            var printStr = '测试打印\r\n';            // 设置字体大小            PrintUtil.SetFontSize(30);            // 打印字符串            PrintUtil.PrintString(printStr);            // 设置字体大小            PrintUtil.SetFontSize(20);            // 打印字符串            PrintUtil.PrintString(printStr);            // 重置打印机            PrintUtil.Reset();            // 打印字符串            PrintUtil.PrintString(printStr);            // 切纸            PrintUtil.CutPage();            // 结束打印            PrintUtil.End();        }        function genLi(bleDevice) {            var li = document.createElement('li');            li.setAttribute('id', bleDevice.getAddress());            li.className = 'mui-table-view-cell';            var a = document.createElement('a');            a.setAttribute('class', 'mui-navigate-right')            a.innerText = bleDevice.getName();            li.appendChild(a);            return li;        }

辅助方法

页面上用到的几个方法也贴出来吧。

    CommonUtil.WaitFor = function(condition, callback, timeout, unitTime) {        // 设置默认等待时间(循环间隔)        if(!unitTime || isNaN(unitTime)) {            unitTime = 100;        }        // 设置超时(到达超时则返回)        if(!timeout || isNaN(timeout)) {            timeout = 100;        }        if(condition && condition()) { // 等待条件成立,则执行回调            callback();        } else if(timeout - unitTime <= 0) { // 等待超时,则执行回调            callback();        } else { // 设置延时等待操作            setTimeout(function() {                owner.WaitFor(condition, callback, timeout - unitTime, unitTime);            }, unitTime);        }    };

PrintUtil打印公共方法

这里使用了一些打印机指令,具体的指令可以自己根据使用的打印机去找。

(function($, owner) {    owner.OutputStream = null;    owner.init = function(BluetoothSocket) {        owner.OutputStream = BluetoothSocket.getOutputStream();        plus.android.importClass(owner.OutputStream);    }    // 设置字体大小    owner.SetFontSize = function(n) {        var font = [0x1D, 0X21, n]        owner.OutputStream.write(font);    };    // 打印字符串    owner.PrintString = function(string) {        var bytes = plus.android.invoke(string, 'getBytes', 'gbk');        owner.OutputStream.write(bytes);    };    // 重置打印机    owner.Reset = function() {        var reset = [0x1B, 0X40];        owner.OutputStream.write(reset);    };    // 打印下划线    owner.Underline = function() {        // 下划线指令        var underline = [0x1b, 0x2d, 0x01];        owner.OutputStream.write(underline);    };    // 结束打印    owner.End = function() {        owner.OutputStream.flush();        var end = [0x1d, 0x4c, 0x1f, 0x00];        owner.OutputStream.write(end);    };    // 打印图片(暂不可用)    owner.Picture = function() {        var picture = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x40, 0x1B, 0x33, 0x00];        // var picture = [0x1B, 0x2A];        owner.OutputStream.write(picture);    };    // 切纸(暂不可用)    owner.CutPage = function() {        // 发送切纸指令          var end = [0x1B, 0x69];        owner.OutputStream.write(end);    };    // 条形码打印(暂不可用)    owner.PrintBarcode = function(n) {        var barcode = [0x1D, 0x6B, 65, 5, 11, 12, 3, 6, 23];        owner.OutputStream.write(barcode);    };}(mui, window.PrintUtil = {}))

    好了,基本上代码都贴出来了,作为一个代码狗,很多时候我都相信:Talk is cheap, show me the code。
1 0
原创粉丝点击