硬件系列(七)----------USB扫码枪

一、扫码枪工具类

public class BarcodeScannerResolver {

    private static final String TAG = BarcodeScannerResolver.class.getSimpleName();

    /**
     * 若500ms之内无字符输入,则表示扫码完成. (若觉得时间还长,则可以设置成更小的值)
     */
    private final static long MESSAGE_DELAY = 150;
    /**
     * 大写或小写
     */
    private boolean mCaps;
    /**
     * 扫码内容
     */
    private StringBuilder mResult = new StringBuilder();

    private OnScanSuccessListener mOnScanSuccessListener;
    private Handler mHandler = new Handler();

    private final Runnable mScanningEndRunnable = new Runnable() {
        @Override
        public void run() {
            performScanSuccess();
        }
    };

    /**
     * 调用回调方法
     */
    private void performScanSuccess() {
        String barcode = mResult.toString();
        Log.i(TAG, "performScanSuccess -> barcode: " + barcode);
        if (mOnScanSuccessListener != null) {
            mOnScanSuccessListener.onScanSuccess(barcode);
        }
        mResult.setLength(0);
    }

    /**
     * key事件处理
     *
     * @param event
     */
    public void resolveKeyEvent(KeyEvent event) {

        int keyCode = event.getKeyCode();
        //字母大小写判断
        checkLetterStatus(event);

        Log.w(TAG, "keyEvent:" + event + "keyCode: " + keyCode + "char: " + KeyEvent.keyCodeToString(keyCode));

        if (event.getAction() == KeyEvent.ACTION_DOWN) {

            char aChar = getInputCode(event);
            Log.w(TAG, "aChar: " + aChar);

            if (aChar != 0) {
                mResult.append(aChar);
            }

            if (keyCode == KeyEvent.KEYCODE_ENTER) {
                //若为回车键,直接返回
                mHandler.removeCallbacks(mScanningEndRunnable);
                mHandler.post(mScanningEndRunnable);
            } else {
                //延迟post,若500ms内,有其他事件
                mHandler.removeCallbacks(mScanningEndRunnable);
                mHandler.postDelayed(mScanningEndRunnable, MESSAGE_DELAY);
            }

        }
    }

    /**
     * 检查shift键
     *
     * @param event
     */
    private void checkLetterStatus(KeyEvent event) {
        int keyCode = event.getKeyCode();
        if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT || keyCode == KeyEvent.KEYCODE_SHIFT_LEFT) {
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                //按着shift键,表示大写
                mCaps = true;
            } else {
                //松开shift键,表示小写
                mCaps = false;
            }
        }
    }

    /**
     * 获取扫描内容
     *
     * @param event
     * @return
     */
    private char getInputCode(KeyEvent event) {
        int keyCode = event.getKeyCode();

        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 interface OnScanSuccessListener {
        void onScanSuccess(String barcode);
    }

    public void setScanSuccessListener(OnScanSuccessListener onScanSuccessListener) {
        mOnScanSuccessListener = onScanSuccessListener;
    }

    public void removeScanSuccessListener() {
        mHandler.removeCallbacks(mScanningEndRunnable);
        mOnScanSuccessListener = null;
    }

}

二、使用说明

  • 1. 在Activity中先创建BarcodeScannerResolver对象,并设置扫码成功监听器: setScanSuccessListener() [一般在onCreate()方法中初始化]
  • 2. 接着在Activity#dispatchKeyEvent() 或者 Activity#onKeyDown() 中调用本类中的resolveKeyEvent()方法。当扫码结束之后,会自动回调第一步设置的监听器中的方法
    

三、原理分析

  • 扫码枪就是一个外部的输入设备(和键盘一样)。扫码的时候,就是在极短的时间内输入了一系列的数字或字母
  • 这样就可以在键盘事件中抓捕这些输入的字符,但是又会产生一个问题(快速扫两次的情形):在键盘事件中应该抓捕多少个字符呢?即一个条码应该在哪个位置结束呢? (有的扫码枪会以一个回车或者换行作为一次扫码的结束符,但是有的就纯粹的是一系列的条码。这个得需要设置)所以为了兼容性,应当是当短时间内不再输入字符的时候,就表示扫码已结束。这样只能定性描述,不能定量,只能自己在程序中用一个具体的数字来表示这个“短时间”,eg:500ms。(如果每个条码结束的时候都有一个结束符那该多好,直接判断这个结束符,就可以知道当前扫码已完成)
    

四、核心原理

  • 在Activity的键盘监听事件中,每抓捕到一个字符的时候,就先向 Handler 一次一个runnable对象,再延迟500ms发送一个runnable. 这样若两个输入字符的间隔时间超过了500ms,则视为两次扫码

五、使用示例

  • 在activity中:
/**
 * 扫码枪工具类
 */
private BarcodeScannerResolver mBarcodeScannerResolver;

在activity的onCreate方法中调用initScannerResolver();

/**
 * 初始化扫码监听
 */
private void initScannerResolver() {
    mBarcodeScannerResolver = new BarcodeScannerResolver();
    mBarcodeScannerResolver.setScanSuccessListener(new BarcodeScannerResolver.OnScanSuccessListener() {
        @Override
        public void onScanSuccess(String barcode) {
            Log.e("TAG", barcode);
            Toast.makeText(MainActivity.this, "扫码枪数据:" + barcode, Toast.LENGTH_SHORT).show();
        }
    });
}


@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() != KeyEvent.KEYCODE_BACK) {
        mBarcodeScannerResolver.resolveKeyEvent(event);
    }
    return super.dispatchKeyEvent(event);
}
  • 给edt设置监听,可以不设置,也可以设置,设置动作监听,在输入完成之后可以直接执行接下来的逻辑
//这是扫码枪输入
edt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        /**
         * 当actionId == XX_SEND 或者 XX_DONE时都触发
         * 或者event.getKeyCode == ENTER 且 event.getAction == ACTION_DOWN时也触发
         * 注意,这是一定要判断event != null。因为在某些输入法上会返回null。
         */
        if (actionId == EditorInfo.IME_ACTION_SEND
                || actionId == EditorInfo.IME_ACTION_DONE
                || (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode() && KeyEvent.ACTION_DOWN == event.getAction())) {
            Log.e("TAG", "扫码结束");
            if (!TextUtils.isEmpty(edt.getText().toString())) {
                mStringBuilder.append(edt.getText().toString().trim() + "\n");
                text_view_scan.setText(mStringBuilder);
                edt.setText("");
            }

        }
        return false;
    }
});
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值