欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

安卓扫码枪开发,拦截扫码事件

程序员文章站 2022-06-14 19:38:23
...

需求

普通的手机开发,可以做一个二维码扫码的页面,用zxing一类的可以轻松实现,但是,如果是大型的安卓系统的终端机的话,摄像头不方便使用。可以依靠扫码枪来实现类似的效果。

分析

大型安卓设备与安卓手机的开发区别还是比较大的,尤其是扫码枪部分,有以下特点。例如:

  • 终端机的开发中,经常是Activity 数量比较少,Fragment比较多。
  • 扫码枪需要全局响应。并不只局限于某一个Fragment。
  • 大多数扫码枪的原理是模拟键盘进行输入,所以不支持包含有汉字的二维码

大多数扫码枪是模拟键盘进行输入,大多数时候需要使用获取焦点的 EditText 接收其扫描的信息。
显然这并不能满足我们的需求。那么,仔细想一下,我们可以认为是在短时间内,识别了二维码中的非汉字信息,并依次按键。我们可以在按键的时候进行按键事件 onKeyDown 的拦截。等全部扫描完毕之后,再去执行其它操作。

实现

找规律

既然我们要进行按键事件拦截,那么就得有一个明确的拦截开始时间和结束时间。可以先通过打印所有的keycode,来观察扫码后都执行了哪些按键。
例如我的扫码枪,在真正内容开始前和结束后,会按下一个keycode 值为 143 的按键。即 KEYCODE_NUM_LOCK 小键盘锁 。
那么可以设置一个布尔值,标识当前是否是扫描状态。并在结束的时候进行下一步操作。即:

怎么进行下一步操作?方法太多了,EventBus,接口回调,方法,……

  var isScan = false;  // 当前是否是扫描状态
  ···
  if (keyCode == KeyEvent.KEYCODE_NUM_LOCK) {
            if (isScan) {
                LogUtils.e("String ==>" + ScanString)
                ScanString = ""
            } else {
                LogUtils.e("String ==>" + "开始扫描……")
            }
            isScan = !isScan
            return true;
        }
        if (isScan) {
            ScanString += getInputCode(event).toString()
            return true;
        }

拼接字符串

只获取到了 keycode 值不行,还需要将keycode值转为具体的内容。

    //获取扫描内容
    private fun getInputCode(event: KeyEvent): Char {
        val keyCode = event.keyCode
        val aChar: Char
        if (keyCode >= KeyEvent.KEYCODE_A && keyCode <= KeyEvent.KEYCODE_Z) {
            //字母
            aChar = (('a').toInt() + keyCode - KeyEvent.KEYCODE_A).toChar()
        } else if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
            //数字
            aChar = ('0' + keyCode - KeyEvent.KEYCODE_0).toChar()
        } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
            aChar = 0.toChar()
        } else {
            //其他符号
            aChar = event.unicodeChar.toChar()
        }
        return aChar
    }

代码

    var isScan = false;  // 当前是否是扫描状态
    var ScanString = "";  // 扫描出的内容

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (keyCode == KeyEvent.KEYCODE_NUM_LOCK) {
            if (isScan) {
                LogUtils.e("String ==>" + ScanString)
                ScanString = ""
            } else {
                LogUtils.e("String ==>" + "开始扫描……")
            }
            isScan = !isScan
            return true;
        }
        if (isScan) {
            ScanString += getInputCode(event).toString()
            return true;
        }
        return super.onKeyDown(keyCode, event)
    }

    //获取扫描内容
    private fun getInputCode(event: KeyEvent): Char {
        val keyCode = event.keyCode
        val aChar: Char
        if (keyCode >= KeyEvent.KEYCODE_A && keyCode <= KeyEvent.KEYCODE_Z) {
            //字母
            aChar = (('a').toInt() + keyCode - KeyEvent.KEYCODE_A).toChar()
        } else if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
            //数字
            aChar = ('0' + keyCode - KeyEvent.KEYCODE_0).toChar()
        } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
            aChar = 0.toChar()
        } else {
            //其他符号
            aChar = event.unicodeChar.toChar()
        }
        return aChar
    }

安卓keycode列表

详细列表 见 https://blog.csdn.net/feizhixuan46789/article/details/16801429
此处简单总结一下keycode列表。

  • 0-9 对应的是 KEYCODE_0 - KEYCODE_9,真实的值为 7 - 16
  • A-Z 对应的是 KEYCODE_A - KEYCODE_Z ,值为 29 - 54
  • 上下左右中 对应 19-23,
  • 功能键如下:
    KEYCODE_ENTER 回车键 66
    KEYCODE_ESCAPE ESC键 111
    KEYCODE_DPAD_CENTER 导航键 确定键 23
    KEYCODE_DPAD_UP 导航键 向上 19
    KEYCODE_DPAD_DOWN 导航键 向下 20
    KEYCODE_DPAD_LEFT 导航键 向左 21
    KEYCODE_DPAD_RIGHT 导航键 向右 22
    KEYCODE_MOVE_HOME 光标移动到开始键 122
    KEYCODE_MOVE_END 光标移动到末尾键 123
    KEYCODE_PAGE_UP 向上翻页键 92
    KEYCODE_PAGE_DOWN 向下翻页键 93
    KEYCODE_DEL 退格键 67
    KEYCODE_FORWARD_DEL 删除键 112
    KEYCODE_INSERT 插入键 124
    KEYCODE_TAB Tab键 61
    KEYCODE_NUM_LOCK 小键盘锁 143
    KEYCODE_CAPS_LOCK 大写锁定键 115
    KEYCODE_BREAK Break/Pause键 121
    KEYCODE_SCROLL_LOCK 滚动锁定键 116
    KEYCODE_ZOOM_IN 放大键 168
    KEYCODE_ZOOM_OUT 缩小键 169