如何与多个USB串行设备和Android

时间:2016-05-26 10:58:19

标签: android broadcastreceiver usbserial

我正在努力使Android代码工作,可以与多个USB串行设备和Android平板电脑进行通信。为此,我使用FELHR85 https://github.com/felHR85/UsbSerial的USB串行库。

我能够一次与单个USB设备通信。但是,现在当我尝试连接并与多个USB串行设备通信时,App失败了。我使用下面的代码来测试多个设备。

public class UsbService extends Service {

public static final String ACTION_USB_READY = "com.felhr.connectivityservices.USB_READY";
public static final String ACTION_USB_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
public static final String ACTION_USB_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";
public static final String ACTION_USB_NOT_SUPPORTED = "com.felhr.usbservice.USB_NOT_SUPPORTED";
public static final String ACTION_NO_USB = "com.felhr.usbservice.NO_USB";
public static final String ACTION_USB_PERMISSION_GRANTED = "com.felhr.usbservice.USB_PERMISSION_GRANTED";
public static final String ACTION_USB_PERMISSION_NOT_GRANTED = "com.felhr.usbservice.USB_PERMISSION_NOT_GRANTED";
public static final String ACTION_USB_DISCONNECTED = "com.felhr.usbservice.USB_DISCONNECTED";
public static final String ACTION_CDC_DRIVER_NOT_WORKING = "com.felhr.connectivityservices.ACTION_CDC_DRIVER_NOT_WORKING";
public static final String ACTION_USB_DEVICE_NOT_WORKING = "com.felhr.connectivityservices.ACTION_USB_DEVICE_NOT_WORKING";
public static final int MESSAGE_FROM_SERIAL_PORT = 0;
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private static int BAUD_RATE = 4800; // BaudRate. Change this value if you need
public static boolean SERVICE_CONNECTED = false;

private IBinder binder = new UsbBinder();

private Context context;
private Handler mHandler;
private UsbManager usbManager;
private UsbDevice device;
private UsbDeviceConnection connection;
private UsbSerialDevice serialPort;

private boolean serialPortConnected;
UsbInterface intf;
SessionManager sessionManager;

/*
 *  Data received from serial port will be received here. Just populate onReceivedData with your code
 *  In this particular example. byte stream is converted to String and send to UI thread to
 *  be treated there.
 */
private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
    @Override
    public void onReceivedData(byte[] arg0) {
        try {
            String data = new String(arg0, "UTF-8");
            data.concat("\0");
            if (mHandler != null)
                mHandler.obtainMessage(MESSAGE_FROM_SERIAL_PORT, data).sendToTarget();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
};
/*
 * Different notifications from OS will be received here (USB attached, detached, permission responses...)
 * About BroadcastReceiver: http://developer.android.com/reference/android/content/BroadcastReceiver.html
 */
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override
    public void onReceive(Context arg0, Intent arg1) {

        if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
            boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
            if (granted) // User accepted our USB connection. Try to open the device as a serial port
            {
                Intent intent = new Intent(ACTION_USB_PERMISSION_GRANTED);
                arg0.sendBroadcast(intent);
                connection = usbManager.openDevice(device);
                serialPortConnected = true;
                new ConnectionThread().run();
            } else // User not accepted our USB connection. Send an Intent to the Main Activity
            {
                Intent intent = new Intent(ACTION_USB_PERMISSION_NOT_GRANTED);
                arg0.sendBroadcast(intent);
            }
        } else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
            if (!serialPortConnected)
                findSerialPortDevice(); // A USB device has been attached. Try to open it as a Serial port
        } else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
            // Usb device was disconnected. send an intent to the Main Activity
            if(intf != null && intf.getInterfaceClass() == UsbConstants.USB_CLASS_HID){
                Intent intent = new Intent(ACTION_USB_DISCONNECTED);
                arg0.sendBroadcast(intent);
                serialPortConnected = false;
                if(serialPort != null)
                    serialPort.close();
            }
        }
    }
};

/*
 * onCreate will be executed when service is started. It configures an IntentFilter to listen for
 * incoming Intents (USB ATTACHED, USB DETACHED...) and it tries to open a serial port.
 */
@Override
public void onCreate() {
    this.context = this;
    serialPortConnected = false;
    UsbService.SERVICE_CONNECTED = true;
    setFilter();
    sessionManager = new SessionManager(context);
    usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    findSerialPortDevice();
}

/* MUST READ about services
 * http://developer.android.com/guide/components/services.html
 * http://developer.android.com/guide/components/bound-services.html
 */
@Override
public IBinder onBind(Intent intent) {
    return binder;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return Service.START_NOT_STICKY;
}

@Override
public void onDestroy() {
    super.onDestroy();
    UsbService.SERVICE_CONNECTED = false;
}

/*
 * This function will be called from MainActivity to write data through Serial Port
 */
public void write(byte[] data) {
    if (serialPort != null)
    {
        //Log.e("Serialport Found","Serialport Found");
        serialPort.write(data);
    }
    //Log.e("Serialport Not Found","Serialport Not Found");
}

public void setHandler(Handler mHandler) {
    this.mHandler = mHandler;
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) private void findSerialPortDevice() {
    // This snippet will try to open the first encountered usb device connected, excluding usb root hubs
    HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
    System.out.println("<====================== Counter Settings =========================>");
    System.out.println("Counter Baudrate =============>"+sessionManager.getCOUNTER_BAUDRATE());
    System.out.println("Counter DataBits =============>"+sessionManager.getCOUNTER_DATA_BITS());
    System.out.println("Counter StopBits =============>"+sessionManager.getCOUNTER_STOP_BITS());
    System.out.println("Counter Parity =============>"+sessionManager.getCOUNTER_PARITY());
    System.out.println("Counter Flow Control =============>"+sessionManager.getCOUNTER_FLOW_CONTROL());

    System.out.println("<====================== Scale Settings =========================>");
    System.out.println("Scale Baudrate =============>"+sessionManager.getSCALE_BAUDRATE());
    System.out.println("Scale DataBits =============>"+sessionManager.getSCALE_DATA_BITS());
    System.out.println("Scale StopBits =============>"+sessionManager.getSCALE_STOP_BITS());
    System.out.println("Scale Parity =============>"+sessionManager.getSCALE_PARITY());
    System.out.println("Scale Flow Control =============>"+sessionManager.getSCALE_FLOW_CONTROL());

    if (!usbDevices.isEmpty()) {
        boolean keep = true;
        for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
            device = entry.getValue();
            int deviceVID = device.getVendorId();
            int devicePID = device.getProductId();
            intf = device.getInterface(0);
            if(device != null && !device.equals(""))
                Utils.writeIntoFile(getBaseContext(),"device =============>"+device+"\n"+"getInterface Count =============>"+device.getInterfaceCount());

            if (intf.getInterfaceClass() != UsbConstants.USB_CLASS_HID) {
                if (deviceVID != 0x1d6b && (devicePID != 0x0001 || devicePID != 0x0002 || devicePID != 0x0003)) {
                    if(device.getDeviceName().equalsIgnoreCase("/dev/bus/usb/001/004")){
                        BAUD_RATE = Integer.valueOf(sessionManager.getCOUNTER_BAUDRATE());
                        System.out.println("getCOUNTER_BAUDRATE=============>"+BAUD_RATE);
                    }else if(device.getDeviceName().equalsIgnoreCase("/dev/bus/usb/001/003")){
                        BAUD_RATE = Integer.valueOf(sessionManager.getSCALE_BAUDRATE());
                        System.out.println("getSCALE_BAUDRATE=============>"+BAUD_RATE);
                    }
                    // There is a device connected to our Android device. Try to open it as a Serial Port.
                    requestUserPermission();
                    keep = false;
                } else {
                    connection = null;
                    device = null;
                }
            }

            if (!keep)
                break;
        }
        if (!keep) {
            // There is no USB devices connected (but usb host were listed). Send an intent to MainActivity.
            Intent intent = new Intent(ACTION_NO_USB);
            sendBroadcast(intent);
        }
    } else {
        // There is no USB devices connected. Send an intent to MainActivity
        Intent intent = new Intent(ACTION_NO_USB);
        sendBroadcast(intent);
    }
}

private void setFilter() {
    IntentFilter filter = new IntentFilter();
    filter.addAction(ACTION_USB_PERMISSION);
    filter.addAction(ACTION_USB_DETACHED);
    filter.addAction(ACTION_USB_ATTACHED);
    registerReceiver(usbReceiver, filter);
}

/*
 * Request user permission. The response will be received in the BroadcastReceiver
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) private void requestUserPermission() {
    PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    usbManager.requestPermission(device, mPendingIntent);
}

public class UsbBinder extends Binder {
    public UsbService getService() {
        return UsbService.this;
    }
}

/*
 * A simple thread to open a serial port.
 * Although it should be a fast operation. moving usb operations away from UI thread is a good thing.
 */
private class ConnectionThread extends Thread {
    @Override
    public void run() {
        serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
        if (serialPort != null) {
            if (serialPort.open()) {
                serialPort.setBaudRate(BAUD_RATE);
                serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
                serialPort.read(mCallback);

                // Everything went as expected. Send an intent to MainActivity
                Intent intent = new Intent(ACTION_USB_READY);
                context.sendBroadcast(intent);
            } else {
                // Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
                // Send an Intent to Main Activity
                if (serialPort instanceof CDCSerialDevice) {
                    Intent intent = new Intent(ACTION_CDC_DRIVER_NOT_WORKING);
                    context.sendBroadcast(intent);
                } else {
                    Intent intent = new Intent(ACTION_USB_DEVICE_NOT_WORKING);
                    context.sendBroadcast(intent);
                }
            }
        } else {
            // No driver for given device, even generic CDC driver could not be loaded
            Intent intent = new Intent(ACTION_USB_NOT_SUPPORTED);
            context.sendBroadcast(intent);
        }
    }
}

}

有人知道如何实现这一目标。我也愿意使用另一个可以帮助我一次连接多个USB串行设备的库。

0 个答案:

没有答案