0
点赞
收藏
分享

微信扫一扫

usb串口通信


//usb串口通信
implementation 'com.github.mik3y:usb-serial-for-android:3.5.1'

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.xxx.gjg.R;
import com.xxx.gjg.widget.usb.UsbDeviceManage;

public class TmpActivity extends AppCompatActivity {


    public static void open(Context context) {
        Intent starter = new Intent(context, TmpActivity.class);
        context.startActivity(starter);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tmp);
        UsbDeviceManage.getInstance().refresh(this, null);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        if ("android.hardware.usb.action.USB_DEVICE_ATTACHED".equals(intent.getAction())) {
            Log.i("调试信息", "onNewIntent:  USB device detected");
        }
        super.onNewIntent(intent);
    }

    @Override
    protected void onResume() {
        UsbDeviceManage.getInstance().onResume(this);
        super.onResume();
    }

    @Override
    protected void onPause() {
        UsbDeviceManage.getInstance().onPause(this);
        super.onPause();
    }

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

    public void clickTest(View view) {

    }

}

<activity
            android:name=".ui.acy.TmpActivity"
            android:exported="false">
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
        </activity>

device_filter.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 0x0403 / 0x60??: FTDI -->
    <usb-device vendor-id="1027" product-id="24577" /> <!-- 0x6001: FT232R -->
    <usb-device vendor-id="1027" product-id="24592" /> <!-- 0x6010: FT2232H -->
    <usb-device vendor-id="1027" product-id="24593" /> <!-- 0x6011: FT4232H -->
    <usb-device vendor-id="1027" product-id="24596" /> <!-- 0x6014: FT232H -->
    <usb-device vendor-id="1027" product-id="24597" /> <!-- 0x6015: FT230X, FT231X, FT234XD -->

    <!-- 0x10C4 / 0xEA??: Silabs CP210x -->
    <usb-device vendor-id="4292" product-id="60000" /> <!-- 0xea60: CP2102 and other CP210x single port devices -->
    <usb-device vendor-id="4292" product-id="60016" /> <!-- 0xea70: CP2105 -->
    <usb-device vendor-id="4292" product-id="60017" /> <!-- 0xea71: CP2108 -->

    <!-- 0x067B / 0x23?3: Prolific PL2303x -->
    <usb-device vendor-id="1659" product-id="8963" /> <!-- 0x2303: PL2303HX, HXD, TA, ... -->
    <usb-device vendor-id="1659" product-id="9123" /> <!-- 0x23a3: PL2303GC -->
    <usb-device vendor-id="1659" product-id="9139" /> <!-- 0x23b3: PL2303GB -->
    <usb-device vendor-id="1659" product-id="9155" /> <!-- 0x23c3: PL2303GT -->
    <usb-device vendor-id="1659" product-id="9171" /> <!-- 0x23d3: PL2303GL -->
    <usb-device vendor-id="1659" product-id="9187" /> <!-- 0x23e3: PL2303GE -->
    <usb-device vendor-id="1659" product-id="9203" /> <!-- 0x23f3: PL2303GS -->

    <!-- 0x1a86 / 0x?523: Qinheng CH34x -->
    <usb-device vendor-id="6790" product-id="21795" /> <!-- 0x5523: CH341A -->
    <usb-device vendor-id="6790" product-id="29987" /> <!-- 0x7523: CH340 -->

    <!-- CDC driver -->
    <usb-device vendor-id="9025" />                   <!-- 0x2341 / ......: Arduino -->
    <usb-device vendor-id="5824" product-id="1155" /> <!-- 0x16C0 / 0x0483: Teensyduino  -->
    <usb-device vendor-id="1003" product-id="8260" /> <!-- 0x03EB / 0x2044: Atmel Lufa -->
    <usb-device vendor-id="7855" product-id="4"    /> <!-- 0x1eaf / 0x0004: Leaflabs Maple -->
    <usb-device vendor-id="3368" product-id="516"  /> <!-- 0x0d28 / 0x0204: ARM mbed -->
    <usb-device vendor-id="1155" product-id="22336" /><!-- 0x0483 / 0x5740: ST CDC -->
    <usb-device vendor-id="11914" product-id="5"   /> <!-- 0x2E8A / 0x0005: Raspberry Pi Pico Micropython -->
    <usb-device vendor-id="11914" product-id="10"  /> <!-- 0x2E8A / 0x000A: Raspberry Pi Pico SDK -->
    <usb-device vendor-id="6790" product-id="21972" /><!-- 0x1A86 / 0x55D4: Qinheng CH9102F -->
</resources>

UsbDeviceManage

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.SpannableStringBuilder;
import android.util.Log;

import com.blankj.utilcode.util.ToastUtils;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import com.xxx.gjg.BuildConfig;
import com.xxx.gjg.app.AppApplication;
import com.xxx.gjg.utils.CabinetDoorUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * usb设备管理(主要用于读卡器)
 * 注意事项:Activity 设置 singleTop
 * <intent-filter>
 * <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
 * </intent-filter>
 * <meta-data
 * android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
 * android:resource="@xml/device_filter" />
 */
public class UsbDeviceManage implements SerialInputOutputManager.Listener {

    private BroadcastReceiver broadcastReceiver;
    private int deviceId;
    private int portNum;
    private int baudRate;
    private boolean withIoManager;
    private UsbListener mUsbListener;

    @Override
    public void onNewData(byte[] data) {
        mainLooper.post(() -> {
            receive(data);
            if (mUsbListener != null) {
                mUsbListener.onNewData(data);
            }
        });
    }

    @Override
    public void onRunError(Exception e) {
        mainLooper.post(() -> {
            status("connection lost: " + e.getMessage());
            disconnect();
            if (mUsbListener != null) {
                mUsbListener.onRunError(e);
            }
        });
    }

    private enum UsbPermission {Unknown, Requested, Granted, Denied}

    private static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
    private static final int WRITE_WAIT_MILLIS = 2000;
    private static final int READ_WAIT_MILLIS = 2000;
    private UsbPermission usbPermission = UsbPermission.Unknown;
    private UsbSerialPort usbSerialPort;

    private SerialInputOutputManager usbIoManager;
    private boolean connected = false;

    private Handler mainLooper;

    private final ArrayList<ListItem> listItems = new ArrayList<>();

    private static UsbDeviceManage instance;

    private UsbDeviceManage() {

    }

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


    public void refresh(Context context, UsbListener usbListener) {
        listItems.clear();
        mUsbListener = usbListener;
        UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        UsbSerialProber usbDefaultProber = UsbSerialProber.getDefaultProber();
        UsbSerialProber usbCustomProber = CustomProber.getCustomProber();
        for (UsbDevice device : usbManager.getDeviceList().values()) {
            UsbSerialDriver driver = usbDefaultProber.probeDevice(device);
            if (driver == null) {
                driver = usbCustomProber.probeDevice(device);
            }
            if (driver != null) {
                for (int port = 0; port < driver.getPorts().size(); port++)
                    listItems.add(new ListItem(device, port, driver));
            } else {
                listItems.add(new ListItem(device, 0, null));
            }
        }
        Log.i("调试信息", "开始监听=>usb连接设备数量: " + listItems.size());
        if (!listItems.isEmpty()) {
            deviceId = listItems.get(0).device.getDeviceId();
            portNum = listItems.get(0).port;
            baudRate = 19200;
            withIoManager = true;

            // 获取设备的厂商ID和产品ID  listItems.get(0).device
            //int vendorId = device.getVendorId();
            //int productId = device.getProductId();
            //
             获取设备的描述信息
            //String deviceName = device.getDeviceName();
            //String deviceClass = device.getDeviceClass();
            //String deviceSubclass = device.getDeviceSubclass();
            //String deviceProtocol = device.getDeviceProtocol();
        }

        startReceiver();
    }

    private void startReceiver() {
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (INTENT_ACTION_GRANT_USB.equals(intent.getAction())) {
                    usbPermission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
                            ? UsbPermission.Granted : UsbPermission.Denied;
                    connect();
                }
            }
        };
        mainLooper = new Handler(Looper.getMainLooper());
    }

    /*
     * Serial + UI
     */
    private void connect() {
        UsbDevice device = null;
        UsbManager usbManager = (UsbManager) AppApplication.getApplication().getSystemService(Context.USB_SERVICE);
        for (UsbDevice v : usbManager.getDeviceList().values()) {
            if (v.getDeviceId() == deviceId)
                device = v;
        }
        if (device == null) {
            status("connection failed: device not found");
            return;
        }
        UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
        if (driver == null) {
            driver = CustomProber.getCustomProber().probeDevice(device);
        }
        if (driver == null) {
            status("connection failed: no driver for device");
            return;
        }
        if (driver.getPorts().size() < portNum) {
            status("connection failed: not enough ports at device");
            return;
        }
        usbSerialPort = driver.getPorts().get(portNum);
        UsbDeviceConnection usbConnection = usbManager.openDevice(driver.getDevice());
        if (usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.getDevice())) {
            usbPermission = UsbPermission.Requested;
            int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? 1 << 25 : 0;
            PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(AppApplication.getApplication(), 0, new Intent(INTENT_ACTION_GRANT_USB), flags);
            usbManager.requestPermission(driver.getDevice(), usbPermissionIntent);
            return;
        }
        if (usbConnection == null) {
            if (!usbManager.hasPermission(driver.getDevice()))
                status("connection failed: permission denied");
            else
                status("connection failed: open failed");
            return;
        }

        try {
            usbSerialPort.open(usbConnection);
            try {
                usbSerialPort.setParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE);
            } catch (UnsupportedOperationException e) {
                status("unsupport setparameters");
            }
            if (withIoManager) {
                usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
                usbIoManager.start();
            }
            status("connected");
            connected = true;
//            controlLines.start();
        } catch (Exception e) {
            status("connection failed: " + e.getMessage());
            disconnect();
        }
    }

    private void disconnect() {
        connected = false;
//        controlLines.stop();
        if (usbIoManager != null) {
            usbIoManager.setListener(null);
            usbIoManager.stop();
        }
        usbIoManager = null;
        try {
            usbSerialPort.close();
        } catch (IOException ignored) {
        }
        usbSerialPort = null;
    }

    private void send(String str) {
        if (!connected) {
            ToastUtils.showLong("not connected");
            return;
        }
        try {
            byte[] data = (str + '\n').getBytes();
            Log.i("调试信息", "send:  " + HexDump.dumpHexString(data));
//            SpannableStringBuilder spn = new SpannableStringBuilder();
//            spn.append("send " + data.length + " bytes\n");
//            spn.append(HexDump.dumpHexString(data)).append("\n");
//            spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//            receiveText.append(spn);
            usbSerialPort.write(data, WRITE_WAIT_MILLIS);
        } catch (Exception e) {
            onRunError(e);
        }
    }

    private void read() {
        if (!connected) {
            ToastUtils.showLong("not connected");
            return;
        }
        try {
            byte[] buffer = new byte[8192];
            int len = usbSerialPort.read(buffer, READ_WAIT_MILLIS);
            receive(Arrays.copyOf(buffer, len));
        } catch (IOException e) {
            // when using read with timeout, USB bulkTransfer returns -1 on timeout _and_ errors
            // like connection loss, so there is typically no exception thrown here on error
            status("connection lost: " + e.getMessage());
            disconnect();
        }
    }

    private void receive(byte[] data) {
        SpannableStringBuilder spn = new SpannableStringBuilder();
        spn.append("receive " + data.length + " bytes\n");
//        if (data.length > 0)
//            spn.append(HexDump.dumpHexString(data)).append("\n");
        receiveText.append(spn);
//        Log.i("调试信息", "receive1:  " + HexDump.dumpHexString(data));
        Log.i("调试信息", "receive2:  " + CabinetDoorUtils.BinaryToHexString(data));
        Log.i("调试信息", "receive3:  " + hexByteArrayToAscii(data));
        Log.i("调试信息", "receive4:  " + HexUtils.hexByteArrayToAscii(data));
        Log.i("调试信息", "receive5:  " + CabinetDoorUtils.BinaryToHexString(HexUtils.asciiToHexByteArray(HexUtils.hexByteArrayToAscii(data))));
    }

    public static String hexByteArrayToAscii(byte[] bytes) {
        StringBuilder output = new StringBuilder("");

        for (int i = 0; i < bytes.length; i++) {
            output.append((char) bytes[i]);
        }

        return output.toString();
    }


    void status(String str) {
        Log.i("调试信息", "status:  " + str);
        if (mUsbListener != null) {
            mUsbListener.state(str);
        }
    }

    public static class ListItem {
        UsbDevice device;
        int port;
        UsbSerialDriver driver;

        ListItem(UsbDevice device, int port, UsbSerialDriver driver) {
            this.device = device;
            this.port = port;
            this.driver = driver;
        }
    }

    /**
     * 在Activity#onResume父类方法之前调用
     * 示例:
     *
     * @Override protected void onResume(){Test.getInstance().onResume(this);super.onResume();}
     */
    public void onResume(Context context) {
        if (broadcastReceiver == null) {
            return;
        }
        context.registerReceiver(broadcastReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB));

        if (usbPermission == UsbPermission.Unknown || usbPermission == UsbPermission.Granted)
            mainLooper.post(this::connect);
    }

    /**
     * 解除广播
     * 示例:
     *
     * @Override protected void onPause() { Test.getInstance().onPause(this); super.onPause(); }
     */
    public void onPause(Context context) {
        if (connected) {
            status("disconnected");
            disconnect();
        }
        context.unregisterReceiver(broadcastReceiver);
    }

    public interface UsbListener {
        /**
         * 当新的传入数据可用时调用
         */
        void onNewData(byte[] data);

        /**
         * 因错误中止时调用
         */
        void onRunError(Exception e);

        /**
         * 状态
         */
        default void state(String str) {

        }
    }


}

package com.xxx.gjg.widget.usb;

import com.hoho.android.usbserial.driver.FtdiSerialDriver;
import com.hoho.android.usbserial.driver.ProbeTable;
import com.hoho.android.usbserial.driver.UsbSerialProber;

/**
 * add devices here, that are not known to DefaultProber
 *
 * if the App should auto start for these devices, also
 * add IDs to app/src/main/res/xml/device_filter.xml
 */
public class CustomProber {

    static UsbSerialProber getCustomProber() {
        ProbeTable customTable = new ProbeTable();
        customTable.addProduct(0x1234, 0x0001, FtdiSerialDriver.class); // e.g. device with custom VID+PID
        customTable.addProduct(0x1234, 0x0002, FtdiSerialDriver.class); // e.g. device with custom VID+PID
        return new UsbSerialProber(customTable);
    }

}

import java.security.InvalidParameterException;

/**
 * Clone of Android's /core/java/com/android/internal/util/HexDump class, for use in debugging.
 * Changes: space separated hex strings
 */
public class HexDump {
    private final static char[] HEX_DIGITS = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };

    public static String dumpHexString(byte[] array) {
        return dumpHexString(array, 0, array.length);
    }

    public static String dumpHexString(byte[] array, int offset, int length) {
        StringBuilder result = new StringBuilder();

        byte[] line = new byte[8];
        int lineIndex = 0;

        for (int i = offset; i < offset + length; i++) {
            if (lineIndex == line.length) {
                for (int j = 0; j < line.length; j++) {
                    if (line[j] > ' ' && line[j] < '~') {
                        result.append(new String(line, j, 1));
                    } else {
                        result.append(".");
                    }
                }

                result.append("\n");
                lineIndex = 0;
            }

            byte b = array[i];
            result.append(HEX_DIGITS[(b >>> 4) & 0x0F]);
            result.append(HEX_DIGITS[b & 0x0F]);
            result.append(" ");

            line[lineIndex++] = b;
        }

        for (int i = 0; i < (line.length - lineIndex); i++) {
            result.append("   ");
        }
        for (int i = 0; i < lineIndex; i++) {
            if (line[i] > ' ' && line[i] < '~') {
                result.append(new String(line, i, 1));
            } else {
                result.append(".");
            }
        }

        return result.toString();
    }

    public static String toHexString(byte b) {
        return toHexString(toByteArray(b));
    }

    public static String toHexString(byte[] array) {
        return toHexString(array, 0, array.length);
    }

    public static String toHexString(byte[] array, int offset, int length) {
        char[] buf = new char[length > 0 ? length * 3 - 1 : 0];

        int bufIndex = 0;
        for (int i = offset; i < offset + length; i++) {
            if (i > offset)
                buf[bufIndex++] = ' ';
            byte b = array[i];
            buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
            buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
        }

        return new String(buf);
    }

    public static String toHexString(int i) {
        return toHexString(toByteArray(i));
    }

    public static String toHexString(short i) {
        return toHexString(toByteArray(i));
    }

    public static byte[] toByteArray(byte b) {
        byte[] array = new byte[1];
        array[0] = b;
        return array;
    }

    public static byte[] toByteArray(int i) {
        byte[] array = new byte[4];

        array[3] = (byte) (i & 0xFF);
        array[2] = (byte) ((i >> 8) & 0xFF);
        array[1] = (byte) ((i >> 16) & 0xFF);
        array[0] = (byte) ((i >> 24) & 0xFF);

        return array;
    }

    public static byte[] toByteArray(short i) {
        byte[] array = new byte[2];

        array[1] = (byte) (i & 0xFF);
        array[0] = (byte) ((i >> 8) & 0xFF);

        return array;
    }

    private static int toByte(char c) {
        if (c >= '0' && c <= '9')
            return (c - '0');
        if (c >= 'A' && c <= 'F')
            return (c - 'A' + 10);
        if (c >= 'a' && c <= 'f')
            return (c - 'a' + 10);

        throw new InvalidParameterException("Invalid hex char '" + c + "'");
    }

    /** accepts any separator, e.g. space or newline */
    public static byte[] hexStringToByteArray(String hexString) {
        int length = hexString.length();
        byte[] buffer = new byte[(length + 1) / 3];

        for (int i = 0; i < length; i += 3) {
            buffer[i / 3] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1)));
        }

        return buffer;
    }
}

package com.xxx.gjg.widget.usb;

/**
 * 进制转换工具类
 */
public class HexUtils {

    /**
     * 16进制转Ascii
     */
    public static String hexByteArrayToAscii(byte[] bytes) {
        StringBuilder output = new StringBuilder("");

        for (int i = 0; i < bytes.length; i++) {
            output.append((char) bytes[i]);
        }

        return output.toString();
    }

    /**
     * Ascii转16进制
     */
    public static byte[] asciiToHexByteArray(String str) {
        int length = str.length();
        byte[] result = new byte[length];

        for (int i = 0; i < length; i++) {
            result[i] = (byte) str.charAt(i);
        }

        return result;
    }



    /**
     * 16进制表示的字符串转换为字节数组
     *
     * @param hexString 16进制表示的字符串
     * @return byte[] 字节数组
     */
    public static byte[] hexStringToByteArray(String hexString) {
        hexString = hexString.replaceAll(" ", "");
        int len = hexString.length();
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节
            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
                    .digit(hexString.charAt(i + 1), 16));
        }
        return bytes;
    }

    /**
     * 将字节数组转换成十六进制的字符串
     *
     * @return
     */
    public static String BinaryToHexString(byte[] bytes) {
        String hexStr = "0123456789ABCDEF";
        String result = "";
        String hex = "";
        for (byte b : bytes) {
            hex = String.valueOf(hexStr.charAt((b & 0xF0) >> 4));
            hex += String.valueOf(hexStr.charAt(b & 0x0F));
            result += hex + " ";
        }
        return result;
    }


}

package com.xxx.gjg.widget.usb;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.SpannableStringBuilder;
import android.util.Log;

import com.blankj.utilcode.util.ToastUtils;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import com.xxx.gjg.BuildConfig;
import com.xxx.gjg.app.AppApplication;
import com.xxx.gjg.utils.CabinetDoorUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * usb设备管理(主要用于读卡器)
 * 注意事项:Activity 设置 singleTop
 * <intent-filter>
 * <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
 * </intent-filter>
 * <meta-data
 * android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
 * android:resource="@xml/device_filter" />
 */
public class UsbDeviceManage implements SerialInputOutputManager.Listener {

    private BroadcastReceiver broadcastReceiver;
    private int deviceId;
    private int portNum;
    private int baudRate;
    private boolean withIoManager;
    private UsbListener mUsbListener;

    @Override
    public void onNewData(byte[] data) {
        mainLooper.post(() -> {
            receive(data);
            if (mUsbListener != null) {
                mUsbListener.onNewData(data);
            }
        });
    }

    @Override
    public void onRunError(Exception e) {
        mainLooper.post(() -> {
            status("connection lost: " + e.getMessage());
            disconnect();
            if (mUsbListener != null) {
                mUsbListener.onRunError(e);
            }
        });
    }

    private enum UsbPermission {Unknown, Requested, Granted, Denied}

    private static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
    private static final int WRITE_WAIT_MILLIS = 2000;
    private static final int READ_WAIT_MILLIS = 2000;
    private UsbPermission usbPermission = UsbPermission.Unknown;
    private UsbSerialPort usbSerialPort;

    private SerialInputOutputManager usbIoManager;
    private boolean connected = false;

    private Handler mainLooper;

    private final ArrayList<ListItem> listItems = new ArrayList<>();

    private static UsbDeviceManage instance;

    private UsbDeviceManage() {

    }

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


    public void refresh(Context context, UsbListener usbListener) {
        listItems.clear();
        mUsbListener = usbListener;
        UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        UsbSerialProber usbDefaultProber = UsbSerialProber.getDefaultProber();
        UsbSerialProber usbCustomProber = CustomProber.getCustomProber();
        for (UsbDevice device : usbManager.getDeviceList().values()) {
            UsbSerialDriver driver = usbDefaultProber.probeDevice(device);
            if (driver == null) {
                driver = usbCustomProber.probeDevice(device);
            }
            if (driver != null) {
                for (int port = 0; port < driver.getPorts().size(); port++)
                    listItems.add(new ListItem(device, port, driver));
            } else {
                listItems.add(new ListItem(device, 0, null));
            }
        }
        Log.i("调试信息", "开始监听=>usb连接设备数量: " + listItems.size());
        if (!listItems.isEmpty()) {
            deviceId = listItems.get(0).device.getDeviceId();
            portNum = listItems.get(0).port;
            baudRate = 19200;
            withIoManager = true;

            // 获取设备的厂商ID和产品ID  listItems.get(0).device
            //int vendorId = device.getVendorId();
            //int productId = device.getProductId();
            //
             获取设备的描述信息
            //String deviceName = device.getDeviceName();
            //String deviceClass = device.getDeviceClass();
            //String deviceSubclass = device.getDeviceSubclass();
            //String deviceProtocol = device.getDeviceProtocol();
        }

        startReceiver();
    }

    private void startReceiver() {
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (INTENT_ACTION_GRANT_USB.equals(intent.getAction())) {
                    usbPermission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
                            ? UsbPermission.Granted : UsbPermission.Denied;
                    connect();
                }
            }
        };
        mainLooper = new Handler(Looper.getMainLooper());
    }

    /*
     * Serial + UI
     */
    private void connect() {
        UsbDevice device = null;
        UsbManager usbManager = (UsbManager) AppApplication.getApplication().getSystemService(Context.USB_SERVICE);
        for (UsbDevice v : usbManager.getDeviceList().values()) {
            if (v.getDeviceId() == deviceId)
                device = v;
        }
        if (device == null) {
            status("connection failed: device not found");
            return;
        }
        UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
        if (driver == null) {
            driver = CustomProber.getCustomProber().probeDevice(device);
        }
        if (driver == null) {
            status("connection failed: no driver for device");
            return;
        }
        if (driver.getPorts().size() < portNum) {
            status("connection failed: not enough ports at device");
            return;
        }
        usbSerialPort = driver.getPorts().get(portNum);
        UsbDeviceConnection usbConnection = usbManager.openDevice(driver.getDevice());
        if (usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.getDevice())) {
            usbPermission = UsbPermission.Requested;
            int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? 1 << 25 : 0;
            PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(AppApplication.getApplication(), 0, new Intent(INTENT_ACTION_GRANT_USB), flags);
            usbManager.requestPermission(driver.getDevice(), usbPermissionIntent);
            return;
        }
        if (usbConnection == null) {
            if (!usbManager.hasPermission(driver.getDevice()))
                status("connection failed: permission denied");
            else
                status("connection failed: open failed");
            return;
        }

        try {
            usbSerialPort.open(usbConnection);
            try {
                usbSerialPort.setParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE);
            } catch (UnsupportedOperationException e) {
                status("unsupport setparameters");
            }
            if (withIoManager) {
                usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
                usbIoManager.start();
            }
            status("connected");
            connected = true;
//            controlLines.start();
        } catch (Exception e) {
            status("connection failed: " + e.getMessage());
            disconnect();
        }
    }

    private void disconnect() {
        connected = false;
//        controlLines.stop();
        if (usbIoManager != null) {
            usbIoManager.setListener(null);
            usbIoManager.stop();
        }
        usbIoManager = null;
        try {
            usbSerialPort.close();
        } catch (IOException ignored) {
        }
        usbSerialPort = null;
    }

    private void send(String str) {
        if (!connected) {
            ToastUtils.showLong("not connected");
            return;
        }
        try {
            byte[] data = (str + '\n').getBytes();
            Log.i("调试信息", "send:  " + HexDump.dumpHexString(data));
//            SpannableStringBuilder spn = new SpannableStringBuilder();
//            spn.append("send " + data.length + " bytes\n");
//            spn.append(HexDump.dumpHexString(data)).append("\n");
//            spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//            receiveText.append(spn);
            usbSerialPort.write(data, WRITE_WAIT_MILLIS);
        } catch (Exception e) {
            onRunError(e);
        }
    }

    private void read() {
        if (!connected) {
            ToastUtils.showLong("not connected");
            return;
        }
        try {
            byte[] buffer = new byte[8192];
            int len = usbSerialPort.read(buffer, READ_WAIT_MILLIS);
            receive(Arrays.copyOf(buffer, len));
        } catch (IOException e) {
            // when using read with timeout, USB bulkTransfer returns -1 on timeout _and_ errors
            // like connection loss, so there is typically no exception thrown here on error
            status("connection lost: " + e.getMessage());
            disconnect();
        }
    }

    private void receive(byte[] data) {
        SpannableStringBuilder spn = new SpannableStringBuilder();
        spn.append("receive " + data.length + " bytes\n");
//        if (data.length > 0)
//            spn.append(HexDump.dumpHexString(data)).append("\n");
        receiveText.append(spn);
//        Log.i("调试信息", "receive1:  " + HexDump.dumpHexString(data));
        Log.i("调试信息", "receive2:  " + CabinetDoorUtils.BinaryToHexString(data));
        Log.i("调试信息", "receive3:  " + hexByteArrayToAscii(data));
        Log.i("调试信息", "receive4:  " + HexUtils.hexByteArrayToAscii(data));
        Log.i("调试信息", "receive5:  " + CabinetDoorUtils.BinaryToHexString(HexUtils.asciiToHexByteArray(HexUtils.hexByteArrayToAscii(data))));
    }

    public static String hexByteArrayToAscii(byte[] bytes) {
        StringBuilder output = new StringBuilder("");

        for (int i = 0; i < bytes.length; i++) {
            output.append((char) bytes[i]);
        }

        return output.toString();
    }


    void status(String str) {
        Log.i("调试信息", "status:  " + str);
        if (mUsbListener != null) {
            mUsbListener.state(str);
        }
    }

    public static class ListItem {
        UsbDevice device;
        int port;
        UsbSerialDriver driver;

        ListItem(UsbDevice device, int port, UsbSerialDriver driver) {
            this.device = device;
            this.port = port;
            this.driver = driver;
        }
    }

    /**
     * 在Activity#onResume父类方法之前调用
     * 示例:
     *
     * @Override protected void onResume(){Test.getInstance().onResume(this);super.onResume();}
     */
    public void onResume(Context context) {
        if (broadcastReceiver == null) {
            return;
        }
        context.registerReceiver(broadcastReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB));

        if (usbPermission == UsbPermission.Unknown || usbPermission == UsbPermission.Granted)
            mainLooper.post(this::connect);
    }

    /**
     * 解除广播
     * 示例:
     *
     * @Override protected void onPause() { Test.getInstance().onPause(this); super.onPause(); }
     */
    public void onPause(Context context) {
        if (connected) {
            status("disconnected");
            disconnect();
        }
        context.unregisterReceiver(broadcastReceiver);
    }

    public interface UsbListener {
        /**
         * 当新的传入数据可用时调用
         */
        void onNewData(byte[] data);

        /**
         * 因错误中止时调用
         */
        void onRunError(Exception e);

        /**
         * 状态
         */
        default void state(String str) {

        }
    }


}

<!-- usb权限=>刷卡用 -->
    <uses-permission android:name="android.permission.USB_PERMISSION" />
    <uses-feature android:name="android.hardware.usb.host" />

举报

相关推荐

0 条评论