我是靠谱客的博主 辛勤大地,这篇文章主要介绍Android接入USB扫码模块的方法,现在分享给大家,希望可以做个参考。

前言

USB扫码模块可以是扫描盒子或者扫码枪之类的,一根USB线作为供电和数据通信使用,有些扫码模块支持虚拟串口模式,虚拟串口模式读取数据会比较简单一点,和普通的串口一样操作即可,就是通过虚拟串口口+波特率即可获取到数据,这里主要讲读取USB模式下的数据。

1.读取USB模式下的数据

USB模式下的扫码模块相当于一个外接键盘,也就是它必须在有光标的地方才能进行扫码,且是直接把扫到的内容自动输入到输入框中,并不受我们的控制,所以我们必须另外想办法,安卓系统中有这么个方dispatchKeyEvent(KeyEvent event),它就是用来处理我们键盘的输入事件的,如果我们拦截该方法,把它交给我们自己去处理,这样我们就可以不通过Edittext从而获取到扫码头传过来的数据了。

值得注意的是扫码输出字符是连续输出的,也就是说扫码的数据并不是一下子输出所有的数据,而是有间隔的输出字符,间隔是比较短的,大概有10ms左右,有些扫码模块有回车结束符,有些没有,所以我们需要封装代码使用,如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import android.os.Build; import android.os.Handler; import android.util.Log; import android.view.KeyEvent; import org.greenrobot.eventbus.EventBus; import java.util.ArrayList; import java.util.List; public class ScanGunHelper { private final static long MESSAGE_DELAY = 200; private StringBuffer mStringBufferResult = new StringBuffer(); private Handler mHandler = new Handler(); private Runnable mScanningFishedRunnable = new Runnable() { @Override public void run() { performScanSuccess(); } }; private List<Integer> keyCodeList = new ArrayList<>(); private static class SingletonHolder { private static final ScanGunHelper instance = new ScanGunHelper(); } private ScanGunHelper() { } public static ScanGunHelper getInstance() { return ScanGunHelper.SingletonHolder.instance; } /** * 返回扫码成功后的结果 */ private void performScanSuccess() { try { boolean mCaps = keyCodeList.contains(KeyEvent.KEYCODE_SHIFT_RIGHT) || keyCodeList.contains(KeyEvent.KEYCODE_SHIFT_LEFT); for (int keyCode : keyCodeList) { char aChar = getInputCode(keyCode, mCaps); if (aChar != 0) { mStringBufferResult.append(aChar); } } String barcode = mStringBufferResult.toString(); Log.e("ScanGunHelper", "barcode==" + barcode); mStringBufferResult.setLength(0); keyCodeList.clear(); if (mHandler != null) { mHandler.removeCallbacks(mScanningFishedRunnable); } } catch (Exception e) { e.printStackTrace(); } } /** * 扫码枪事件解析 */ public void analysisKeyEvent(KeyEvent event) { //Virtual是我所使用机器的内置软键盘的名字 //在这判断是因为项目中避免和软键盘冲突(扫码枪和软键盘都属于按键事件) int keyCode = event.getKeyCode(); if (event.getAction() == KeyEvent.ACTION_UP) { keyCodeList.add(keyCode); if (keyCode == KeyEvent.KEYCODE_ENTER) { mHandler.removeCallbacks(mScanningFishedRunnable); mHandler.post(mScanningFishedRunnable); } else { mHandler.removeCallbacks(mScanningFishedRunnable); mHandler.postDelayed(mScanningFishedRunnable, MESSAGE_DELAY); } } } //获取扫描内容 private char getInputCode(int keyCode, boolean mCaps) { char aChar; if (keyCode >= KeyEvent.KEYCODE_A && keyCode <= KeyEvent.KEYCODE_Z) { //字母 aChar = (char) ((mCaps ? 'A' : 'a') + keyCode - KeyEvent.KEYCODE_A); } else if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) { //数字 aChar = (char) ('0' + keyCode - KeyEvent.KEYCODE_0); } else { //其他符号 switch (keyCode) { case KeyEvent.KEYCODE_PERIOD: aChar = '.'; break; case KeyEvent.KEYCODE_MINUS: aChar = mCaps ? '_' : '-'; break; case KeyEvent.KEYCODE_SLASH: aChar = '/'; break; case KeyEvent.KEYCODE_BACKSLASH: aChar = mCaps ? '|' : '\'; break; default: aChar = 0; break; } } return aChar; } /** * 输入设备是否存在 */ public static boolean isScanGunExist(KeyEvent event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Log.e("ScanGunHelper", "ProductId==" + event.getDevice().getProductId() + ",VendorId==" + event.getDevice().getVendorId()); if (event.getDevice().getVendorId() == 1409 && event.getDevice().getProductId() == 262) { return true; } } return false; } }

如果用的扫码模块有确定的ProductId和VendorId,可以直接过滤,写死ProductId和VendorId会使得程序很不灵活,万一换了一款扫码模块就不适配了,所以建议做成可配置,避免很多麻烦

如果不用ProductId和VendorId过滤输入事件,那就区分一下软键盘即可,系统自动软件盘的DeviceId为-1,只要不等于-1,就是扫码模块输入的字符。

单列模式封装代码,主要是考虑到一台安卓一体机不可能接入两个扫码模块,当成唯一设备作为处理即可。

2.在基类的Activity中使用,确保每个界面能拦截到数据,方便使用,不需要每个界面都拦截

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.KeyEvent; import android.view.WindowManager; public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getDeviceId() > 0) { ScanGunHelper.getInstance().analysisKeyEvent(event); return true; } return super.dispatchKeyEvent(event); } }

总结:

现在的USB扫码模块是比较流行,但是扫码模块与终端设备的通信方式花样百出,有wifi、蓝牙、USB、串口等等,但是万变不离其宗,对于安卓设备而言,扫码模块就是个外接键盘,不管是什么方式通信也好(除了串口以外),最终呈现的形态就是个外接键盘,当然,我们也可以使用蓝牙读取扫码数据,这些都是so esay了,串口更加简单,有实际的串口线更好,虚拟串口会麻烦一点,每次插拔虚拟串口号会不固定,不同的安卓设备表现出的串口号也尽不相同,所以虚拟串口模式需要做很多适配工作,不能写死一个虚拟串口号,这样会照成程序不灵活、不适配,做成可配置,才能应付多变的招标现场或者客户需求现场。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。

最后

以上就是辛勤大地最近收集整理的关于Android接入USB扫码模块的方法的全部内容,更多相关Android接入USB扫码模块内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(137)

评论列表共有 0 条评论

立即
投稿
返回
顶部