2
votes

I've been looking at examples and I'm still not clear on how to actually read data from the usb port in my Android application. I'd like it to be event/intent driven but I'm pretty lost on how to do this. I have a BroadcastReceiver but I'm unsure what Intent.action I need to be looking for to catch data coming in. Any insight is appreciated!

Edit: To clarify my Android device is a Nexus 9 running as a USB Host and I'm looking to communicate with an Arduino Leonardo.

Edit2: At this point I have an Arduino sketch running sending a message over serial every 2 seconds. I have a button that based off of my understanding should read the buffer when pressed but doesn't actually do anything.

    TextView displayMessages = (TextView)findViewById(R.id.textView);

    try
    {
        byte[] msgBytes = new byte[1000];
        connection.bulkTransfer(input, msgBytes, msgBytes.length, TIMEOUT);

        String msgString = new String(msgBytes, "UTF-8");// msgBytes.toString();
        displayMessages.setText(msgString);
    }
    catch (Exception e)
    {
        displayMessages.setText(e.getMessage());
    }

The result is simply that the textView is blank. If I don't do the conversion and drop the byte[].toString() in I get hex values that change each press but I'm not sure how to interpret that.

Edit 3: Just some more information as some time has passed, I have disabled the Arduino Leonardo showing up as an HID keyboard input device as per Arduino being recognized as keyboard by android. I simply modified the USBDesc.h to remove "#define HID_ENABLED". This didn't change the situation. In the meantime I have also implemented the Physicaloid USB library and that proved unsuccessful as well. I am in the process of debugging/converting mik3y's USB-serial-for-android library but have so far been unable to test with it.

1

1 Answers

0
votes

Your android device can be used as a usb host or accessory. So depending on whether you use your phone as a usb host, you use the following intents and permissions in your manifest.

<uses-feature android:name="android.hardware.usb.host" />
<activity ... usb host...>
        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
        </intent-filter>
            <meta-data
            android:resource="@xml/device_filter"
            android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />

With an xml resource file giving the details of your device.

<?xml version="1.0" encoding="utf-8"?>
<resources>
//details of a device I own
<usb-device vendor-id="22b8" product-id="2e76" class="ff" subclass="ff" protocol="00" />
</resources>

Then set up the broadcast receiver and follow the steps in the API.

    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

    public void onReceive(Context context, Intent intent) {

        String action = intent.getAction();
        if (ACTION_USB_PERMISSION.equals(action)) {
            synchronized (this) {
                UsbDevice device =
                        (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if (device != null) {
                        //call method to set up device communication
                    }
                } else {
                }
            }
        }
    }
};

You need to register your receiver.

    mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

    mPermissionIntent =
            PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    registerReceiver(mUsbReceiver, filter);

Then create your function to read and write data.

private Byte[] bytes
private static int TIMEOUT = 0;
private boolean forceClaim = true;

...

UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
UsbDeviceConnection connection = mUsbManager.openDevice(device); 
connection.claimInterface(intf, forceClaim);
connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread

You need to modify this code to take the data where you'd like to. This link (android.serverbox) gives good discussion about handling the transfer thread.

This code has been taken and partially modified from the android.com docs.

Likewise there is a similar process to set up your device as a usb accessory.