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

news2024/11/20 8:36:48

前言

目前公司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'
            }
          })
        }
      }
    }
   }
 }

相关文章

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


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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1302207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何通过内网穿透工具实现任意浏览器远程访问Linux本地zabbix web管理界面

前言 Zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。能监视各种网络参数&#xff0c;保证服务器系统的安全运营&#xff1b;并提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问题。 本地zabbix web管理界面限制在只能局域…

GD32F30X-RT-Thread学习-线程管理

1. 软硬件平台 GD32F307E-START Board开发板MDK-ARM Keil 2.RT-Thread Nano 3.RT-Thread 内核学习-线程管理 ​ 在多线程操作系统中&#xff0c;可以把一个复杂的应用分解成多个小的、可调度的、序列化的程序单元&#xff0c;当合理地划分任务并正确地执行时&#xff0c;这…

我的acer电脑U盘装系统前BIOS设置及装系统过程中的操作

1、开机长按F2进入BIOS设置 2、使能F12 3、调整boot顺序&#xff0c;使USB启动的优先级最高 4、按F10保存退出 5、插入U盘开机&#xff0c;boot选择界面无需操作&#xff0c;等待几秒&#xff0c;默认进入U盘系统 由于既使能了F12&#xff0c;又将U盘的优先级进调整到了最高&…

三层交换原理

三层交换机出现的背景 早期的网络中一般使用二层交换机来搭建局域网&#xff0c;而不同局域网之间的网络互通由路由器来完成。那时的网络流量&#xff0c;局域网内部的流量占了绝大部分&#xff0c;而网络间的通信访问量比较少&#xff0c;使用少量路由器已经足够应付了。 但…

鸿蒙生态千帆起:从者众,行则远

“轻舟已过万重山”&#xff0c;鸿蒙的成长速度惊人&#xff0c;一定程度上打破了iOS和安卓二分天下的格局。短短四年时间&#xff0c;搭载华为鸿蒙系统的生态设备数已经突破7亿&#xff0c;开发者突破220万。据Counterpoint数据显示&#xff0c;华为HarmonyOS系统在中国的市场…

钓鱼网站域名识别工具dnstwist算法研究

先上一个AI的回答&#xff1a; dnstwist是一种钓鱼网站域名识别工具&#xff0c;可帮助用户识别和检测可能被恶意使用的域名。它通过生成类似的域名变体来模拟攻击者可能使用的钓鱼域名&#xff0c;并提供了一系列有用的功能和信息。 dnstwist能够生成一组类似的域名变体&…

Linux基础指令(2)

今天我们继续来学我们有关于Linux的指令&#xff0c;今天的指令要比上次多多了。开始我们的学习吧。 man手册 先来看标题&#xff0c;手册我们第一时间想到的就是手册的查阅功能&#xff0c;我们都知道在我们上小学的时候&#xff0c;如果遇到不会的字&#xff0c;我们会通过…

淘宝1688京东解析商品详情方法丨API接口指南及相关文档说明

要解析淘宝、1688和京东的商品详情&#xff0c;可以按照以下步骤进行&#xff1a; 获取API接口权限&#xff1a;首先&#xff0c;需要在对应的平台上申请API接口权限。这通常涉及到注册开发者账号&#xff0c;创建应用&#xff0c;并获取App Key和App Secret。编写API请求代码…

Docker build 无法解析域名

### 报错 Docker build 无法解析域名 报错&#xff1a;ERROR [ 2/12] RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo 解决Docker build无法解析域名 # 追加到 etc/docker/daemon.json&#xff0c;注意JSON的格式 {"dn…

机器学习硬件十年:性能变迁与趋势

本文分析了机器学习硬件性能的最新趋势&#xff0c;重点关注不同GPU和加速器的计算性能、内存、互连带宽、性价比和能效等指标。这篇分析旨在提供关于ML硬件能力及其瓶颈的全面视图。本文作者来自调研机构Epoch&#xff0c;致力于研究AI发展轨迹与治理的关键问题和趋势。 &…

设计模式-门面模式(Facade)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、定义二、结构 前言 在组件构建过程中&#xff0c;某些接口之间直接依赖会带来很多问题&#xff0c;甚至无法直接实现。采用一层间接接口&#xff0c;来隔离…

Appium 并行测试多个设备

一、前置说明 在自动化测试中&#xff0c;经常需要验证多台设备的兼容性&#xff0c;Appium可以用同一套测试运例并行测试多个设备&#xff0c;以达到验证兼容性的目的。 解决思路&#xff1a; 查找已连接的所有设备&#xff1b;为每台设备启动相应的Appium Server&#xff1b…

URL提示不安全

当用户访问一个没有经过SSL证书加密的网站&#xff08;即使用HTTP而不是HTTPS协议&#xff09;&#xff0c;或者SSL证书存在问题时&#xff0c;浏览器URL会显示不安全提示。这些提示旨在保护用户免受潜在的恶意活动&#xff0c;并提醒他们谨慎对待这些不安全的网站。那么该如何…

28. Python Web 编程:Django 基础教程

目录 安装使用创建项目启动服务器创建数据库创建应用创建模型设计路由设计视图设计模版 安装使用 Django 项目主页&#xff1a;https://www.djangoproject.com 访问官网 https://www.djangoproject.com/download/ 或者 https://github.com/django/django Windows 按住winR 输…

Python中的并发编程(3)线程池、锁

concurrent.futures 提供的线程池 concurrent.futures模块提供了线程池和进程池简化了多线程/进程操作。 线程池原理是用一个任务队列让多个线程从中获取任务执行&#xff0c;然后返回结果。 常见的用法是创建线程池&#xff0c;提交任务&#xff0c;等待完成并获取结果&…

mysql 字符串合并方法以及合并为null问题

concat()不推荐 mysql一般提供了两种一种是concat()函数一种是concat_ws()函数&#xff0c;前者合并字符串有个弊端&#xff0c;合并字段不能有null值&#xff0c; 否则如下图合并后会是null concat_ws()推荐 concat_ws()函数可以解决合并字符串为null问题&#xff0c;conca…

人工智能期末复习重点【只针对(适合)个人】

第二章 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.框架题 12.1地震框架 12.2洪水框架 13.第二章总结 第三章 14. 15. 3.1.1 推理的定义 16. 3.1.2 推理方式及其分类 &#xff08;1&#xff09;确定性推理&#xff1a; u 推理时所用的 知识与证据 都是 确定的 &…

在 Qt Creator 中编写 Doxygen 风格的注释

2023年12月10日&#xff0c;周日上午 如何生成Doxygen 风格的注释 在需要Doxygen 风格注释的函数上方输入 /**&#xff0c;然后按下 Enter 键。Qt Creator 将自动为你生成一个注释模板。 输入&#xff0c;Qt Creator会自动帮你补全Doxygen标签 不得不说&#xff0c;写了Doxyge…

Linux库之动态库静态库

一、什么是库&#xff08;Library&#xff09; 二、库的分类 三、静态库、动态库优缺点 四、静态库的制作和使用 五、动态库的制作和使用 SO-NAME–解决主版本号之间的兼容问题 基于符号的版本机制 共享库系统路径 共享库的查找过程 有用的环境变量 gcc 编译器常用选项 Linux共…

私域爆款案例拆解-元气森林

一、背景调研 二、引流策略 三、私域运营策略