USB support for Android is ready!

USB support for Android is ready!

A few weeks months ago, we announced the Java API. It is at last available, even better we have two versions of the Java API. A standard Java version and a version for Android. You can download them from the usual location. As we have already written about the standard Java library, we are going to talk about the specificities of the Andoid library.


In the opposite to other Java platforms (which do not offer USB access), with Android it is possible to access USB peripherals natively from a Java class. Indeed, from Android 3.1 Google provides an API to send and receive USB packets. In theory, this enables any recent Android machine to interact with our USB modules without having to root or tinker with the tablet.

Nevertheless, it is necessary for the tablet or phone to support the Host USB mode and for the builder's firmware to correctly implement this functionality. If you don't know what the Host mode is, here is a short explanation:

In a USB connection, there is always a Host (a computer, for example) and a Device (a keyboard, for example). The Host is responsible for supplying power to the peripherals (it's your computer which supplies your keyboard and not the opposite), it is also responsible for communications to work well. In the case of a computer and a keyboard, everything seems obvious and clear, but with an Android tablet, it's somewhat more complex because the tablet can be Host and/or Device. Let's take for example an Acer Iconia Tab A200 tablet, we have:

- 1 micro USB port for when the tablet works as a Device (to connect the tablet to a computer)

- 1 USB type A port (which is the port on all the computers) which works as a Host (to connect a keyboard to the tablet).

The two USB ports of the Iconia Tab A200
The two USB ports of the Iconia Tab A200



To come back to our usage example, we therefore need a tablet which works as a Host on which we will connect our USB modules.
We have successfully used the following two tablets:
- Acer Iconia Tab A200
- Asus Tranformer Pad TF300T (with the latest firmware)

The following machines should work correctly, but we haven't tested them in our lab:
- Galaxy Nexus
- Lenovo ThinkPad Tablet
- Asus Transformer TF101
- Motorola Xoom
- Toshiba Thrive AT100
- Samsung Galaxy Tab 7.0 Plus (Wifi)

Some time ago, very cheap small Android "boxes", which connect directly to a television, appeared on the market (for example the MK802 and the MK805).
Our experience shows that these systems don't correctly implement this functionality under Android. Concretely, keyboards and USB keys are supported, but the other peripherals are ignored by the firmware.

For security reasons, Android always warns you before authorizing an application to access USB peripherals.

Android asks you confirmation the first time you connect a USB peripheral
Android asks you confirmation the first time you connect a USB peripheral



First example

Now that we have a tablet which supports the Host mode, a Java library designed for Android, let's have a look at how to interact with a Yocto-Meteo. We are going to create a very basic app which displays the three values of the three sensors of the connected Yocto-Meteo or a "Not connected" message if the module is not connected.

The Yoctopuce API functions as on all other platforms. There are, however, two additional steps to be performed in the Android version.

The first once consists in adding in our AndroidManifest.xml file the fact that we are using the Host USB function:

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



The second is to activate the Host mode in our API. To access the USB port, we must provide a pointer to an object or to a subobject android.content.Context by using the method YAPI.EnableUSBHost. As the android.app.Activity class inherits from android.content.Context, the easiest way is to simply call YAPI.EnableUSBHost(this) when the application starts.



    public void onCreate(Bundle savedInstanceState) {
        ...
        try {
                // Pass the application Context to the Yoctopuce Library
                        YAPI.EnableUSBHost(this);
                // Register all usb device
                YAPI.RegisterHub("usb");       
        } catch (YAPI_Exception e) {
                //report the error
                ...
        }
        ...
}



When these two steps have been taken care of, there is no need to worry about the communication part. The Yoctopuce library takes care itself to request access to the USB port and to maintain communication. We only need to retrieve the values when it suits us.

In our app, we want to update twice per second the three text fields with the value of the corresponding sensor. The only difficulty is to make sure that the code is run by the main thread because we are going to modify the text fields.

The simplest way is to add a Handler in the event loop which
-1 updates the list of connected modules
- 2 displays the temperature
- 3 displays the humidity
- 4 displays the pressure
- 5 saves the handler in the event loop again.

Here is the code of the handler:


...
public void run()
{
    try {
        YAPI.UpdateDeviceList();
    } catch (YAPI_Exception e1) {
        temp_msg.setText("update device list failed with "+e1.getLocalizedMessage());
        return;
    }

    YTemperature temp_sensor=YTemperature.FirstTemperature();
    if(temp_sensor!=null && temp_sensor.isOnline()) {
            try {
                temp_msg.setText(
                    String.format("%.1f %s",temp_sensor.getCurrentValue(),temp_sensor.getUnit()));
            } catch (YAPI_Exception e) {
                temp_msg.setText(String.format("%s",e.getLocalizedMessage()));
            }
    }else {
        temp_msg.setText("No temperature sensor connected");
    }


    YPressure pres_sensor = YPressure.FirstPressure();
    if(pres_sensor!=null && pres_sensor.isOnline()) {
        try {
            pres_msg.setText(
                String.format("%.0f %s",pres_sensor.getCurrentValue(),pres_sensor.getUnit()));
        } catch (YAPI_Exception e) {
            pres_msg.setText(String.format("%s",e.getLocalizedMessage()));
        }
    } else{
        pres_msg.setText("No pressure sensor connected");
    }

    YHumidity hum_sensor = YHumidity.FirstHumidity();
    if(hum_sensor!=null && hum_sensor.isOnline()) {
        try {
            hum_msg.setText(
                String.format("%.0f %s",hum_sensor.getCurrentValue(),hum_sensor.getUnit()));
        } catch (YAPI_Exception e) {
            hum_msg.setText(String.format("%s",e.getLocalizedMessage()));
        }

    }else {
        hum_msg.setText("No humidity sensor connected");
    }


    handler.postDelayed(this, 500);
}
...




And here is the result
And here is the result



The source files for this example are available in the Java Android library. You can also download directly the application here if you want to test if your tablet is compatible. There is currently very few Android examples provided with the library, but obviously we are going to add examples for each module. We are also going to provide a few examples directly on Google Play.

Add a comment No comment yet Back to blog












Yoctopuce, get your stuff connected.