前言
目前公司Vue H5项目,用webview打包成APP,现产品提出这样打包出来的app运行较慢,需要用uniapp方式(即使用HBuilder编辑器来打包H5)来打包,那需要的基座就不是安卓的基座而是uniapp的基座,而H5项目实现手机扫描功能就需要调用uniapp的基座的方法。
需求&流程说明
Vue2 开发的移动端项目(H5项目及ipad端项目),需要连接蓝牙设备打印
需求说明:
1、点击打印按钮时,先判断当前设备是否已连接过蓝牙(即是否存在蓝牙设备ID)
a、若已连接过:直接调用打印配置(即:type:bluetoothPrint)
b、若未连接过:1、先获取当前设备的所有蓝牙list(即:type:getBluetoothList)
2、选中设备后调用蓝牙连接(即:type:connBluetooth)
3、连接成功后存储已连接的设备ID(即选中的设备)
具体步骤
一、Uniapp Webview 源码
<template>
<view>
<web-view :src="src" @message="showMessage"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
src: 'http://******/', // H5项目地址
qrCodeWv: null,
devices: [],
currDev: null,
connId: '',
}
},
onReady() {
// #ifdef APP-PLUS
let currentWebview = this.$scope.$getAppWebview()
setTimeout(() => {
this.wv = currentWebview.children()[0]
this.qrCodeWv = currentWebview.children()[0]
this.wv.setStyle({ scalable: true })
}, 1000)
// #endif
},
methods: {
showMessage(event) {
if (event.detail.data && event.detail.data.length > 0) {
let dataInfo = event.detail.data[0]
console.log(dataInfo)
let type = dataInfo.type
if (type === 'getBluetoothList') {
this.getBluetoothList()
}
if (type === 'connBluetooth') {
console.log(dataInfo.params)
let args = dataInfo.params;
let deviceId = args.deviceId;
let device = this.devices.find((item) => {
return item.deviceId == deviceId;
})
console.log(device)
this.connBluetooth(device)
}
if (type === 'bluetoothPrint') {
let args = dataInfo.params;
let deviceId = args.deviceId;
let command = args.command;
let device = this.devices.find((item) => {
return item.deviceId == deviceId;
})
//当设备没有连接时需要重新连接设备
if (this.connId == '') {
this.initBluetoothList();
this.connBluetooth(device);
}
let serviceId = this.currDev.services[0].serviceId;
let characteristicId = this.currDev.services[0].characteristicId;
this.senBlData(deviceId, serviceId, characteristicId, command);
}
}
},
// 获取蓝牙设备list
getBluetoothList() {
this.initBluetoothList();
const data = JSON.stringify(this.devices)
console.log('获取蓝牙设备list', data)
this.qrCodeWv.evalJS(`appBluetoothListResult('${data}')`)
},
initBluetoothList() {
this.searchBle();
setTimeout(() => {
this.stopFindBule();
}, 10000)
},
// 查找蓝牙设备
searchBle() {
var self = this
console.log("initBule")
uni.openBluetoothAdapter({
success(res) {
console.log("打开 蓝牙模块")
console.log(res)
self.onDevice()
uni.getBluetoothAdapterState({
success: function (res) {
console.log(res)
if (res.available) {
if (res.discovering) {
self.stopFindBule()
}
//搜索蓝牙
//开始搜寻附近的蓝牙外围设备
console.log("开始搜寻附近的蓝牙外围设备")
uni.startBluetoothDevicesDiscovery({
success(res) {
console.log(res)
}
})
} else {
console.log('本机蓝牙不可用')
}
},
})
}
})
},
onDevice() {
console.log("监听寻找到新设备的事件---------------")
var self = this
//监听寻找到新设备的事件
uni.onBluetoothDeviceFound(function (devices) {
//获取在蓝牙模块生效期间所有已发现的蓝牙设备
console.log('--------------new-----------------------' + JSON.stringify(devices))
var re = JSON.parse(JSON.stringify(devices))
let name = re.devices[0].name
if (name != "未知设备" && name.length != 0) {
console.log(name.length)
let deviceId = re.devices[0].deviceId
//信号过滤。大于50
//如果已经存在也不用加入
if (re.devices[0].RSSI > self.filterRSSI) {
if (!self.devices.some(v => v.deviceId == deviceId)) {
self.devices.push({
name: name,
deviceId: deviceId,
services: []
})
}
}
}
})
},
stopFindBule() {
console.log("停止搜寻附近的蓝牙外围设备---------------")
uni.stopBluetoothDevicesDiscovery({
success(res) {
console.log(res)
}
})
},
// 连接蓝牙
connBluetooth(device) {
this.onConn(device);
},
// 连接蓝牙
onConn(item) {
var self = this
console.log(`连接蓝牙---------------${item.deviceId}`)
let deviceId = item.deviceId
uni.createBLEConnection({
deviceId: deviceId,
complete(res) {
let result = false;
if (res.errMsg == "createBLEConnection:ok") {
plus.nativeUI.toast(`设备:${item.name} 已连接`, {
verticalAlign: 'center'
})
self.connId = deviceId;
self.currDev = item,
setTimeout(function () {
self.getBLEServices(deviceId)
}, 2000)
result = true;
} else {
plus.nativeUI.toast(`设备: ${item.name} 连接失败。请重试!`, {
verticalAlign: 'center',
})
//切换异常时释放掉链接
if (self.connId != '') {
uni.closeBLEConnection({
deviceId: self.connId,
success(res) {
console.log(res)
}
})
}
}
//连接成功 关闭搜索
self.stopFindBule()
//发生是否成功结果
var data = {};
data.result = result;
var data1 = JSON.stringify(data)
self.wv.evalJS(`appConnBluetoothResult('${data1}')`)
},
})
},
getBLEServices(_deviceId) {
var self = this;
let deviceId = _deviceId
console.log("获取蓝牙设备所有服务(service)。---------------")
uni.getBLEDeviceServices({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: deviceId,
complete(res) {
console.log(res)
let serviceId = ""
for (var s = 0; s < res.services.length; s++) {
console.log(res.services[s].uuid)
let serviceId = res.services[s].uuid
uni.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId: serviceId,
success(res) {
var re = JSON.parse(JSON.stringify(res))
console.log(`deviceId =[${deviceId}] serviceId = [${serviceId}]`)
for (var c = 0; c < re.characteristics.length; c++) {
if (re.characteristics[c].properties.write == true) {
let uuid = re.characteristics[c].uuid
console.log(`deviceId =[${deviceId}] serviceId = [${serviceId}] characteristics=[${uuid}]`)
for (var index in self.devices) {
if (self.devices[index].deviceId == deviceId) {
self.devices[index].services.push({
serviceId: serviceId,
characteristicId: uuid
})
break
}
}
console.log(JSON.stringify(self.devices))
}
}
}
})
}
},
fail(res) {
console.log(res)
},
})
},
senBlData(deviceId, serviceId, characteristicId, uint8Array) {
var uint8Buf = Array.from(uint8Array);
function split_array(datas, size) {
var result = {};
var j = 0
if (datas.length < size) {
size = datas.length
}
for (var i = 0; i < datas.length; i += size) {
result[j] = datas.slice(i, i + size)
j++
}
//result[j] = datas
console.log(result)
return result
}
var sendloop = split_array(uint8Buf, 20);
// console.log(sendloop.length)
function realWriteData(sendloop, i) {
var data = sendloop[i]
if (typeof (data) == "undefined") {
return
}
//console.log("第【" + i + "】次写数据"+data)
var buffer = new ArrayBuffer(data.length)
var dataView = new DataView(buffer)
for (var j = 0; j < data.length; j++) {
dataView.setUint8(j, data[j]);
}
uni.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: buffer,
success(res) {
console.log('发送成功', i)
setTimeout(() => {
realWriteData(sendloop, i + 1);
}, 100)
},
fail(e) {
console.log('发送数据失败')
console.log(e)
}
})
}
var i = 0;
realWriteData(sendloop, i);
},
}
}
</script>
二、H5 Vue项目引入js
1、在public新建js文件夹uni.webview.1.5.4.js文件,其源码地址
https://gitee.com/dcloud/uni-app/raw/dev/dist/uni.webview.1.5.4.js
2、index.html 引入 public/js 下文件
<script src="<%= BASE_URL %>js/uni.webview.1.5.4.js"></script>
3、main.js 定义回调方法和对象
// 蓝牙设备列表
window.appBluetoothListResult = function (val) {
window.appBluetoothListResultString = val
window.dispatchEvent(new CustomEvent('bluetoothListResult'))
}
// 蓝牙连接成功或失败
window.appConnBluetoothResult = function (val) {
window.appConnBluetoothResultString = val
window.dispatchEvent(new CustomEvent('connBluetoothResult'))
}
4、Vue扫码页面代码
1、在mixins文件夹下新建bluetoothMixins.js:代码如下
export default {
data() {
return {
bluetoothShow: false, // 蓝牙设备弹窗
deviceId: '', // 蓝牙设备ID
listArr: [] // 获取所有蓝牙设备
}
},
created() {
window.addEventListener('bluetoothListResult', this.handleBluetoothList, false)
window.addEventListener('connBluetoothResult', this.handleConnBluetoothResult, false)
},
beforeDestroy() {
window.removeEventListener('bluetoothListResult', this.handleBluetoothList)
window.removeEventListener('connBluetoothResult', this.handleConnBluetoothResult)
},
methods: {
handleConnBluetoothResult() {
const result = window.appConnBluetoothResultString
console.log('返回蓝牙是否连接成功', result)
if (JSON.parse(result).result) {
console.log('连接成功')
const deviceId = localStorage.getItem('bluetoothDeviceId')
localStorage.setItem('bluetoothDeviceId', deviceId || this.deviceId)
// alert(`${this.deviceId}---设置值选中的值`)
// alert(`${deviceId}---设置值缓存的值`)
this.bluetoothShow = false
}
},
handleBluetoothList() {
const result = window.appBluetoothListResultString
console.log('返回蓝牙list', result)
if (result) {
this.bluetoothShow = true
this.listArr = JSON.parse(result)
}
},
// 选中设备
selectBluetooth(item) {
console.log('选中设备', item)
this.deviceId = item.deviceId
uni.postMessage({
data: {
action: 'connBluetooth',
params: { deviceId: this.deviceId }
}
})
}
}
}
2、实际Vue页面:如下
import BluetoothMixins from '@/mixins/bluetoothMixins'
export default {
mixins: [BluetoothMixins],
methods: {
// 点击打印按钮
async print(deliveryNo) {
console.log('配送单deliveryNo----', deliveryNo)
// 获取蓝牙打印参数
const res = await this.$api.getDeliveryPrintParam({ deliveryNo })
if (res.success) {
// 判断之前是否有连接过蓝牙
const deviceId = localStorage.getItem('bluetoothDeviceId')
// alert(`${deviceId}---配送单缓存值`)
if (deviceId) {
// 连接过直接打印
uni.postMessage({
data: {
action: 'bluetoothPrint',
params: { deviceId, command: JSON.parse(res.data) }
}
})
} else {
// 没有连接过,先去获取蓝牙设备数据(list)
uni.postMessage({
data: {
action: 'getBluetoothList'
}
})
}
}
}
}
}