一直困惑在uni-app中实现pda的广播扫码功能,今天终于找到了一个解决方案。
方案就是做一个全局监听,只引入一次,来防止很多页面都引入了扫码的组件,造成多次扫描,数据出现多次
知识点 全局监听:官网的全局监听地址

uni.$emit:触发全局的自定事件。附加参数都会传给监听器回调。
uni.$on:监听全局的自定义事件。事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数
uni.$off:移除全局自定义事件监听器。

一定要记得移除全局事件,不燃就会出现多次扫描

一:在你的pda中要是设置广播输出:模式是键盘方式输出
方法:设置---扫描---Default:把里面的键盘方式输出取消掉,就会看到下面的广播动作和广播数据标签(这两个很重要,在后面会用到)上图:
2023-09-13T05:35:04.png

二:在你的uni-app项目里 新建一个公共组件 就叫 scan-code 吧,放到公共组件components中,目录:components/scan-code/scan-code.vue
这里就用到了广播动作和广播数据标签

filter.addAction("android.intent.ACTION_DECODE_DATA")
intent.getStringExtra("barcode_string")

代码里的filter.addAction里换成你的广播动作,intent.getStringExtra(里换成你的广播标签
代码如下

<template>
  <view class="content"></view>
</template>

<script>
var main, receiver, filter
var _codeQueryTag = false
export default {
  name: "scan-code",
  data() {
    return {
      model: {
        "AUTOID Q7": "com.android.server.scannerservice.broadcast",
        CRUISE: "com.example.chinaautoid",
      },
    }
  },
  created: function (option) {
    this.initScan()
    this.startScan()
  },
  onHide: function () {
    this.stopScan()
  },
  destroyed: function () {
    /*页面退出时一定要卸载监听,否则下次进来时会重复,造成扫一次出2个以上的结果*/
    this.stopScan()
  },
  methods: {
    initScan() {
      let _this = this
      main = plus.android.runtimeMainActivity() //获取activity
      var IntentFilter = plus.android.importClass(
        "android.content.IntentFilter"
      )
      filter = new IntentFilter()
      // PDA广播切换
      filter.addAction(_this.model[_this.deviceModel]) // 换你的广播动作
      // filter.addAction("com.example.chinaautoid"); // 换你的广播动作
      receiver = plus.android.implements(
        "io.dcloud.feature.internal.reflect.BroadcastReceiver",
        {
          onReceive: function (context, intent) {
            plus.android.importClass(intent)
            let code = intent.getStringExtra("scannerdata") // 换你的广播标签
            for (let i = 1; i < 3; i++) {
              _this.queryCode(code)
            }
          },
        }
      )
    },
    startScan() {
      main.registerReceiver(receiver, filter)
    },
    stopScan() {
      main.unregisterReceiver(receiver)
    },
    queryCode: function (code) {
      //防重复
      if (_codeQueryTag) return false
      _codeQueryTag = true
      setTimeout(function () {
        _codeQueryTag = false
      }, 150)
      var id = code && code.replace(/[\r\n]/g, "")
      console.log("id:", id)
      uni.$emit("scancodedate", { code: id })
    },
  },
}
</script>

<style>
page {
  background-color: #efeff4;
}
.content {
  text-align: center;
}
</style>

三:页面引用,只引用一次就好,我是index.vue 引用的,我的app的其他功能都是在这个页面链接走的
直接上代码:
切记:首页往各个子页面跳转的时候 移除监听事件uni.$off('scancodedate'),要不首页的监听会一直存在,就会出现首页这个扫码
uni.navigateTo({ 之前、之前、之前 uni.$off('scancodedate')

import scanCode from '@/components/scan-code/index.vue'

  export default {
    components: {
      MenuList,
      scanCode,
    },
    data() {
      return {
      }
    },
    onShow() {
      uni.$off('scancodedate') // 每次进来先 移除全局自定义事件监听器
      uni.$on('scancodedate', function(data) {
        console.log(data.code)
      })
    },

    onUnload() {
      // 移除监听事件
      uni.$off('scancodedate')
    },

其他的页面引用方法:不需要再次引入scanCode
因为其他的页面都是从首页跳转过来的,所以其他的页面需要
onUnload() {
// 移除监听事件
uni.$off('scancodedate')
}
代码如下:

onLoad() {  
   var _this = this  
   uni.$on('scancodedate',function(data){  
        // _this 这里面的方法用这个 _this.code(data.code)  
    console.log('你想要的code:', data.code)  
   })  
},  
onUnload() {  
   // 移除监听事件      
   uni.$off('scancodedate')  
}  

如果这个页面还有详细页面需要跳转,切记 uni.navigateTo({ 之前、之前、之前 uni.$off('scancodedate')

到此所有的代码就完事了。

重点就是全局监听,真机测试的时候在控制台可以打印出你的code和routes,看下是否每次的扫描只是执行的本页面(路由)下的程序。

发表评论