USB扫码枪获取数据流的实现方式
硬件条件:
- OTG接口转换器(或者自带usb接口的设备(大头))
- USB扫码枪(支持USB虚拟串口)
- 安卓设备
实现方式:
- 串口方式
- USB方式
使用场景:
在扫码枪连接机器的时候,当扫码枪扫描到内容时,获取扫描到的内容。
解决的问题:
之前扫码枪使用的是USB模式(即扫描到的内容会直接输入到EditText之中,并且末尾会增加一个回车键),但是后来发现,当二维码包含中文的时候,中文不会输出进来,于是乎,使用以上两种方式实现。
实现思路:
连接扫码枪,因为数据肯定是以字节流的方式发送的,那么我们只需获取到输入的字节流,自己处理成需要的内容就可以了。
实现方式------串口方式:
需要经过以下几个步骤:
- 集成谷歌原生serial_port包,参考该文章集成就可以了: Android串口集成
- 寻找设备串口地址(这个咱们仅仅是为了获取串口地址,因为串口地址是固定的,所以这里可以不加在程序中,咱们目的是为了知道USB扫码枪的串口地址)
- 连接设备
- 获取数据流
步骤一:集成谷歌原生serial_port包,这个自己看上面教程了。
步骤二:寻找设备串口地址,在完成步骤一之后,会有一个SerialPortFinder的类,这个类的作用是寻找咱们安卓设备上连接的串口设备(包括扫码枪),具体获取扫码枪串口地址的思路:获取未插入扫码枪时所有设备的串口地址------》获取插入扫码枪时所有设备的串口地址
-----》看看多出那个,多出的那个就是扫码枪的串口地址了,废话不多说,直接贴代码了:
case R.id.btn_print://获取所有串口设备地址,mFinder就是SerialPortFinderStringBuffer stringBuffer = new StringBuffer();for (String str:mFinder.getAllDevicesPath()) {stringBuffer.append(str + "\n");}mTvMessage.setText(stringBuffer.toString());break;
怎么找USB扫码枪你懂我意思吧。
步骤三:连接设备:
废不多讲,首先咱们连接到串口设备,如果你连接不上,那么就是步骤一有问题,请到步骤一那篇博客问问作者:
private String mSerialPath = "/dev/ttyUSB0" ;//物理串口地址,这个就是咱们步骤二找到的地址了,这是我的设备的地址,你的自己找去private int baudrate = 9600;//波特率,这个是可以扫码枪自己设置的,看说明书private SerialPort mSerialPort;private InputStream mInputStream;@Overrideprotected int getContentView() {return R.layout.activity_test;}@Overrideprotected void initView() {super.initView();initSerialPort();}private void initSerialPort(){//连接串口设备,建议加try,硬件设备你永远不知道会为啥崩溃try {mSerialPort = new SerialPort(new File(mSerialPath),baudrate);mInputStream = mSerialPort.getInputStream();ReadThread thread = new ReadThread();//这是读取数据流的线程,代码在下方贴出thread.start();//启动数据流读取线程} catch (Exception e) {e.printStackTrace();}}
步骤四:获取数据流,这时候步骤三,我们开启了一个线程读取扫码枪的数据流,这时候我写了一个死循环,轮询扫码枪发送的内容,线程代码如下
private InputStream mInputStream;/*** 读串口线程*/private class ReadThread extends Thread {//这是我的内部类,我代码习惯不好,别瞎鸡儿抄@Overridepublic void run() {super.run();while ((!Thread.currentThread().isInterrupted())) {final int size;try {if (mInputStream == null)return;final byte[] buffer = new byte[512];size = mInputStream.read(buffer);//这就是扫描到的内容了if (size > 0) {runOnUiThread(new Runnable() {@Overridepublic void run() {try {ToastUtils.makeText(TestActivity.this,new String(buffer,"GB2312"));//此处我设置的编码是GB2312,这个可以看说明书,可以设置的} catch (UnsupportedEncodingException e) {e.printStackTrace();}}});}Thread.sleep(300);//你自己可以设置睡眠时间,这个睡眠时间可以会影响识别速度,那么就可以叫用户加钱,你懂我意思吧。} catch (Exception e) {//如果抛出异常则再次设置中断请求Thread.currentThread().interrupt();return;}}}}
嗯,到了这一步,大功告成了。
注意:串口方式实现的话兼容性不好,因为遇到部分安卓设备直接阉割了这部分功能,所以我才会研究USB方式的。
惊不惊喜,意不意外。
实现方式------USB方式:
该种方式好处在于不需要集成serial_port包,但是里面一些类理解比较灵性,USB方式需要经过以下几个步骤:
- 寻找需要连接的devices设备
- 连接设备
- 获取数据流
步骤一:寻找需要连接的devices设备,这里的话有两种场景
1.USB扫码枪一直插在安卓设备上,我们需要在程序启动的时候自动找到并且连接
2.USB扫码枪在热拔插的情况下,我们需要在插入的时候连接
第一种的话我是直接写了一个方法,在程序启动的时候检查时候插入需要支持的设备类型,如果有,那么直接连接,判断方法是通过设备的pid和vid对比进行判断,pid和vid获取方式自己百度,或者把扫码枪插在电脑上,在设备管理可以看到,我通过findDevices方法找到需要连接的扫码枪设备。
贴代码:
private UsbManager mManager;//查找已连接的设备UsbDevice findDevices() {if (null == mManager) {return null;}HashMap<String, UsbDevice> mMap = mManager.getDeviceList();for (UsbDevice device : mMap.values()) {if (BaseScanner.isS5920(device) || BaseScanner.isS5600(device)) {//判断设备是否支持的类型return device;}}return null;}
这是baseScanner,这个类名我觉得不够准确,它是用来记录需要支持的设备的信息的,包含设备的判断方法:
public class BaseScanner{private static final int scanner5600_pid = 4456;private static final int scanner5600_vid = 866;private static final int scanner5920_pid = 9527;private static final int scanner5920_vid = 549;public static boolean isS5600(UsbDevice usbDevice){//是不是s5600扫码枪return usbDevice.getProductId() == scanner5600_pid && usbDevice.getVendorId() == scanner5600_vid;}public static boolean isS5920(UsbDevice usbDevice){//是不是s5920return usbDevice.getProductId() == scanner5920_pid && usbDevice.getVendorId() == scanner5920_vid;}
}
第二种USB扫码枪热拔插连接方式,这时候我们采用的是广播监听的方式,因为设备拨叉都会有广播发送,这条广播包含的信息包含一个USBDevices对象(也就是扫码枪),我们需要动态注册拔,插两条广播,静态注册不生效,代码如下:
//这是广播类,因为我的扫描是写在一个service中,所以把连接的设备交给service处理就可以
public class USBBroadcastReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubString action = intent.getAction();if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (device != null) {// call your method that cleans up and closes communication with the deviceToast.makeText(context, "拔出", Toast.LENGTH_LONG).show();}}else if(UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)){//设备插入UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);//获取插入的设备Intent intent1 = new Intent(context,ScannerService.class);Bundle bundle = new Bundle();bundle.putParcelable("device",device);intent1.putExtra("data",bundle);//将设备包入intent中,交给service处理context.startService(intent1);Toast.makeText(context, "插入", Toast.LENGTH_LONG).show();}}}
我是在程序启动的时候就注册了这个广播如下:
public class MyApplication extends Application {private USBBroadcastReceiver mUsbReceiver;@Overridepublic void onCreate() {super.onCreate();registBroadCast();}@Overridepublic void onTerminate() {unregisterReceiver(mUsbReceiver);super.onTerminate();}private void registBroadCast(){//注册USB插拔广播mUsbReceiver = new USBBroadcastReceiver();IntentFilter usbDeviceStateFilter = new IntentFilter();usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);//插入设备状态usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);//拔出设备状态registerReceiver(mUsbReceiver, usbDeviceStateFilter);}}
步骤二,连接设备,这边我把所有都写注释里面:
private UsbDevice mDevide;private UsbDeviceConnection mConnect;private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";private static UsbConnectManager mInstance;private ScannerListener mListener;private UsbManager mManager;private UsbEndpoint mUsbEndpointIn;private UsbInterface mUsbInterface;private Thread mReadingthread;public void connetDevice(UsbDevice device, Context context) {disConnect();//断开之前的连接mDevide = device;//当前需要连接的设备try {if (!mManager.hasPermission(mDevide)) {//检查是否有扫码枪的访问权限,如果没有,那么请求一下临时权限PendingIntent intent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);mManager.requestPermission(mDevide, intent);}mConnect = mManager.openDevice(mDevide);//打开设备mUsbInterface = device.getInterface(0);//获取数据的接口.这个可以理解成设备有多少个线头子mUsbEndpointIn = mUsbInterface.getEndpoint(0);//获取设备的输出流向,输入或者输出因为usb扫码枪只有一个输出项,所以直接选择0if (mConnect.claimInterface(mUsbInterface, true)) {//获取设备数据写入流,如果获取成功,那么数据已经通常,我这边写的是一个获取数据,输入数据的话把getEndpoint(0)换成输入的接口即可Log.i(TAG, "connetDevice: find device,start get data!!!");startReading();//开启读取数据流的线程} else {mConnect.close();Log.i(TAG, "connetDevice: not find device !!!");}} catch (Exception e) {e.printStackTrace();}}
步骤三,获取输入的流,并解析成需要的内容,代码如下:
//开线程读取数据private void startReading() {if (null != mReadingthread) {mReadingthread.interrupt();}mReadingthread = new Thread(new Runnable() {@Overridepublic void run() {while (!mReadingthread.isInterrupted()) {synchronized (this) {byte[] bytes = new byte[128];int ret = mConnect.bulkTransfer(mUsbEndpointIn, bytes, bytes.length, 100);//获取数据流if (ret > 0) {try {byte[] bs = new byte[ret];System.arraycopy(bytes, 0, bs, 0, ret);//获取数据长度String str = new String(bs,"GB2312");//转换成汉字if (null != mListener){mListener.onScanner(str);//你自己需要的处理方式}} catch (UnsupportedEncodingException e) {e.printStackTrace();}}}}}});mReadingthread.start();}
OK啦,USB模式的也完成了。
有疑问或者有建议的膀友可以加群:497438697 我是群里的 杭州-大魔王,有艾特必应。
祝大家新年快乐,万事亨通!!!
USB扫码枪获取数据流的实现方式相关推荐
- Android USB 扫码枪获取扫描内容
最近做了关于在Android设备上外接扫码的项目,在此记录一下关于Android USB扫码枪获取内容的问题 首先我这边使用是USB HID的扫码枪,即插即用,只需要在界面上有一个带有焦点的EditT ...
- js 条码枪扫描_js获取USB扫码枪数据
前言 找了很多相关的教程不太好用,汲取各家之长总结精简了一下 原理 扫码枪扫描到的条形码每一位会触发一次onkeydown事件 比如扫描条码位'1234567890'的条形码,会连续执行10次onke ...
- python读取usb扫码枪数据_USB
Android使用AccessibilityService实现USB扫码枪数据抓取 android单屏机,通过扫码枪扫描二维码的场景非常多,扫码枪的种类也有蓝牙.USB.串口等等 目前USB的扫码枪主 ...
- USB扫码枪二维码读取(二)——MFC篇
USB扫码枪为即插即用,通过类似键盘的方式和系统进行交互,在MFC中进行处理比较方便,对键盘消息进行处理即可. (1)文本框输入获取焦点,扫描后自动显示在文本框内. (2)在PreTranslateM ...
- USB扫码枪二维码读取(一)——U3D篇
USB扫码枪为即插即用,通过类似键盘的方式和系统进行交互,扫描出来的数据获取方式有两种实现方式. (1)文本框输入获取焦点,扫描后自动显示在文本框内. (2)使用键盘钩子,勾取扫描枪虚拟按键,进行键盘 ...
- [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入
[C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入 [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入 [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入 1.扫描枪获取数据原理基本 ...
- USB扫码枪无焦点输入到指定页面、指定文件框中
USB扫码枪无焦点输入到指定页面.指定文件框中 USB扫码枪无焦点输入到指定页面.指定文件框中 新建工程添一个MDIParent窗口,两个FORM窗口.第一步添加一个类(ScanerHook),代码如 ...
- Android通过扫码枪获取到商品的编码 完成自动搜索
最近要做一个大型的Android设备的软件,是超市前台收银的设备,机器上有外接扫码枪等设备,这里的扫码枪指的是外接USB扫码枪 其本质是模拟输入法的一段输入流 通过获取焦点的EditText 可以直接 ...
- 获取服务器路径的方式 【记录】
JSP页面获取服务器路径的方式 1.basePath方式 <% String path = request.getContextPath(); String basePath = request ...
最新文章
- 软件定义网络 对我们有多重要?
- opencv文件路径问题
- Codeforces Round #476 (Div. 2) A. Paper Airplanes
- http发送16进制报文_阿里云物联网平台使用心得(25)MQTT协议详解UNSUBSCRIBE报文...
- CSS基础「五」定位
- [hdu1269]迷宫城堡(SCC)
- 【Flink】FLink PipelineExecutorFactory 基于工厂模式的任务提交与SPI机制
- Java 机器学习库 Tribuo
- JS中的各种尺寸问题
- java 多线程 6 : 同步锁(Lock)
- jQuery mobile 开发问题记录
- 卡方分布、T分布和F分布
- 《21天学通Java(第6版)》—— 1.6 总结
- iozone磁盘读写测试工具的使用以及命令详解、下载(网站最详细讲解步骤)
- 对话Ruby创始人松本行弘、阿里高级技术专家朴灵!
- GC暂停时间过长——未关闭Swap
- spring跨重定向传递数据
- 华为云NP考试题库_华为云服务考试 华为云hcip认证试题
- mysql数据库合库数据库合并心得
- 央联众商理财公司,我个人的理财观!