硬件条件:

  1. OTG接口转换器(或者自带usb接口的设备(大头))
  2. USB扫码枪(支持USB虚拟串口)
  3. 安卓设备

实现方式:

  1. 串口方式
  2. 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扫码枪获取数据流的实现方式相关推荐

  1. Android USB 扫码枪获取扫描内容

    最近做了关于在Android设备上外接扫码的项目,在此记录一下关于Android USB扫码枪获取内容的问题 首先我这边使用是USB HID的扫码枪,即插即用,只需要在界面上有一个带有焦点的EditT ...

  2. js 条码枪扫描_js获取USB扫码枪数据

    前言 找了很多相关的教程不太好用,汲取各家之长总结精简了一下 原理 扫码枪扫描到的条形码每一位会触发一次onkeydown事件 比如扫描条码位'1234567890'的条形码,会连续执行10次onke ...

  3. python读取usb扫码枪数据_USB

    Android使用AccessibilityService实现USB扫码枪数据抓取 android单屏机,通过扫码枪扫描二维码的场景非常多,扫码枪的种类也有蓝牙.USB.串口等等 目前USB的扫码枪主 ...

  4. USB扫码枪二维码读取(二)——MFC篇

    USB扫码枪为即插即用,通过类似键盘的方式和系统进行交互,在MFC中进行处理比较方便,对键盘消息进行处理即可. (1)文本框输入获取焦点,扫描后自动显示在文本框内. (2)在PreTranslateM ...

  5. USB扫码枪二维码读取(一)——U3D篇

    USB扫码枪为即插即用,通过类似键盘的方式和系统进行交互,扫描出来的数据获取方式有两种实现方式. (1)文本框输入获取焦点,扫描后自动显示在文本框内. (2)使用键盘钩子,勾取扫描枪虚拟按键,进行键盘 ...

  6. [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入

    [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入 [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入 [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入 1.扫描枪获取数据原理基本 ...

  7. USB扫码枪无焦点输入到指定页面、指定文件框中

    USB扫码枪无焦点输入到指定页面.指定文件框中 USB扫码枪无焦点输入到指定页面.指定文件框中 新建工程添一个MDIParent窗口,两个FORM窗口.第一步添加一个类(ScanerHook),代码如 ...

  8. Android通过扫码枪获取到商品的编码 完成自动搜索

    最近要做一个大型的Android设备的软件,是超市前台收银的设备,机器上有外接扫码枪等设备,这里的扫码枪指的是外接USB扫码枪 其本质是模拟输入法的一段输入流 通过获取焦点的EditText 可以直接 ...

  9. 获取服务器路径的方式 【记录】

    JSP页面获取服务器路径的方式 1.basePath方式 <% String path = request.getContextPath(); String basePath = request ...

最新文章

  1. 软件定义网络 对我们有多重要?
  2. opencv文件路径问题
  3. Codeforces Round #476 (Div. 2) A. Paper Airplanes
  4. http发送16进制报文_阿里云物联网平台使用心得(25)MQTT协议详解UNSUBSCRIBE报文...
  5. CSS基础「五」定位
  6. [hdu1269]迷宫城堡(SCC)
  7. 【Flink】FLink PipelineExecutorFactory 基于工厂模式的任务提交与SPI机制
  8. Java 机器学习库 Tribuo
  9. JS中的各种尺寸问题
  10. java 多线程 6 : 同步锁(Lock)
  11. jQuery mobile 开发问题记录
  12. 卡方分布、T分布和F分布
  13. 《21天学通Java(第6版)》—— 1.6 总结
  14. iozone磁盘读写测试工具的使用以及命令详解、下载(网站最详细讲解步骤)
  15. 对话Ruby创始人松本行弘、阿里高级技术专家朴灵!
  16. GC暂停时间过长——未关闭Swap
  17. spring跨重定向传递数据
  18. 华为云NP考试题库_华为云服务考试 华为云hcip认证试题
  19. mysql数据库合库数据库合并心得
  20. 央联众商理财公司,我个人的理财观!

热门文章

  1. Ubuntu20.4安装百度云盘
  2. 不用写代码的Android 2D RPG游戏引擎
  3. CA6140后托架(831001)加工工艺及夹具设计CAD图纸(论文 CAD图纸 开题报告 任务书 工艺卡 文献翻译)
  4. 日历表的jq简单写法
  5. 利用Gitlab进行代码的协作开发
  6. JS 实现十大排序算法
  7. iPhone、iPad所有字体UIFont
  8. CAD图纸如何免费导出成Word文档?
  9. oracle 官网邮箱和密码是什么,我是如何进入21cn内网的(可能获取用户邮箱密码)...
  10. 使用成功路径实现数据库状态回传