最近、レシート印刷の作業をしており、プロジェクトの要件としてiOSとAndroidの両方で実装する必要がありました。最初は全く分からず、インターネットで多くの資料を探し、たくさんの落とし穴にはまり、多くの記事を読みましたが、結果的にはうまくいきました。 Bluetoothプリンターは一般的に、レシート印刷とラベル印刷の2種類の印刷モードに分けられます。
会社が購入した粗悪なプリンターには開発ドキュメントすらなく、多くの落とし穴にはまる羽目になりました。開発担当者に購入時に相談してくれればよかったのに。 現在、WeChatミニプログラムでBluetoothプリンターに接続する wx.createBLEConnection は、iOSデバイスでは問題なく動作しますが、一部のAndroidスマートフォンでは異常が発生します(接続時にシステムペアリングボックスがポップアップ表示され、キャンセルをタップしても、ペアリングコードを入力して確定をタップしても、すぐに接続が切断されます。入力もキャンセルもしない場合、30秒以内にBluetoothプリンターから自動的に切断されます)。
現在採用している方法は、AndroidとiOSそれぞれにBluetooth印刷コマンドのセットを作成することです。 IOS
// ====================蓝牙操作================== //初始化蓝牙模块 openBluetoothAdapter() { if (app.sysinfo.provider == 1) { // 开启蓝牙 app.onBluetooth() setTimeout(() => { this.android_search() }, 2000) return false; } this.closeBluetoothAdapter() uni.openBluetoothAdapter({ success: (res) => { console.log("初始化蓝牙模块: " + JSON.stringify(res)); this.startBluetoothDevicesDiscovery() }, fail: (res) => { if (res.errCode === 10001) { uni.onBluetoothAdapterStateChange((res) => { console.log('监听蓝牙适配器状态变化事件', res) if (res.available == false) { app.global_printing = {} this.connected = false this.chs = [] this.canWrite = false } if (res.available) { this.startBluetoothDevicesDiscovery() } }) } if (res.errCode) { app.alert('初始化蓝牙失败,错误码:' + res.errCode) return false; } app.alert(res.errMsg) } }) }, //获取本机蓝牙适配器状态 getBluetoothAdapterState() { uni.getBluetoothAdapterState({ success: (res) => { console.log('获取本机蓝牙适配器状态。', JSON.stringify(res)) if (res.discovering) { this.onBluetoothDeviceFound() } else if (res.available) { this.startBluetoothDevicesDiscovery() } }, fail: (res) => { console.log('error:获取本机蓝牙适配器状态失败', JSON.stringify(res)) setTimeout(() => { this.getBluetoothAdapterState() }, 500) } }) }, //开始搜寻附近的蓝牙外围设备 startBluetoothDevicesDiscovery() { console.log(this.discoveryStarted); if (this.discoveryStarted) { return } console.log('开始搜索蓝牙设备'); this.discoveryStarted = true this.onBluetoothDeviceFound() setTimeout(() => { uni.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true, success: (res) => { console.log('startBluetoothDevicesDiscovery success', JSON.stringify( res)) }, fail: (res) => { if (res.errCode == '10001') { app.alert('当前蓝牙适配器不可用') } else { app.alert('搜索蓝牙失败,状态码:' + res.errCode) } } }) }, 500) }, // 停止搜索 stopBluetoothDevicesDiscovery() { uni.stopBluetoothDevicesDiscovery() this.discoveryStarted = false }, //寻找到新设备的事件的回调函数 onBluetoothDeviceFound() { console.log('寻找到新设备的事件的回调函数'); uni.onBluetoothDeviceFound((res) => { console.log(res); res.devices.forEach(device => { if (!device.name && !device.localName) { return } const foundDevices = this.devices const idx = this.inArray(foundDevices, 'deviceId', device.deviceId) if (idx === -1) { this.devices.push(device) } else { this.devices[idx] = device } }) }) }, //连接低功耗蓝牙设备 createBLEConnection(e) { uni.showLoading({ title: '设备连接中', mask: true }); const ds = e.currentTarget.dataset const deviceId = ds.deviceId const name = ds.name if (app.sysinfo.provider == 1) { if (ds.pair !== true) { this.android_search(deviceId) } else { console.log('已配对') } var device = null, BAdapter = null, BluetoothAdapter = null, uuid = null, main = null, bluetoothSocket = null; var mac_address = deviceId var main = plus.android.runtimeMainActivity(); BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter"); var UUID = plus.android.importClass("java.util.UUID"); uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); BAdapter = BluetoothAdapter.getDefaultAdapter(); device = BAdapter.getRemoteDevice(mac_address); plus.android.importClass(device); bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid); plus.android.importClass(bluetoothSocket); if (!bluetoothSocket.isConnected()) { console.log('检测到设备未连接,尝试连接....'); bluetoothSocket.connect(); } this.connected = true this.name = name this.deviceId = deviceId this.canWrite = true app.global_printing = { name: name, deviceId: deviceId } app.saveData1('global_printing', app.global_printing) uni.hideLoading(); return false; } uni.createBLEConnection({ deviceId, success: (res) => { this.connected = true this.name = name this.deviceId = deviceId app.global_printing = { name: name, deviceId: deviceId } this.onBLEConnectionStateChange() // 防止获取失败 setTimeout(() => { this.getBLEDeviceServices(deviceId) }, 1000) }, fail: (res) => { uni.hideLoading(); app.Toast('设备连接失败') console.log("蓝牙连接失败:", res); } }) this.stopBluetoothDevicesDiscovery() }, //获取蓝牙设备所有服务(service) getBLEDeviceServices(deviceId) { uni.getBLEDeviceServices({ deviceId, success: (res) => { console.log("获取蓝牙服务成功:" + JSON.stringify(res)) if (res.services.length == 0) { uni.hideLoading(); app.alert('没有获取到蓝牙服务,无法打印001') app.global_printing = {} return false } for (let i = 0; i < res.services.length; i++) { if (res.services[i].isPrimary) { this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) return } } }, fail: (res) => { setTimeout(() => { this.getBLEDeviceServices(deviceId) }, 500) console.log("获取蓝牙服务失败:" + JSON.stringify(res)) } }) }, //获取蓝牙设备某个服务中所有特征值(characteristic) getBLEDeviceCharacteristics(deviceId, serviceId) { console.log('获取蓝牙设备某个服务中所有特征值', deviceId, serviceId) uni.getBLEDeviceCharacteristics({ deviceId, serviceId, success: (res) => { console.log('获取蓝牙设备某个服务中所有特征值 success', JSON.stringify(res)) uni.hideLoading(); if (res.characteristics.length == 0) { app.alert('没有获取到蓝牙服务,无法打印002') app.global_printing = {} return false } for (let i = 0; i < res.characteristics.length; i++) { let item = res.characteristics[i] if (item.properties.read) { uni.readBLECharacteristicValue({ deviceId, serviceId, characteristicId: item.uuid, }) } if (item.properties.write) { this.canWrite = true app.global_printing._deviceId = deviceId app.global_printing._serviceId = serviceId app.global_printing._characteristicId = item.uuid app.saveData1('global_printing', app.global_printing) //this.writeBLECharacteristicValue() } if (item.properties.notify || item.properties.indicate) { uni.notifyBLECharacteristicValueChange({ deviceId, serviceId, characteristicId: item.uuid, state: true, }) } } }, fail(res) { console.error('获取特征值失败:', res) } }) // 操作之前先监听,保证第一时间获取数据 uni.onBLECharacteristicValueChange((characteristic) => { console.log(this.data.chs); const idx = this.inArray(this.data.chs, 'uuid', characteristic.characteristicId) const data = {} if (idx === -1) { this.chs[this.data.chs.length] = { uuid: characteristic.characteristicId, value: ab2hex(characteristic.value) } } else { this.chs[idx] = { uuid: characteristic.characteristicId, value: ab2hex(characteristic.value) } } }) }, onBLEConnectionStateChange() { uni.onBLEConnectionStateChange((res) => { // 该方法回调中可以用于处理连接意外断开等异常情况 console.log(`蓝牙连接状态改变device ${res.deviceId} state has changed, connected: ${res.connected}`) if (res.connected == false) { app.global_printing = {} this.connected = false this.chs = [] this.canWrite = false } }) }, //断开与低功耗蓝牙设备的连接 closeBLEConnection() { app.global_printing = {} uni.closeBLEConnection({ deviceId: this.deviceId }) this.connected = false this.chs = [] this.canWrite = false }, //关闭蓝牙模块 closeBluetoothAdapter() { app.global_printing = {} uni.closeBluetoothAdapter() this.discoveryStarted = false }, //发送数据 sendStr(bufferstr, success, fail) { var that = this; uni.writeBLECharacteristicValue({ deviceId: app.global_printing._deviceId, serviceId: app.global_printing._serviceId, characteristicId: app.global_printing._characteristicId, value: bufferstr, success: function(res) { success(res); console.log('发送的数据:' + bufferstr) // console.log('message发送成功') }, fail: function(res) { fail(res) console.log("数据发送失败:" + JSON.stringify(res)) }, complete: function(res) { // console.log("发送完成:" + JSON.stringify(res)) } }) }, //遍历发送数据 printCode(arr) { var that = this; if (arr.length > 0) { this.sendStr(arr[0], function(success) { arr.shift(); that.printCode(arr); }, function(error) { app.alert('打印失败,错误码:' + error.errCode) app.printing_status = false console.log(error); }); return false; } setTimeout(function() { app.printing_status = false console.log('打印结束'); }, 1000); }, Android 比較的シンプルで便利です。Native.jsを使用してNative Javaインターフェースチャネルを直接呼び出し、plus.androidを介してAndroidネイティブシステムAPIを呼び出します。 ネイティブAndroidドキュメント https://developer.android.google.cn/reference/android/bluetooth/BluetoothAdapter?hl=en
...