Vue H5项目,怎么引入uni.webview sdk,调用uni postMessage实现手机蓝牙连接打印功能(uniapp)

前言

目前公司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 源码

html 复制代码
<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文件,其源码地址

html 复制代码
https://gitee.com/dcloud/uni-app/raw/dev/dist/uni.webview.1.5.4.js

2、index.html 引入 public/js 下文件

html 复制代码
<script src="<%= BASE_URL %>js/uni.webview.1.5.4.js"></script>

3、main.js 定义回调方法和对象

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:代码如下

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页面:如下

js 复制代码
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'
            }
          })
        }
      }
    }
   }
 }

相关文章

基于ElementUi再次封装基础组件文档


基于ant-design-vue再次封装基础组件文档


vue3+ts基于Element-plus再次封装基础组件文档

相关推荐
Momo__14 小时前
Vue 3.6 Vapor Mode:跳过虚拟 DOM,性能极致优化
前端·vue.js
walking95715 小时前
重新学习前端之JavaScript
前端·vue.js·面试
walking95715 小时前
重新学习前端之HTML
前端·vue.js·面试
walking95715 小时前
重新学习前端之Vue
前端·vue.js·面试
泉城老铁15 小时前
springboot实现word转换pdf
vue.js·后端
walking95715 小时前
重新学习前端之Linux
前端·vue.js·面试
walking95715 小时前
重新学习前端之CSS
前端·vue.js·面试
walking95715 小时前
重新学习前端之Git
前端·vue.js·面试
Hello--_--World16 小时前
Vue指令:v-if vs v-show、v-if 与 v-for 的优先级冲突、自定义指令
前端·javascript·vue.js
Hello--_--World20 小时前
Vue:虚拟Dom
前端·javascript·vue.js