uniapp或安卓对接扫码枪

背景介绍

最近老板又随便丢过来一个扫码枪让我研究快速上线,我心想着又是什么串口通信吗,结果发现是usb的,我想着是不是有什么协议,结果直接插上电脑或者手机 均可在输入框直接输入,不用任何的代码编写

但结合了一下实际场景,我们需要一个全局的没有编辑框的输入监听才能满足的我们的需求,比如一扫就跳转一扫就去支付等处理业务

基本概念

1.条形码和二维码都对应固定文本也就是字符串,本身没有业务逻辑是我们程序赋予此业务逻辑

2.扫码枪本质原理是识别条形码和二维码后进行外接键盘输入

监听输入

uniapp实现

	const onConfirm = (code : string) => {console.log('拿到的code', code);// 此处写我们自己的逻辑 这里我只是举例 具体根据你们自己业务如何解析let str = code;// 使用 split 方法根据冒号分割字符串  let parts = str.split(":");// 检查是否至少有 3 个部分(两个冒号)  if (parts.length >= 3) {// 提取第二个部分(索引为 1,因为索引从 0 开始)  let extracted = parts[1];console.log(extracted); // 输出: DD240531143948587 // 给相关页面页发消息进行切换if (extracted) {// 后面可以添加更严格的判断// 发给menuuni.$emit('scanCode', extracted);// 发给发给子页面uni.$emit('scanCodeDetail', extracted);return}} else {console.log("字符串格式不正确,没有足够的冒号");}uni.showToast({title: "非本应用格式暂不支持",icon: "none",duration: 2e3});}const keypress = (e : any) => {console.log('keypress e', JSON.stringify(e), codeToStr(e.keyCode));if (e.keyCode === 66 || e.key == 'Enter') {inputString.value = inputCache.value;onConfirm(inputString.value)inputCache.value = '';} else {// #ifdef APP-PLUSinputCache.value += codeToStr(e.keyCode) || ''// #endif // #ifdef H5inputCache.value += e.key// #endif}}onLoad((options) => {console.log("index onLoad")// #ifdef APP-PLUSplus.key.addEventListener("keyup", keypress);// #endif // #ifdef H5document.addEventListener("keyup", keypress);// #endif})onUnload(() => {console.log("index onUnload")// #ifdef APP-PLUSplus.key.removeEventListener("keyup", keypress)// #endif// #ifdef H5document.removeEventListener("keyup", keypress)// #endif})

原生实现

    override fun dispatchKeyEvent(event: KeyEvent?): Boolean {if (event?.action == KeyEvent.ACTION_DOWN) {val keyCode = event.keyCodeif (mScanGun?.isMaybeScanning(keyCode, event) == true) {return true}}return super.dispatchKeyEvent(event)}

实际过程中都能得到event,但直接获取code又有问题,下面给个我目前使用支持中文和数字的转化,我也一直没有找到完整的,感觉像asicll码偏移了,只能限制业务逻辑中只有数字英文和固定字符,如果有字符需求 ,直接自己生成一个二维码然后去扫出来看看是什么

uniapp

// keymap.js 以下来源网络收集,不同的设备对应的keyCode可能不同
// 随手给的设备没有文档只能自己苦逼研究解码 发现少了就自己加,目前为安卓平台测试结果
// 大概率是ASCII偏移了
let keyMap = {"7": "0","8": "1","9": "2","10": "3","11": "4","12": "5","13": "6","14": "7","15": "8","16": "9","29": "A","30": "B","31": "C","32": "D","33": "E","34": "F","35": "G","36": "H","37": "I","38": "J","39": "K","40": "L","41": "M","42": "N","43": "O","44": "P","45": "Q","46": "R","47": "S","48": "T","49": "U","50": "V","51": "W","52": "X","53": "Y","54": "Z","55": ",","56": ".","59": "","69": "-","70": "=","81": "+","74": ":",}export function codeToStr(code: keyof typeof keyMap) : String {return keyMap[code]
}

我这边直接就把keyCode 转化成字符串拼接完事了

其他人的工具类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.chice.scangun;import android.view.KeyEvent;public class ScanGun {public static final int MAX_KEYS_INTERVAL_DEFAULT = 20;private long currentTime = 0L;private boolean isKeySHIFT = false;private StringBuilder stringBuilder = new StringBuilder();private ScanGunCallBack callBack = null;private static int maxKeysInterval = 20;public static void setMaxKeysInterval(int interval) {maxKeysInterval = interval;}public ScanGun(ScanGunCallBack callBack) {this.callBack = callBack;}public boolean isMaybeScanning(int keyCode, KeyEvent event) {if (event.getFlags() != 8) {return false;} else {if (this.currentTime == 0L) {if (this.stringBuilder.length() > 0) {this.stringBuilder = this.stringBuilder.delete(0, this.stringBuilder.length());}this.currentTime = System.currentTimeMillis();} else {if (System.currentTimeMillis() - this.currentTime > (long)maxKeysInterval && this.stringBuilder.length() > 0) {this.stringBuilder = this.stringBuilder.delete(0, this.stringBuilder.length());}this.currentTime = System.currentTimeMillis();}if (keyCode == 59) {this.isKeySHIFT = true;}if (keyCode == 66) {this.isKeySHIFT = false;this.currentTime = 0L;if (this.callBack != null) {this.callBack.onScanFinish(this.stringBuilder.toString());}return true;} else {if (keyCode >= 7 && keyCode <= 16) {this.handleTopNumKeys(keyCode);} else if (keyCode >= 29 && keyCode <= 54) {this.checkShift((char)(keyCode + 68), (char)(keyCode + 36));} else {if (keyCode < 144 || keyCode > 158) {switch (keyCode) {case 55:this.checkShift(',', '<');break;case 56:this.checkShift('.', '>');break;case 57:case 58:case 59:case 60:case 61:case 63:case 64:case 65:case 66:case 67:default:return false;case 62:this.stringBuilder.append(' ');break;case 68:this.checkShift('`', '~');break;case 69:this.checkShift('-', '_');break;case 70:this.checkShift('=', '+');break;case 71:this.checkShift('[', '{');break;case 72:this.checkShift(']', '}');break;case 73:this.checkShift('\\', '|');break;case 74:this.checkShift(';', ':');break;case 75:this.checkShift('\'', '"');break;case 76:this.checkShift('/', '?');}return true;}this.handleNumPadKeys(keyCode);}return true;}}}private void checkShift(char ascallNoShift, char ascallOnShift) {if (this.isKeySHIFT) {this.stringBuilder.append(ascallOnShift);this.isKeySHIFT = false;} else {this.stringBuilder.append(ascallNoShift);}}private void handleNumPadKeys(int keyCode) {if (keyCode <= 153) {this.stringBuilder.append((char)(keyCode - 96));} else if (keyCode == 154) {this.stringBuilder.append('/');} else if (keyCode == 155) {this.stringBuilder.append('*');} else if (keyCode == 156) {this.stringBuilder.append('-');} else if (keyCode == 157) {this.stringBuilder.append('+');} else if (keyCode == 158) {this.stringBuilder.append('.');}}private void handleTopNumKeys(int keyCode) {if (keyCode >= 7 && keyCode <= 16) {switch (keyCode) {case 7:this.checkShift('0', ')');break;case 8:this.checkShift('1', '!');break;case 9:this.checkShift('2', '@');break;case 10:this.checkShift('3', '#');break;case 11:this.checkShift('4', '$');break;case 12:this.checkShift('5', '%');break;case 13:this.checkShift('6', '^');break;case 14:this.checkShift('7', '&');break;case 15:this.checkShift('8', '*');break;case 16:this.checkShift('9', '(');}}}public interface ScanGunCallBack {void onScanFinish(String var1);}
}

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

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

相关文章

【Proteus仿真】【Arduino单片机】基于物联网新能源电动车检测系统设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶显示模块、WIFI模块、蜂鸣器、LED按键、ADC、DS18B20温度传感器等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示温…

试题与研究杂志试题与研究杂志社试题与研究编辑部2024年第16期目录

教海纵横 互动式教学模式在初中道德与法治课的应用探究 陈文海; 1-3 基于跨学科项目式学习的地理研学旅行课程设计——以“佛山梁园”为例 周红艳; 4-6 育人导向下道德与法治教学与社会实践活动的融合探索 李鹤群; 7-9 合作学习模式下的初中数学教学策略探究 张…

2024/6/25随笔

去重庆出差了8天&#xff0c;给我整麻了&#xff0c;第一天去了吃了顿地道的重庆老火锅&#xff0c;真不错啊&#xff0c;然后拉了六天。半夜2点让骑手给我送了一盒蒙脱石散&#xff0c;吃了一周也没好&#xff0c;一回武汉直接就好了。肯定就是那个火锅吃的&#xff0c;导致严…

视频融合平台LntonCVS视频监控汇聚平台:构建多元接入与智能管理的安防新生态

一、视频融合平台概述 视频融合平台支持多种协议和设备类型的接入&#xff0c;包括GB28181、Onvif、RTSP、RTMP、海康SDK、Ehome、大华SDK、宇视SDK等。它能够统一整合和管理来自不同品牌、不同协议的视频资源&#xff0c;构建视频数据资源池&#xff0c;并通过视频资源目录为…

pdf文件太大如何压缩变小?pdf文件变小的简单方法

pdf作为目前一种常用的文件格式&#xff0c;通过这种格式的文件展示内容&#xff0c;能够保证在不同设备上显示基本一致的效果&#xff0c;无论是计算机、平板还是手机&#xff0c;都能保持原始的布局、字体和图像效果。PDF是一种分享、存档和打印最合适的选择&#xff0c;那么…

ffmpeg音视频开发从入门到精通——ffmpeg 视频数据抽取

文章目录 FFmpeg视频处理工具使用总结环境配置主函数与参数处理打开输入文件获取流信息分配输出文件上下文猜测输出文件格式创建视频流并设置参数打开输出文件并写入头信息读取、转换并写入帧数据写入尾信息并释放资源运行程序注意事项源代码 FFmpeg视频处理工具使用总结 环境…

.NET 6.0 Web API项目中实现基于Token的身份验证

本文以一个完整的示例&#xff0c;展示如何在.NET 6.0 Web API项目中实现基于Token的身份验证。这个例子包括了如何创建和验证JWT Token&#xff0c;以及如何在控制器中使用这些Token。 步骤 1: 创建Web API项目 首先&#xff0c;用Visual Studio 2022创建一个基于.NET6.0的 …

PointCloudLib-滤波模块(Filtering)-使用体素网格过滤器对点云进行降采样

在本教程中,我们将学习如何缩减采样——即减少数量 点 – 使用体素化格网方法的点云数据集。 我们将要介绍的类在输入上创建一个 3D 体素网格(将体素网格视为空间中的一组微小 3D 框) 点云数据。然后,在每个体素(即 3D 框)中,所有点都存在 将用它们的质心近似(即下采样…

java spring boot 单/多文件上传/下载

文章目录 使用版本文件上传服务端客户端&#xff08;前端&#xff09;方式一方式二 文件下载服务端客户端&#xff08;前端&#xff09; 代码仓库地址 使用版本 后端 spring-boot 3.3.0jdk17 前端 vue “^3.3.11”vite “^5.0.8”axios “^1.7.2” 文件上传 上传文件比较…

从零到一学FFmpeg:av_packet_rescale_ts 函数详析与实战

文章目录 前言一、函数原型二、功能描述三、使用实例 前言 av_packet_rescale_ts是FFmpeg库中的一个函数&#xff0c;用于重新缩放或转换媒体流中的时间戳&#xff08;timestamp&#xff09;&#xff0c;以适配不同的时间基&#xff08;timebase&#xff09;。 在处理多媒体数…

Spark离线开发指南(详细版)

文章目录 1--Spark—core**2.1--RDD的创建**2.1.1--并行化创建2.1.2--获取分区数2.1.3--读取文件创建RDDtextFilewholeTextFile 2.2--RDD算子2.2.1--算子概念2.2.2--Transformation算子mapflatMapreduceByKeymapValuesgroupByfilterdistinctunionjoinintersectionglomgroupByKe…

【遇到的问题】集群上查看gpu的使用情况

流程&#xff1a; 查看bme_cpu所有节点的详细情况scontrol show node bme_gpu[12-23] 下面这个看起来分配出去较少 查看bme_cpu空闲节点sinfo -p bme_gpu -o "%n %G %C %m %e NVIDIAA10080GBPCIe 卡 gpu 13看起来最少 在命令中选择这个节点 #!/bin/bash #SBATCH -J rati…

别再盲目生产了!精益KPI管理让你事半功倍!

在竞争日益激烈的制造业领域&#xff0c;如何提升生产效率、降低成本、确保产品质量&#xff0c;是每个企业都需要面对的重要课题。而研华科技作为工业自动化领域的领军企业&#xff0c;凭借其独特的精益生产KPI分析与管理平台&#xff0c;为企业提供了一套行之有效的解决方案。…

OpenAI突然宣布停止向中国提供API服务!

标题 &#x1f31f; OpenAI突然宣布停止向中国提供API服务! &#x1f31f;摘要 &#x1f4dc;引言 &#x1f4e2;正文 &#x1f4dd;1. OpenAI API的重要性2. 停止服务的原因分析3. 对中国市场的影响4. 应对措施代码案例 &#x1f4c2;常见问题解答&#xff08;QA&#xff09;❓…

Java-HashMap和ConcurrentHashMap的区别

Java-HashMap和ConcurrentHashMap的区别 一、关键区别1.数据结构2.线程安全3.性能4.扩容机制 二、源码简析1.并发控制机制2.数据结构转换&#xff1a;链表转红黑树3.扩容机制触发hashMap和concurentHashMap扩容机制的条件 三、putIfAbsent方法computeIfAbsent方法区别 ​ 在 J…

Linux(简单概述)

目录 第一章 初识Linux 第四章 文件管理与常用命令 1.文件基础知识 2.文件显示命令 3.文件内容查询 4. 文件和目录基本操作 5. 文件复制、移动、删除 7. 链接 8. 文件访问权限 9. 文件查找命令 10. 压缩和解压缩 第五章用户与用户组 第六章软件包管理RPM和YUM数据库…

CesiumJS【Basic】- #011天气特效

文章目录 天气特效1 目标2 实现2.1 Weather.ts2.2 main.ts天气特效 1 目标 用着色器实现 - 白天 - 多云 - 雾 - 雨 - 雪 2 实现 在Cesium version 1.118.1中,默认是gles 3.0的语法,以前的gl_FragColor、varying和texture2D无法继续使用 2.1 Weather.ts import * as Ces…

面试-synchronized(java5以前唯一)和ReentrantLock的区别

1.ReentrantLock&#xff08;再入锁&#xff09;&#xff1a; (1).在java.util.concurrent.locks包 (2).和CountDownLatch,FutureTask,Semaphore一样基于AQS实现。 AQS:AbstractQueuedSynchronizer 队列同步器。Java并发用来构建锁或其他同步主键的基础框架&#xff0c;是j.u.c…

【金】04Y? 人脸识别系统 | 前端PyQT

参考-教程bilibil视频&#xff1a;树莓派进阶玩法 | 人脸识别项目教程 界面参考&#xff1a;基于深度学习的人脸识别与管理系统&#xff08;UI界面增强版&#xff0c;Python代码&#xff09;_python管理系统深度学习-CSDN博客 1、 树莓派小项目&#xff1a;人脸识别&#xff…