安卓源码:拦截USB-HID协议内容(模拟键盘输入方式的读卡器)
前言
接触到的扫描设备分为三类:1)-usb或其它方式转串口,常规的打开读取串口即可;2)-usb模拟键盘输入模式,这种模式底层不是串口;3)原生串口模式,最简单,但这种接口普通手机没有。
本文只介绍第二种USB键入模式,通过USB设备查找、匹配、打开、数据读这个流程,可以先于并阻止安卓系统获得内容,就是说如果是后台进程这样读取后,安卓输入框中不会显示扫描到的内容
设备特点
USB接入方式、即插即用不需要驱动、可以在任意输入框内扫描并“输入”字符串、最后回车。例如,打开一个文本编辑器并处于活动状态,刷卡后可以看到就像键盘输入了一样,得到10位长度的卡号、回车。
就是说这种设备的接入一般是不需要编程的,但是问题就在于它输出的内容也无法控制,就像是用户在通过一个键盘输入。
拦截这种设备需求的产生
如果你想在“用户输入”的内容上做一些处理怎么办?要么是响应键盘输入事件,要么是像本文一样直接拦截USB数据流。
先看一下运行效果
(注意:这里有个USB安全提示,一般设备都是无法去除的,在订制机或者拥有系统签名的情况下才能去除)
流程核心代码:
1,获得USB管理器:
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);if (usbManager == null) {this.mainHandler.obtainMessage(MainHandler.WHAT_SHOW_MESSAGE, "无法获得USB服务").sendToTarget();return false;}
2,匹配特定的设备:
//获得所有USB设备HashMap<String, UsbDevice> usbDeviceMap = usbManager.getDeviceList();if (usbDeviceMap.size() == 0) {this.mainHandler.obtainMessage(MainHandler.WHAT_SHOW_MESSAGE, "找不到USB设备").sendToTarget();return false;}for (final UsbDevice device : usbDeviceMap.values()) {Log.d(tag, "USB:pid=" + device.getProductId() + " vid=" + device.getVendorId());if (USB_DEV_PID == device.getProductId() && USB_DEV_VID == device.getVendorId()) {this.mainHandler.obtainMessage(MainHandler.WHAT_SHOW_MESSAGE, "已找到USB读卡器").sendToTarget();targetUsb = device;break;}}
3,打开USB连接
usbDeviceConnection = usbManager.openDevice(targetUsb);if (usbDeviceConnection == null) {mainHandler.obtainMessage(MainHandler.WHAT_USB_ERROR, "打开USB设备失败").sendToTarget();return;}UsbInterface usbInterface = targetUsb.getInterface(0);if (!usbDeviceConnection.claimInterface(usbInterface, true)) {mainHandler.obtainMessage(MainHandler.WHAT_USB_ERROR, "不是已知协议的USB设备,无法使用").sendToTarget();return;}
4,开始读取
ArrayList<Byte> listBytes = new ArrayList<>();byte[] buffer = new byte[maxPackageSize];UsbEndpoint inEndpoint = usbInterface.getEndpoint(0);mainHandler.obtainMessage(MainHandler.WHAT_READING, "读取准备就绪,请刷卡").sendToTarget();deviceReading = true;while (!Thread.interrupted()) {int ret = usbDeviceConnection.bulkTransfer(inEndpoint, buffer, buffer.length, 200);if (ret > 0) {byte[] reab = new byte[ret];System.arraycopy(buffer, 0, reab, 0, ret);//Log.d(tag, "读取到:" + bytesToHexString(reab));//字节流断句for (byte ab : reab) {if (ab == (byte) 0x28) {if (listBytes.size() > 0) {Byte[] lineBytes = listBytes.toArray(new Byte[0]);getCarCodeBytes(ArrayUtils.toPrimitive(lineBytes));listBytes.clear();}} else if (ab != (byte) 0x00) {listBytes.add(ab);}}}}
5,解析字节原理
读取到的字节为USB-键值,对照表如下(设备不会输出其它值,故只列出相关部分):
1E Keyboard 1
1F Keyboard 2
20 Keyboard 3
21 Keyboard 4
22 Keyboard 5
23 Keyboard 6
24 Keyboard 7
25 Keyboard 8
26 Keyboard 9
27 Keyboard 0
6,解析方法:
private void decode(byte[] bytes) {//转换时,可以直接一一对照,我这里用简单的减法StringBuilder intString = new StringBuilder();for (byte ab : bytes) {//按字节循环//如果0x27,由于它的10进制是39,减去29是10,所以单独处理if (ab == (byte) 0x27) intString.append(0);//其它都是化为10进制后减去起始值29得到对应值else intString.append(ByteTools.byteToInt(ab) - 29);}String hex = Long.toHexString(Long.parseLong(intString.toString()));//TODO 获得字符串后继续其它业务
}
硬件及安卓源码
完整项目下载见我的资源《《USB读卡器安卓源码》》。
测试需要设备
1,读卡器可以到TB搜索USB读卡器,或者直接扫描我图片里的二维码,找类似的就行,只要是这种方式的都一样。
2,公头小口转母口大口的USB,TYPE-c或者MicroUsb的就看测试用的手机了。
文章写的有点糙,因为是两个版本的原因,改来改去都不满意,最后直接上全部代码,Android Studio项目整体压缩的,直接打开就行了。
注意,使用USB设备时如果没有系统权限,需要申请USB使用权限。
安卓源码:拦截USB-HID协议内容(模拟键盘输入方式的读卡器)相关推荐
- USB HID 协议
USB HID 协议入门 转载请注明来源:cuixiaolei的技术博客 USB HID设备类的应用场合 USB HID类是USB设备的一个标准设备类,包括的设备非常多.HID类设备定义它属于人机交互 ...
- 安卓源码AOSP下载使用的正确姿势
安卓源码AOSP下载使用的正确姿势 从同步源码到编译完成,整个过程应至少准备200G空间. 编译时需要的内存数与编译线程数相关,博主实测比较极限的配置是4核8G,超过这个范围将触发swap交换导致编译 ...
- 【源码篇】安卓源码解析(持续总结)
前言 在Linux中,一切皆为文件.安卓底层也是基于Linux开发的. 在我们了解源码目录的时候,我们要先知道这些源码的后缀名代表的是什么文件,什么意思,才能更好的去了解其中的原理. 文章目录 前言 ...
- windows编译安卓源码记录
环境 Windows10 + vmware17 + ubuntu22 ubuntu环境设置 装完ubuntu系统后拖拽复制文件进去验证vmtools功能情况,如果vmtools异常很麻烦,试了n多方法 ...
- 安卓源码(一)下载与同步
推荐系统:基于Debian8的Linux发行版,ubuntu16.04,(因为安卓源码实在ubuntu下编译的,redhat系没有) 我使用的系统:Deepin15.3(ubuntu是debian8 ...
- 安卓与单片机进行usb hid通信
安卓USB_HID通信文档 因为一直在研究stm32,需要用到usb hid通信,就研究了安卓与stm32进行usb hid通信,目前已经能进行正常通信,我这里只跟大家说一下通信时需要注意的问题. u ...
- 直播源码中有哪些网络协议需要注意?
在当今的直播平台中,对直播源码越来越注重.那么直播源码中有哪些网络协议需要注意的呢? 1.TCP:TCP为点对点的协议,虽然能保证了数据传输的可靠性,但是对服务器资源耗费较大,在数据流大的场合难以保证 ...
- 安卓编译安装python_安卓源码编译环境搭建
本编译环境以 Ubuntu 14.04 系统为例 修改软件源(可选) 安装相关依赖 安装Android编译工具JDK 一. 修改软件源(可选) : sudo gedit /etc/apt/source ...
- mac下编译安卓源码
资源 Mac OS10.12 编译Android源码8.1 aosp编译-需翻墙 Mac下编译安卓源码 手把手教你在Mac OS下载.编译及导入Android源码 步骤 准备 磁盘空间大于180G 安 ...
最新文章
- C++ 中 inline 用法概述
- 基于springboot实现的仓储管理系统
- linux - word frequency
- jzoj6065-[NOI2019模拟2019.3.18]One?One!【FFT】
- UIKit应用 - Swift 版本: 3.让UITableViewCell的背景色渐变
- js php 中文乱码怎么解决_php中文乱码怎么解决
- Java IO类库之CharArrayWriter
- 【堆】这是要搞事情啊——取出
- linux ssh 推送文件_通过SSH实现Windows与linux之间传输文件
- Node.js跨域请求解决方案
- HP 8770W windows10 1803 安装 HP 3D DriveGuard
- 2021年华为Java面经,顺利收获Offer
- java+mysq 基于jsp825幼儿园管理系统(java,web)
- 某种家庭式光伏发电系统设计
- 一文彻底搞懂加密、数字签名和数字证书,看不懂你打我!
- 局域网之间两台计算机同屏,spacedesk解决两台电脑同屏的问题
- 人工智能技术应用的领域主要有哪些?
- excel 筛选 粘贴_在筛选的Excel列表中粘贴快捷方式
- Gerrit 2.11.5 发布,代码评审工具
- Xilinx的FPGA手册中关于如何Booting RFSoCsZynq