公司的设备以前接入的都是串口的扫码头,优点是直接通过串口读取流里面的数据就OK了,缺点是你需要知道每一款扫码器的型号以获取波特率及Android设备的串口地址。因为现在usb扫码器越来越方便且即插即用,不需要额外供电以及价格便宜等特点,公司以后开发的设备都打算采用usb扫码器。所以我开始尝试接入usb扫码器,下面就是我在接入时的方法以及遇到的一些问题。
import android.view.KeyEvent; public class ScanKeyManager { private StringBuilder mResult; public OnScanValueListener mListener; private boolean mCaps; public interface OnScanValueListener { void onScanValue(String value); } public ScanKeyManager(OnScanValueListener listener) { this.mListener = listener; this.mResult = new StringBuilder(); } /** * 扫码设备事件解析 */ public void analysisKeyEvent(KeyEvent event) { int keyCode = event.getKeyCode(); checkLetterStatus(event); if (event.getAction() == KeyEvent.ACTION_DOWN) { char aChar = getInputCode(mCaps, event.getKeyCode()); if (aChar != 0) { mResult.append(aChar); } if (keyCode == KeyEvent.KEYCODE_ENTER) { if (mListener != null) { mListener.onScanValue(mResult.toString()); } mResult.delete(0, mResult.length()); } } } /** * 判断大小写 */ private void checkLetterStatus(KeyEvent event) { int keyCode = event.getKeyCode(); if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT || keyCode == KeyEvent.KEYCODE_SHIFT_LEFT) { mCaps = event.getAction() == KeyEvent.ACTION_DOWN; } } /** * 将keyCode转为char * * @param caps 是不是大写 * @param keyCode 按键 * @return 按键对应的char */ private char getInputCode(boolean caps, int keyCode) { if (keyCode >= KeyEvent.KEYCODE_A && keyCode <= KeyEvent.KEYCODE_Z) { return (char) ((caps ? 'A' : 'a') + keyCode - KeyEvent.KEYCODE_A); } else { return keyValue(caps, keyCode); } } /** * 按键对应的char表 */ private char keyValue(boolean caps, int keyCode) { switch (keyCode) { case KeyEvent.KEYCODE_0: return caps ? ')' : '0'; case KeyEvent.KEYCODE_1: return caps ? '!' : '1'; case KeyEvent.KEYCODE_2: return caps ? '@' : '2'; case KeyEvent.KEYCODE_3: return caps ? '#' : '3'; case KeyEvent.KEYCODE_4: return caps ? '$' : '4'; case KeyEvent.KEYCODE_5: return caps ? '%' : '5'; case KeyEvent.KEYCODE_6: return caps ? '^' : '6'; case KeyEvent.KEYCODE_7: return caps ? '&' : '7'; case KeyEvent.KEYCODE_8: return caps ? '*' : '8'; case KeyEvent.KEYCODE_9: return caps ? '(' : '9'; case KeyEvent.KEYCODE_NUMPAD_SUBTRACT: return '-'; case KeyEvent.KEYCODE_MINUS: return '_'; case KeyEvent.KEYCODE_EQUALS: return '='; case KeyEvent.KEYCODE_NUMPAD_ADD: return '+'; case KeyEvent.KEYCODE_GRAVE: return caps ? '~' : '`'; case KeyEvent.KEYCODE_BACKSLASH: return caps ? '|' : '\'; case KeyEvent.KEYCODE_LEFT_BRACKET: return caps ? '{' : '['; case KeyEvent.KEYCODE_RIGHT_BRACKET: return caps ? '}' : ']'; case KeyEvent.KEYCODE_SEMICOLON: return caps ? ':' : ';'; case KeyEvent.KEYCODE_APOSTROPHE: return caps ? '"' : '''; case KeyEvent.KEYCODE_COMMA: return caps ? '<' : ','; case KeyEvent.KEYCODE_PERIOD: return caps ? '>' : '.'; case KeyEvent.KEYCODE_SLASH: return caps ? '?' : '/'; default: return 0; } } }
在该类中,我拦截处理了键盘输入事件的绝大部分字符,并把它转化成我们需要的数据通过接口回调传给我们需要用到的页面。
用法如下 在activity中使用import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.KeyEvent; public class MainActivity extends AppCompatActivity { private ScanKeyManager scanKeyManager; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //拦截扫码器回调,获取扫码内容 scanKeyManager = new ScanKeyManager(new ScanKeyManager.OnScanValueListener() { @Override public void onScanValue(String value) { Log.e("ScanValue", value); } }); } /*监听键盘事件,除了返回事件都将它拦截,使用我们自定义的拦截器处理该事件*/ @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() != KeyEvent.KEYCODE_BACK) { scanKeyManager.analysisKeyEvent(event); return true; } return super.dispatchKeyEvent(event); } } 在dialog中使用
public class ScanDialog extends Dialog { private ScanKeyManager scanKeyManager; private OnScanDialogListener mListener; public ScanDialog(Context context) { super(context, R.style.LoadDialogStyle); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.dialog_scan); setCanceledOnTouchOutside(false); scanKeyManager = new ScanKeyManager(new ScanKeyManager.OnScanValueListener() { @Override public void onScanValue(String value) { Log.e("dialog", value); if (mListener == null) return; mListener.onScanResult(value); } }); } @Override public boolean dispatchKeyEvent(@NonNull KeyEvent event) { scanKeyManager.analysisKeyEvent(event); return true; } public interface OnScanDialogListener { void onScanResult(String scanValue); } public void setOnScanDialogListener(OnScanDialogListener listener) { mListener = listener; } }
使用起来都是比较简单,只需要创建键盘拦截管理类,并设置监听回调,以及复写dispatchKeyEvent(KeyEvent event)拦截键盘事件就ok了,如果是dialog中使用则多了一个接口回调的步骤。
如果按照上述的方法去做是可以做到完美监听扫码器扫码事件的,但是我在实际使用中还遇到了一个比较严重问题,就是如果页面中有Edittext输入框的时候,如果我使用该方法拦截键盘事件之后,会出现数字,一些符号,以及删除键等一些字符输入无效的问题,好像这样我们在使用键盘拦截的时候就没法使用键盘输入了,那该怎么办呢?
上面我们说到,使用键盘拦截的时候就没法使用键盘输入了,那么有没有一种可能,就是我在键盘输入的时候不拦截键盘事件,不输入的时候我才进行拦截呢?这个时候就需要监听软键盘的显示和隐藏事件了,但是安卓系统所提供的api当中是没有监听键盘事件的,那么如果需要监听键盘事件就需要我们自定义了,我的另一篇文章中就对键盘的显示隐藏事件监听有比较好的解决办法,有兴趣的同学可以去看看Android软键盘显示隐藏事件监听。下面就开始上代码:
import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.KeyEvent; public class SecondActivity extends AppCompatActivity { private ScanKeyManager scanKeyManager; /*是否是输入状态(输入时扫码监听不拦截)*/ private boolean isInput = false; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); onKeyBoardListener(); //拦截扫码器回调,获取扫码内容 scanKeyManager = new ScanKeyManager(new ScanKeyManager.OnScanValueListener() { @Override public void onScanValue(String value) { Log.e("ScanValue", value); } }); } /*监听键盘事件,除了返回事件都将它拦截,使用我们自定义的拦截器处理该事件*/ @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() != KeyEvent.KEYCODE_BACK && !isInput) { scanKeyManager.analysisKeyEvent(event); return true; } return super.dispatchKeyEvent(event); } //监听软件盘是否弹起 private void onKeyBoardListener() { SoftKeyBoardListener.setListener(this, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() { @Override public void keyBoardShow(int height) { Log.e("软键盘", "键盘显示 高度" + height); isInput = true; } @Override public void keyBoardHide(int height) { Log.e("软键盘", "键盘隐藏 高度" + height); isInput = false; } }); } }
那么,这个时候就可以完美解决usb扫码器的监听问题啦,可能还会有小伙伴会问,那我在键盘弹起的时候岂不是就不能用扫码头了?这个其实不用担心,当我们不拦截键盘事件的时候,且Edittext获取焦点时,那么扫到的内容就会被自动输入到输入框中了。
由于安卓系统并没有提供软键盘弹入和弹出的系统方法,所以我们有时候需要用到监听软件盘的时候会非常的麻烦,今天我根据监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变超过一定的数值来监听软键盘的弹入弹出事件,使用起来也非常简单.
public class SoftKeyBoardListener { private View rootView;//activity的根视图 int rootViewVisibleHeight;//纪录根视图的显示高度 private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener; public SoftKeyBoardListener(Activity activity) { //获取activity的根视图 rootView = activity.getWindow().getDecorView(); //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变 rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //获取当前根视图在屏幕上显示的大小 Rect r = new Rect(); rootView.getWindowVisibleDisplayFrame(r); int visibleHeight = r.height(); System.out.println(""+visibleHeight); if (rootViewVisibleHeight == 0) { rootViewVisibleHeight = visibleHeight; return; } //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变 if (rootViewVisibleHeight == visibleHeight) { return; } //根视图显示高度变小超过300,可以看作软键盘显示了,该数值可根据需要自行调整 if (rootViewVisibleHeight - visibleHeight > 200) { if (onSoftKeyBoardChangeListener != null) { onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight); } rootViewVisibleHeight = visibleHeight; return; } //根视图显示高度变大超过300,可以看作软键盘隐藏了,该数值可根据需要自行调整 if (visibleHeight - rootViewVisibleHeight > 200) { if (onSoftKeyBoardChangeListener != null) { onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight); } rootViewVisibleHeight = visibleHeight; return; } } }); } private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener; } public interface OnSoftKeyBoardChangeListener { void keyBoardShow(int height); void keyBoardHide(int height); } public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity); softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener); } }
<activity android:name=".MainActivity" android:launchMode="singleTop" android:configChanges="keyboardHidden" android:windowSoftInputMode="adjustPan|stateHidden"/>
//监听软件盘是否弹起 private void onKeyBoardListener() { SoftKeyBoardListener.setListener(MainActivity.this, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() { @Override public void keyBoardShow(int height) { Log.e("软键盘", "键盘显示 高度" + height); } @Override public void keyBoardHide(int height) { Log.e("软键盘", "键盘隐藏 高度" + height); } }); }
如果该篇文章对你有用,希望你能够点个喜欢支持一下,如果其中有错误希望多多指正。
相关知识
思远创二维无线扫描枪付款码健康码快递一维码二维码
兴通XT205M5健康码条码扫描器售货机存储柜二维扫码模块
兴通XT2001C二维扫描平台桌面式条码枪条形码健康码扫码盒
身份证+二维码扫码二合一读卡器模组
XT7303P医用收款扫描枪电子健康卡识读终端核酸检测二维码扫描器
二三代社保卡+扫码+身份证多合一读卡器小模组
全国医疗电子健康卡、电子社保卡等介质的扫码设备
疫情码怎么扫(疫情扫健康码怎么扫)
华大HD
USB免驱多合一智能卡读写器 健康卡社保医保卡读卡器 NFC阅读器
网址: Android外接USB扫码枪 https://m.trfsz.com/newsview1805912.html