Comaneanu Mugurel
Comaneanu Mugurel

Reputation: 71

USB Serial Driver Java Plugin not working in Unity Android build

I'm trying to make an Android app with the Unity editor in order to read from an USB device. I'm using Unity 2019.4.12f1 and the android device I'm building to is a Xiaomi Mi Box S, running Android 9.

What I've done so far is to use Android Studio to compile some java code in order to gain access to the USB port on Xiaomi.

I'm using this repo: https://github.com/mik3y/usb-serial-for-android as the base functionality of the library I'm trying to build.

This is the code I wrote in my Java library:

public class Plugin extends Activity {
private static UsbSerialPort port;
private static final int READ_WAIT_MILLIS = 2000;

public static String Initialize(Context unityContext) throws IOException {
    UsbManager manager = (UsbManager) unityContext.getSystemService(Context.USB_SERVICE);
    ProbeTable customTable = new ProbeTable();
    customTable.addProduct(0x067b, 0x2303, CdcAcmSerialDriver.class);
    UsbSerialProber prober = new UsbSerialProber(customTable);
    List<UsbSerialDriver> availableDrivers = prober.findAllDrivers(manager);

    if (availableDrivers.isEmpty()) {
        return "Drivers list is empty";
    }

    // Open a connection to the first available driver.
    UsbSerialDriver driver = availableDrivers.get(0);
    UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
    if (connection == null) {
        return "Connection is null";
    }

    port = driver.getPorts().get(0); // Most devices have just one port (port 0)
    port.open(connection);
    port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);


    return "Connection Successful";
}

public static String ReadPort() throws IOException {
    if(port == null || !port.isOpen())
        return "Null";

    byte[] buffer = new byte[8192];
    int len = port.read(buffer, READ_WAIT_MILLIS);

    return buffer.toString();
}

public static void CloseSerialPort() throws IOException {
    if(port != null && port.isOpen())
        port.close();
}

And this is the C# code i'm using on the Unity side:

void Start()
{
    AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
    AndroidJavaObject context = activity.Call<AndroidJavaObject>("getApplicationContext");
    AndroidJavaClass pluginClass = new AndroidJavaClass("com.hoho.android.usbserial.Plugin");
    string response = pluginClass.CallStatic<string>("Initialize", context);

    Debug.Log(response);
    if (response.Contains("Successful"))
    {
        string read = pluginClass.CallStatic<string>("ReadPort");
        Debug.Log(read);
    }
    else
    {
        Debug.Log("Init failed");
    }
}

You can see that I've created a custom "Prober" for my device with the it's Vendor and Product ID's, so in theory the Java side should know what to look for. Unfortunately the collection "availableDrivers" is empty after the code executes.

On the C# side, I'm sending my unity activity for the Java to get it's context from. I see that the USB manager needs that context in order to be instanced. I did check and the variable "unityContext" is not null after is passed into the Java library from C#. Right now I'm investigating if maybe the context I'm sending to Java is not the right one, causing the USB manager not being able to access the USB devices.

The return String that I get from the Java code to Unity is: "Drivers list is empty", hence the conclusion that the USB drivers list is empty.

Any help or any kind of leading in the right direction is going to be helpful.

PS. Things I've checked:

  1. I know that the USB device is able to communicate with the Android device because I've used an app to check and everything seemed fine. (https://play.google.com/store/apps/details?id=de.kai_morich.serial_usb_terminal&hl=en)

Upvotes: 2

Views: 959

Answers (1)

Comaneanu Mugurel
Comaneanu Mugurel

Reputation: 71

I'm answering my own question here. Maybe someone else will stumble upon this. There were a couple of issues that I was not aware of:

  1. The Xiaomi USB port will not continue to communicate with the sensor if it is set to USB Debugging Mode;
  2. Again, even if the Xiaomi USB Debugging mode was turned off, it will not work. To make it work I had to restart the device.

The conclusion being that if you are working with Xiaomi Mi Box S make sure the hardware connection is working before you start changing anything on your code.

To make all of this work:

  1. Make sure you understand how Java <-> C# communication works;
  2. You will need to be a little bit familiar with Android Studio library builds;
  3. Follow the instructions on the repo I posted.

You should be good to go at this point. Let me know if you need any further help.

Upvotes: 3

Related Questions