当前位置: 首页 > article >正文

Android硬件通信之 USBManager通信

一 简介

1.1 USB是一种常见的设备端接口,在PC端,移动端等上面应用非常的广泛,这就涉及到USB设备与主机端的通信。下面就讲下Android设备上的USB通信流程。

1.2 在android提供了USBManager接口来管理USB设备,USBManager类是Android系统管理USB设备与操作的核心组件,涉及设备识别、权限请求、数据传输、事件监听等。通过USBManager,开发者可以实现设备模式切换、USB权限管理、配置选择、自定义USB驱动程序开发以及支持MIDI和音频设备的管理。

二 USBManager通信流程

2.1 添加USB权限和特性声明

<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-feature android:name="android.hardware.usb.host" />

2.2 初始化USB通信

   //设备管理器
    private UsbManager usbManager;
    //连接的设备
    private UsbDevice currentDevice = null;
    //连接状态类
    private UsbDeviceConnection connection;
    //USB连接接口
    private UsbInterface usbInterface;

    //请求权限
    private String ACTION_USB_PERMISSION = "com.your.package.USB_PERMISSION";
    private BroadcastReceiver mUsbBroadcast;

    /**
     * USB请求权限
     */
    private class UsbBroadcast extends BroadcastReceiver {
        public void onReceive(Context paramAnonymousContext, Intent paramAnonymousIntent) {
            try {

                String action = paramAnonymousIntent.getAction();
                // 判断广播类型
                if (ACTION_USB_PERMISSION.equals(action)) {
                    try {
                        // 如果用户同意,则对读写器进行操作
                        connectDevice();
                    } catch (Exception e) {
                        disconnectDevice();
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

2.3  注册USB广播接收器

IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(usbReceiver, filter);

2.4 搜索USB设备

    /**
     * 获取Usb列表
     * @return
     */
    public List<UsbDevice> getUsbPrinters() {
        List<UsbDevice> usbDevices = new ArrayList<>();
        usbManager = (UsbManager) App.getContext().getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

        while (deviceIterator.hasNext()) {
            UsbDevice device = deviceIterator.next();
            if (isCscidDevice(device)) {
                usbDevices.add(device);
            }
        }
        return usbDevices;
    }


    /**
     * 判断UsbDevice 是否为读卡器类型设备
     * @param device
     * @return true:读卡器设备
     */
    public boolean isCscidDevice(UsbDevice device) {
        if (device == null) {
            return false;
        }
        if (device.getInterfaceCount() == 0) {
            return false;
        }
        for (int i = 0; i < device.getInterfaceCount(); i++) {
            android.hardware.usb.UsbInterface usbInterface = device.getInterface(i);
           
            if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
                int productId = device.getProductId();
                int vendorId = device.getVendorId();
                if (productId == 10203 && vendorId == 5824) {
                    return true;
                }
            }
        }
        return false;
    }

2.5 请求权限,并连接设备

    /**
     * 连接设备
     */
    public void connectDevice() {
        try {
            //权限请求
            /*
             * 在使用USB读写器设备前,应用必须获得权限。
             * 为了确切地获得权限,首先需要创建一个广播接收器。在调用requestPermission()这个方法时从得到的广播中监听这个意图。
             * 通过调用requestPermission()这个方法为用户跳出一个是否连接该设备的对话框。
             */
            if (mUsbBroadcast == null) {
                mUsbBroadcast = new UsbBroadcast();
                IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
                App.getContext().registerReceiver(mUsbBroadcast, filter);
            }

            //获取全部设备
            if (currentDevice == null) {
                List<UsbDevice> usbDeviceList = getUsbPrinters();
                if (usbDeviceList.size() > 0) {
                    currentDevice = usbDeviceList.get(0);
                }
            }

            if (currentDevice != null) {
                // 检查设备是否具有所需的权限
                if (usbManager.hasPermission(currentDevice)) {
                    // 打开设备并进行通信
                    if (connection == null) {
                        connection = usbManager.openDevice(currentDevice);
                    }
                    if (connection != null) {
                        // 获取接口并配置
                        if (usbInterface == null) {
                            usbInterface = currentDevice.getInterface(0);
                        }
                        connection.claimInterface(usbInterface, true);

                        // 你可以在这里与设备进行通信
                        //readDataFromDevice();
                        Log.d(TAG, "连接到设备: " + currentDevice.getDeviceName());
                    } else {
                        Log.e(TAG, "无法打开设备: " + currentDevice.getDeviceName());
                    }
                } else {
                    // 如果没有则请求权限
                    PendingIntent mPermissionIntent = PendingIntent.getBroadcast(JuAiApp.getContext(), 0,
                            new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE);
                    usbManager.requestPermission(currentDevice, mPermissionIntent);
                }
            }
        } catch (Exception r) {
            r.printStackTrace();
        }

    }

2.6 发送数据,先获取UsbEndpoint输出流端点

/**
     * 发送数据
     *
     * @param message
     */
    UsbEndpoint endpointOut = null;

    private void sendDataToDevice(String message) {
        // 获取输出端点
        if (endpointOut == null) {
            for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                UsbEndpoint endpoint = usbInterface.getEndpoint(i);
                if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK &&
                        endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                    endpointOut = endpoint; // 获取输出端点
                    break;
                }
            }

        }

        if (endpointOut == null || connection == null) {
            Log.e(TAG, "输出端点或连接未初始化");
            return;
        }

        byte[] buffer = message.getBytes(); // 将要发送的字符串转换为字节数组
        int bytesSent = connection.bulkTransfer(endpointOut, buffer, buffer.length, 1000); // 1秒超时
        if (bytesSent < 0) {
            Log.e(TAG, "发送数据失败");
        } else {
            Log.d(TAG, "成功发送数据: " + message);
        }
    }

2.7 读取数据,先获取输入流端点

/**
     * 读取数据
     */
    UsbEndpoint endpointIn = null;
    private static final int BUFFER_SIZE = 1024; // 定义读取的缓冲区大小

    private void readDataFromDevice() {
        if (endpointIn == null) {
            // 获取输入端点
            for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                UsbEndpoint endpoint = usbInterface.getEndpoint(i);
                Log.e(TAG, "readDataFromDevice: " + endpoint.getType());
                Log.e(TAG, "getDirection: " + endpoint.getDirection());
                if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT &&
                        endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
                    endpointIn = endpoint; // 获取输入端点
                    break;
                }
            }
        }

        if (endpointIn == null || connection == null) {
            Log.e(TAG, "输入端点或连接未初始化");
            return;
        }


        byte[] buffer = new byte[BUFFER_SIZE]; // 创建缓冲区

        // 循环读取数据
        Thread readThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    int bytesRead = connection.bulkTransfer(endpointIn, buffer, buffer.length, 1000); // 1秒超时
                    if (bytesRead > 0) {
                        // 处理读取到的数据
                        String data = new String(buffer, 0, bytesRead); // 将字节数组转换为字符串
                        Log.d(TAG, "读取数据: " + data);
                    } else if (bytesRead == 0) {
                        Log.d(TAG, "没有更多数据可读");
                        break;
                    } else {
                        Log.e(TAG, "读取数据失败: " + bytesRead);
                        break;
                    }
                }
            }
        });
        readThread.start(); // 启动读取线程
    }

2.8 断开USB设备并关闭资源

/**
     * 断开设备
     */
    public void disconnectDevice() {
        try {
            if (usbManager != null && currentDevice != null && usbInterface != null) {
                // 获取之前连接的接口
                // 释放接口
                connection.releaseInterface(usbInterface);
                // 关闭连接
                connection.close();
                // 清空连接
                connection = null;
                usbInterface = null;
                //读取置空
                endpointIn = null;
                //写入置空
                endpointOut = null;
                //设备置空
                currentDevice = null;
                if (mUsbBroadcast != null) {
                    App.getContext().unregisterReceiver(mUsbBroadcast);
                }
                Log.d(TAG, "设备已断开: ");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

三 USB协议相关概念

3.1 USB常见类型,用于判断是哪种USB设备

//获取设备类型
for (int i = 0; i < device.getInterfaceCount(); i++) {
            android.hardware.usb.UsbInterface usbInterface = device.getInterface(i);
            /**
             * 设备类 ID	设备类名称	描述
             * 0x01	Audio	音频设备,如 USB 音频接口。
             * 0x02	Communications	通信设备,如调制解调器和网络适配器。
             * 0x03	HID (Human Interface Device)	人机接口设备,通常指键盘、鼠标等。
             * 0x05	Physical Interface Device	物理接口设备,通常用于各种控制设备。
             * 0x06	Image	图像设备,如 USB 摄像头和扫描仪。
             * 0x07	Printer	打印机设备。
             * 0x08	Mass Storage	大容量存储设备,如 USB 闪存驱动器和外部硬盘。
             * 0x09	Hub	USB 集线器。
             * 0x0A	CDC (Communications Device Class)	通信设备类,常用于调制解调器和串行口。
             * 0x0B	Smart ICCard	智能卡读卡器。
             * 0x0D	Content Security Device	内容保护设备,用于安全性应用。
             * 0x0E	Video	视频设备,如视频采集卡。
             * 0xEF	Miscellaneous	其他不属于上述类别的设备。
             * 0xFF	Vendor Specific	厂商自定义设备,通常特定于某个硬件厂商的设备。
             * @param deviceClass
             * @param deviceSubclass
             * @param deviceProtocol
             * @return
             */
            if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
                int productId = device.getProductId();
                int vendorId = device.getVendorId();
                if (productId == 10203 && vendorId == 5824) {
                    return true;
                }
            }
        }
ID设备类名称描述
0x01Audio音频设备,如 USB 音频接口。
0x02Communications通信设备,如调制解调器和网络适配器。
0x03HID(Human Interface Device)人机接口设备,通常指键盘、鼠标等。
0x05Physical Interface Device物理接口设备,通常用于各种控制设备。
0x06Image图像设备,如 USB 摄像头和扫描仪。
0x07Printer打印机设备。
0x08Mass大容量存储设备,如 USB 闪存驱动器和外部硬盘。
0x09Hub    USB 集线器。
0x0ACDC通信设备类,常用于调制解调器和串行口。
0x0BSmart ICCard智能卡读卡器。
0x0DContent Security Device内容保护设备,用于安全性应用。
0x0EVideo视频设备,如视频采集卡。
0x0FMiscellaneous其他不属于上述类别的设备。
0x0FVendor Specific

厂商自定义设备,通常特定于某个硬件厂商的设

3.2 设备信息参数

//获取设备类型
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
   //产品ID
	int productId = device.getProductId();
	//厂商ID
	int vendorId = device.getVendorId();
	if (productId == 10203 && vendorId == 5824) {
		return true;
	}
}
* DeviceName=/dev/bus/usb/005/007         USB端口名字
* ProductName=null                        产品名字
* DeviceId=5007(0x138F)                   设备ID
* VendorId=5824(0x16C0)                   厂商ID
* ProductId=10203(0x27DB)                 产品ID
* DeviceClass=0                           设备分类
* device Class 为0-------------      
* Interface.describeContents()=0          接口描述
* Interface.getEndpointCount()=2          接口端点数量
* Interface.getId()=0                     ID接口
* Interface.getInterfaceClass()=3         接口数量
* anInterface.getInterfaceProtocol()=0    接口协议数量
* anInterface.getInterfaceSubclass()=0
* device Class 为0------end-------

四 示例代码

public class USBManagerUtils {
    private static final String TAG = "USBManagerUtils";
    private static USBManagerUtils mInstance;

    public static USBManagerUtils getInstance() {
        if (mInstance == null) {
            synchronized (USBManagerUtils.class) {
                if (mInstance == null) {
                    mInstance = new USBManagerUtils();
                }
            }
        }
        return mInstance;
    }


    //设备管理器
    private UsbManager usbManager;
    //连接的设备
    private UsbDevice currentDevice = null;
    //连接状态类
    private UsbDeviceConnection connection;
    //USB连接接口
    private UsbInterface usbInterface;

    //请求权限
    private String ACTION_USB_PERMISSION = "com.your.package.USB_PERMISSION";
    private BroadcastReceiver mUsbBroadcast;

    /**
     * USB请求权限
     */
    private class UsbBroadcast extends BroadcastReceiver {
        public void onReceive(Context paramAnonymousContext, Intent paramAnonymousIntent) {
            try {

                String action = paramAnonymousIntent.getAction();
                // 判断广播类型
                if (ACTION_USB_PERMISSION.equals(action)) {
                    try {
                        // 如果用户同意,则对读写器进行操作
                        connectDevice();
                    } catch (Exception e) {
                        disconnectDevice();
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取Usb 打印机列表
     * get USB printer list
     *
     * @return
     */
    public List<UsbDevice> getUsbPrinters() {
        List<UsbDevice> usbDevices = new ArrayList<>();
        usbManager = (UsbManager) App.getContext().getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

        while (deviceIterator.hasNext()) {
            UsbDevice device = deviceIterator.next();
            if (isCscidDevice(device)) {
                usbDevices.add(device);
            }
        }
        return usbDevices;
    }


    /**
     * 判断UsbDevice 是否为读卡器类型设备
     * check a UsbDevice
     * DeviceName=/dev/bus/usb/005/007
     * ProductName=null
     * DeviceId=5007(0x138F)
     * VendorId=5824(0x16C0)
     * ProductId=10203(0x27DB)
     * DeviceClass=0
     * device Class 为0-------------
     * Interface.describeContents()=0
     * Interface.getEndpointCount()=2
     * Interface.getId()=0
     * Interface.getInterfaceClass()=3
     * anInterface.getInterfaceProtocol()=0
     * anInterface.getInterfaceSubclass()=0
     * device Class 为0------end-------
     *
     * @param device
     * @return true:读卡器设备
     * 对于同一型号的USB产品,其 vendorId 和 productId 通常是一致的,因为它们来自同一个制造商且属于同一产品系列。例如,如果一个制造商生产了一个特定的USB闪存驱动器型号,那么该型号的所有设备都会共享相同的 vendorId 和 productId。
     */
    public boolean isCscidDevice(UsbDevice device) {
        if (device == null) {
            return false;
        }
        if (device.getInterfaceCount() == 0) {
            return false;
        }
        for (int i = 0; i < device.getInterfaceCount(); i++) {
            android.hardware.usb.UsbInterface usbInterface = device.getInterface(i);
            /**
             * 设备类 ID	设备类名称	描述
             * 0x01	Audio	音频设备,如 USB 音频接口。
             * 0x02	Communications	通信设备,如调制解调器和网络适配器。
             * 0x03	HID (Human Interface Device)	人机接口设备,通常指键盘、鼠标等。
             * 0x05	Physical Interface Device	物理接口设备,通常用于各种控制设备。
             * 0x06	Image	图像设备,如 USB 摄像头和扫描仪。
             * 0x07	Printer	打印机设备。
             * 0x08	Mass Storage	大容量存储设备,如 USB 闪存驱动器和外部硬盘。
             * 0x09	Hub	USB 集线器。
             * 0x0A	CDC (Communications Device Class)	通信设备类,常用于调制解调器和串行口。
             * 0x0B	Smart ICCard	智能卡读卡器。
             * 0x0D	Content Security Device	内容保护设备,用于安全性应用。
             * 0x0E	Video	视频设备,如视频采集卡。
             * 0xEF	Miscellaneous	其他不属于上述类别的设备。
             * 0xFF	Vendor Specific	厂商自定义设备,通常特定于某个硬件厂商的设备。
             * @param deviceClass
             * @param deviceSubclass
             * @param deviceProtocol
             * @return
             */
            if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
                int productId = device.getProductId();
                int vendorId = device.getVendorId();
                if (productId == 10203 && vendorId == 5824) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 连接设备
     */
    public void connectDevice() {
        try {
            //权限请求
            /*
             * 在使用USB读写器设备前,应用必须获得权限。
             * 为了确切地获得权限,首先需要创建一个广播接收器。在调用requestPermission()这个方法时从得到的广播中监听这个意图。
             * 通过调用requestPermission()这个方法为用户跳出一个是否连接该设备的对话框。
             */
            if (mUsbBroadcast == null) {
                mUsbBroadcast = new UsbBroadcast();
                IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
                App.getContext().registerReceiver(mUsbBroadcast, filter);
            }

            //获取全部设备
            if (currentDevice == null) {
                List<UsbDevice> usbDeviceList = getUsbPrinters();
                if (usbDeviceList.size() > 0) {
                    currentDevice = usbDeviceList.get(0);
                }
            }

            if (currentDevice != null) {
                // 检查设备是否具有所需的权限
                if (usbManager.hasPermission(currentDevice)) {
                    // 打开设备并进行通信
                    if (connection == null) {
                        connection = usbManager.openDevice(currentDevice);
                    }
                    if (connection != null) {
                        // 获取接口并配置
                        if (usbInterface == null) {
                            usbInterface = currentDevice.getInterface(0);
                        }
                        connection.claimInterface(usbInterface, true);

                        // 你可以在这里与设备进行通信
                        //readDataFromDevice();
                        Log.d(TAG, "连接到设备: " + currentDevice.getDeviceName());
                    } else {
                        Log.e(TAG, "无法打开设备: " + currentDevice.getDeviceName());
                    }
                } else {
                    // 如果没有则请求权限
                    PendingIntent mPermissionIntent = PendingIntent.getBroadcast(App.getContext(), 0,
                            new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE);
                    usbManager.requestPermission(currentDevice, mPermissionIntent);
                }
            }
        } catch (Exception r) {
            r.printStackTrace();
        }

    }

    /**
     * 发送数据
     *
     * @param message
     */
    UsbEndpoint endpointOut = null;

    private void sendDataToDevice(String message) {
        // 获取输出端点
        if (endpointOut == null) {
            for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                UsbEndpoint endpoint = usbInterface.getEndpoint(i);
                if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK &&
                        endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                    endpointOut = endpoint; // 获取输出端点
                    break;
                }
            }

        }

        if (endpointOut == null || connection == null) {
            Log.e(TAG, "输出端点或连接未初始化");
            return;
        }

        byte[] buffer = message.getBytes(); // 将要发送的字符串转换为字节数组
        int bytesSent = connection.bulkTransfer(endpointOut, buffer, buffer.length, 1000); // 1秒超时
        if (bytesSent < 0) {
            Log.e(TAG, "发送数据失败");
        } else {
            Log.d(TAG, "成功发送数据: " + message);
        }
    }

    /**
     * 读取数据
     */
    UsbEndpoint endpointIn = null;
    private static final int BUFFER_SIZE = 1024; // 定义读取的缓冲区大小

    private void readDataFromDevice() {
        if (endpointIn == null) {
            // 获取输入端点
            for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                UsbEndpoint endpoint = usbInterface.getEndpoint(i);
                Log.e(TAG, "readDataFromDevice: " + endpoint.getType());
                Log.e(TAG, "getDirection: " + endpoint.getDirection());
                if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT &&
                        endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
                    endpointIn = endpoint; // 获取输入端点
                    break;
                }
            }
        }

        if (endpointIn == null || connection == null) {
            Log.e(TAG, "输入端点或连接未初始化");
            return;
        }


        byte[] buffer = new byte[BUFFER_SIZE]; // 创建缓冲区

        // 循环读取数据
        Thread readThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    int bytesRead = connection.bulkTransfer(endpointIn, buffer, buffer.length, 1000); // 1秒超时
                    if (bytesRead > 0) {
                        // 处理读取到的数据
                        String data = new String(buffer, 0, bytesRead); // 将字节数组转换为字符串
                        Log.d(TAG, "读取数据: " + data);
                    } else if (bytesRead == 0) {
                        Log.d(TAG, "没有更多数据可读");
                        break;
                    } else {
                        Log.e(TAG, "读取数据失败: " + bytesRead);
                        break;
                    }
                }
            }
        });
        readThread.start(); // 启动读取线程
    }


    /**
     * 断开设备
     */
    public void disconnectDevice() {
        try {
            if (usbManager != null && currentDevice != null && usbInterface != null) {
                // 获取之前连接的接口
                // 释放接口
                connection.releaseInterface(usbInterface);
                // 关闭连接
                connection.close();
                // 清空连接
                connection = null;
                usbInterface = null;
                //读取置空
                endpointIn = null;
                //写入置空
                endpointOut = null;
                //设备置空
                currentDevice = null;
                if (mUsbBroadcast != null) {
                    App.getContext().unregisterReceiver(mUsbBroadcast);
                }
                Log.d(TAG, "设备已断开: ");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

五 注意事项

5.1 对于同一型号的USB产品,其 vendorId 和 productId 通常是一致的,因为它们来自同一个制造商且属于同一产品系列。例如,如果一个制造商生产了一个特定的USB闪存驱动器型号,那么该型号的所有设备都会共享相同的 vendorId 和 productId。 

5.2 扫码枪usb插拔时,会造成Activity重新加载,说明对Activity生命周期有影响,需要处理一下。
可在Activity配置

android:configChanges="orientation|keyboard|keyboardHidden"

六 使用场景举例-扫码枪设备

6.1 Android端获取扫码枪数据一般有如下三种获取方式

  • USB键盘模式,自感模式(出厂默认):大多数扫码枪是模拟键盘进行输入(不支持包含有汉字的二维码),大多数时候需要使用带焦点的 EditText 接收其扫描的信息。设置一个带焦点的EditText进行接收,此方式容易漏读扩展的ASCII码数据,除非二维码是标准的ASCII码(1-128)。由于扫码枪会将扫描出来的内容转化为键盘事件,对应的就是Android中的KeyEvent事件,所以我们只需要在我们的activity中重写dispatchKeyEvent方法,即可获取相应事件。
  • 通过 USB COM连接扫码:发送扫码开关指令进行扫码,即基于Usb相关类控制扫码开关
  • USB串口自感模式:即串口连接(当扫码枪使用 USB 通讯接口,但主机应用程序是采用串口通讯方式接收数据),客户端只负责监听读取数据,无须控制扫码枪指令,需要依赖usb串口传输数据的第三方库:https://github.com/mik3y/usb-serial-for-android

6.2 USB键盘模式使用

/**
 * usb键盘模式扫码示例,无需EditText接收
 */
public class ScannerUsbKeyboardActivity extends AppCompatActivity {
    UsbKeyboardAutoScan usbKeyboardAutoScan;
    EditText et_barcode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.scanner_usb_keyboard_activity);
        et_barcode = findViewById(R.id.et_barcode);
        usbKeyboardAutoScan = new UsbKeyboardAutoScan();
        usbKeyboardAutoScan.setOnScanListener(new OnScanListener() {
            @Override
            public void onScanSuccess(String barcode) {
            	//扫码接收
                et_barcode.setText(barcode);
            }
        });
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (usbKeyboardAutoScan.isIntercept()
                && event.getKeyCode() != KeyEvent.KEYCODE_BACK) {//不处理返回键
            usbKeyboardAutoScan.analysisKeyEvent(event);
            return true;//防止输入框接收事件
        }
        return super.dispatchKeyEvent(event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        usbKeyboardAutoScan.cancel();
    }
}

 6.3 USB串口自感模式使用

/**
 * 基于usb扫码
 */
public class ScannerUsbActivity extends AppCompatActivity {
    BaseUsbScan usbScan;
    EditText et_barcode;
    UsbConfig usbConfig = new UsbConfig();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.scanner_usb_activity);
        et_barcode = findViewById(R.id.et_barcode);
        usbConfig.setProductId(1233);
        usbConfig.setVendorId(1234);
//        usbScan = new UsbCmdScan(this); //通过usb连接扫码, 发送命令扫码
        UsbConfig.SerialPortConfig serialPortConfig = new UsbConfig.SerialPortConfig();
        usbConfig.setSerialPortConfig(serialPortConfig);
        usbScan = new UsbComAutoScan(this);//通过usb转串口,自感模式,推荐
        usbScan.setOnScanListener(new OnScanListener() {
            @Override
            public void onScanSuccess(String barcode) {

            }
        });
    }


    public void listUsbDevice(View view) {
        //找到设备插入的usb孔对应UsbDevice
        List<UsbDevice> usbDevices = usbScan.getUsbDevices(this);
        for (UsbDevice device : usbDevices) {
            et_barcode.setText(et_barcode.getText() + "\n" + device.getDeviceName() + ",vendorID:" + device.getVendorId() + ",ProductId:" + device.getProductId());
        }
    }

    public void openUsbScan(View view) {
        int ret = usbScan.openScan(usbConfig);
        if (ret != 0) {
            showMsg("打开usb扫码失败,ret" + ret);
        } else {
            showMsg("打开usb扫码成功");
        }
    }

    private void showMsg(String s) {
        et_barcode.setText(s);
    }

    public void closeUsbScan(View view) {
        usbScan.closeScan();
    }

    public void loopScan(View view) {
        usbScan.startReading();
    }

    public void stopLoopScan(View view) {
        usbScan.stopReading();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        usbScan.closeScan();
    }
}


http://www.kler.cn/a/503563.html

相关文章:

  • 【gin】http方法了解,以及RESTful API与版本控制
  • 设计模式 行为型 访问者模式(Visitor Pattern)与 常见技术框架应用 解析
  • html中鼠标位置信息
  • # CentOS7 系统 /dev/mapper/centos-root满了,十步清理
  • 【某大型互联网企业】软件测试面试经验分享(1 ~ 3年)
  • LeetCode 2270: 分割数组的方案数
  • mybatis-spring @MapperScan走读分析
  • 国产编辑器EverEdit - 一个优秀的文本编辑器该有的删除功能
  • Chat2DB
  • Vue.js 组件开发:构建可复用的UI元素
  • 【深度学习】PyTorch:手写数字识别
  • 接口测试Day09-数据库工具类封装
  • nvm use使用nodejs版本时报错
  • 深度学习学习笔记(第29周)
  • 【Linux】【内存】Buddy内存分配基础 NUMA架构
  • HarmonyOS NEXT边学边玩,从零开发一款影视APP(二、首页轮播图懒加载的实现)
  • 用css 现实打字机效果
  • 嵌入式系统Linux实时化(四)Xenomai应用开发测试
  • Spring Boot 2 学习指南与资料分享
  • PHP优校管理系统
  • primitive 的 Appearance编写着色器材质
  • IMX6U Qt 开发环境
  • C++实现设计模式---原型模式 (Prototype)
  • C# XPTable 日期字段处理(XPTable控件使用说明十三)
  • 日常工作之 Elasticsearch 常用查询语句汇总
  • 想法分享,利用html通过求输入框中用户输入数组的最大值