在uniapp中使用优博讯PDA红外扫描头

在uniapp中使用优博讯PDA红外扫描头

前言

因公司最近有开发一个库存管理模块的需求,需要开发一个PDA软件,经过一番调研后决定采用uniapp进行开发,虽然速度不如原生,但此场景下也足够满足需求了。一旦涉及到PDA肯定是跑不了开发扫描条码或二维码的功能的,由于uniapp是一个使用vue.js开发前端应用的框架,而扫描功能需要调用系统底层的一些功能,想想还是有困难的。

不过,当阅读了uniapp官网和H5+产业联盟的文章后,真的是柳暗花明又一村呀!如果要在uniapp实现扫描功能还是比较简单的,没有想象中的复杂。总结下来一共两种方式实现扫描功能,接下来我将分别进行说明。

方式一:采用相机扫描

值得庆幸的是uniapp官方提供了扫码API传送门

Pasted image 20240519224842.png

此方法使用起来非常简单,只需要在界面上放一个组件,然后绑定点击事件,在点击事件中去调用此扫描API,当扫描成功会后返回对应的结果。

以下是一个案例:

<template>
	<view class="content">
		<view class="title">调用相机扫描条码</view>
		<view class="input">
			<uni-easyinput suffixIcon="scan" v-model="orderNo" placeholder="请扫描条码"
				@iconClick="scanClick"></uni-easyinput>
		</view>
		
	</view>
</template>

<script setup>
	import {
		ref
	} from 'vue';

	let orderNo = ref('');

	/**
	 * 相机扫描
	 */
	function scanClick() {
		uni.scanCode({
			success: function(res) {
				console.log('条码类型:' + res.scanType);
				console.log('条码内容:' + res.result);
				orderNo.value = res.result
			}
		});

	}

</script>

<style lang="scss" scoped>
	.content {
		.title {
		margin-top: 20px;
		margin-bottom: 10px;
		font-size: 40rpx;
		font-weight: 600;
		}
	}


</style>

5011816b-0635-4440-b236-66cefd100c36.gif

说明:

  1. 优点:使用简单,适用范围广,只要手机有相机且满足uniapp的版本要求就可以使用
  2. 缺点:识别较慢,不合适在库存管理这种需要多次扫描的场景下使用

方式二:采用红外扫描头

如果PDA带有红外扫描头,可使用H5+产业联盟规定的API调用系统底层的组件,可以自行制作一个uniapp的android原生插件,uniapp调用原生插件,原生插件调用红外扫描头。此处只介绍相对简单的H5+的方法,如需了解原生插件可以参考uniapp插件市场中的扫描插件(传送门)。

通过前期研究,了解到了PDA的扫描组件一般支持两种输出方式,一种是键盘方式输入,一种是广播输出。

  1. 键盘输出:扫描头识别到内容后会自动将内容已键盘输入的方式输入到当前光标所在的位置。
  2. 广播输出:扫描头识别到内容后通过广播的方式通知调用者,使用此方式需要获取【广播动作】和【广播字符串数据标签】

优博讯扫描设置

Pasted image 20240519232140.png

Pasted image 20240519232444.png

案例

  1. 定义一个用于扫描的工具模块
let main;
let filter;
let receiver;
let tag = false;

/**
 * 开始广播监听
 */
const start = () => {
	 /* #ifdef APP-PLUS */
	main.registerReceiver(receiver, filter);
	 /* #endif */
}
/**
 * 停止广播监听
 */
const stop = () => {
	/* #ifdef APP-PLUS */
	main.unregisterReceiver(receiver);
	/* #endif */
}


/**
 *
 * 定义广播
 * that:传this;
 */
const init = (onReceive) => {
	/* #ifdef APP-PLUS */
	//获取activity
	main = plus.android.runtimeMainActivity();
	const IntentFilter = plus.android.importClass('android.content.IntentFilter');
	filter = new IntentFilter();
	
	const scanManager = plus.android.importClass('android.device.ScanManager');
	
	// 扫描设置的广播动作
	filter.addAction("android.intent.ACTION_DECODE_DATA");
	receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
		onReceive: function(context, intent) {
			plus.android.importClass(intent);
			// 扫描设置的广播字符数据标签
			// const code = intent.getStringExtra("barcode_string");
			const code = intent.getStringExtra(scanManager.BARCODE_STRING_TAG);
			
			//条码长度  
			// var barcodeLength = intent.getIntExtra("length", 0)
			var barcodeLength = intent.getIntExtra(scanManager.BARCODE_LENGTH_TAG, 0)
			// 条码类型
			// var barcodeType = intent.getByteExtra("barcodeType", (0 | 0))
			var barcodeType = intent.getByteExtra(scanManager.BARCODE_TYPE_TAG, (0 | 0))

			if (tag) return;
			tag = true;
			setTimeout(function() {
				tag = false;
			}, 150);
			//扫描成功调用回调函数
			onReceive && onReceive(code, barcodeType, barcodeLength);
		}
	});

	function byteToString(arr) {
		if (typeof arr === 'string') {
			return arr;
		}
		var str = '',
			_arr = arr;
		for (var i = 0; i < _arr.length; i++) {
			var one = _arr[i].toString(2),
				v = one.match(/^1+?(?=0)/);
			if (v && one.length == 8) {
				var bytesLength = v[0].length;
				var store = _arr[i].toString(2).slice(7 - bytesLength);
				for (var st = 1; st < bytesLength; st++) {
					store += _arr[st + i].toString(2).slice(2);
				}
				str += String.fromCharCode(parseInt(store, 2));
				i += bytesLength - 1;
			} else {
				str += String.fromCharCode(_arr[i]);
			}
		}
		return str;
	}
	 /* #endif */

}

export const broadcastScan = {
	init,
	start,
	stop,
};

  1. 在main.js中将扫描模块挂载在vue的原型链上,在全局使用
// main.js

import App from './App'

// 扫描组件
import {broadcastScan} from '@/utils/scanner'

import { createSSRApp } from 'vue'
export function createApp() {
  const app = createSSRApp(App)
  
  // 全局挂载红外扫描组件
  app.config.globalProperties.$broadcastScan=broadcastScan
  
  return {
    app
  }
}

  1. 在页面中使用
<template>
	<view class="content">
		<view class="title">uniapp优博讯PDA红外扫描示例</view>
		<view class="text-area">
			<uni-easyinput type="textarea" disabled autoHeight v-model="scanText"
				placeholder="点击红外扫描按钮识别到内容后会显示在这儿"></uni-easyinput>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		getCurrentInstance
	} from 'vue';
	import {
		onLoad,
		onUnload,
		onHide,
		onShow
	} from '@dcloudio/uni-app';

	let scanText = ref('');

	const {
		proxy,
		ctx
	} = getCurrentInstance();

	onLoad((res) => {
		proxy.$broadcastScan.init(getScancode);


	})
	onUnload(() => {
		proxy.$broadcastScan.stop();
	})

	onHide(() => {
		proxy.$broadcastScan.stop();
	})

	onShow(() => {
		proxy.$broadcastScan.start();
	})

	/**
	 * PDA扫码回调方法
	 * @param {Object} code
	 * @param {Object} barcodeType
	 * @param {Object} barcodeLength
	 */
	function getScancode(code, barcodeType, barcodeLength) {
		code = code.trim()
		console.log(code)
		scanText.value = code

	}
</script>

<style lang="scss" scoped>
	.content {
		.title {
			margin-top: 20px;
			margin-bottom: 10px;
			font-size: 40rpx;
			font-weight: 600;
		}
	}
</style>

b3dd635f-8418-4c3b-ad78-2c77d0c338de.gif

结尾

上述案例代码参见: https://github.com/TonyDiao/infrared_scan

参考链接:

  1. https://ask.dcloud.net.cn/article/id-36468
  2. https://www.jianshu.com/p/8d35fca3ae76

在uniapp中使用优博讯PDA红外扫描头
https://www.diaoyc.cn//archives/1716136163633
作者
Adiaoyc
发布于
2024年05月20日
许可协议