Open In App

Understanding USB Communication in Android Apps

Last Updated : 24 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we are going to see how to interact with USB in Android apps. What things are Required and Also 1 mini Project to Get a Clear Idea of How Things Work When We Need to Interact Android Apps With USB.

USB Endpoints and Interfaces

Endpoints:

Endpoints are the channels through which data is transferred between the USB device and the host (in this case our Android device is the host). They come in two types:

  1. In Endpoints: These are used by USB devices to send data to the host. For example, a camera might use an In Endpoint to send image data to a computer.
  2. Out Endpoints: These are used by USB devices to receive data from the host. For example, a printer might use an Out Endpoint to receive print jobs from a computer.

Interfaces:

The interface represents a set of endpoints that perform a specific function. A USB device can have multiple interfaces and each interface is identified by a unique number. For example, a printer might have one interface for printing and another for status information.

Required Components for USB Interaction and Implementing USB Communication in Android Apps

1. USB Host Mode Support:

For Android device to communicate with USB peripherals it must support USB Host Mode.Mostly modern Android devices have this capability.

2. USB Host API:

Android provides a set of APIs for interacting with USB devices. Primary classes for USB communication are UsbManager, UsbDevice, UsbDeviceConnection. These classes allow us to manage the USB devices connected to the host.

  • UsbManager: This is the entry point for interacting with USB devices. It allows us to obtain a list of connected devices, request permission to communicate with a device, manage device connections.
  • UsbDevice: Represents a connected USB device. It provides information about the device like its vendor and product IDs, interfaces,endpoints.
  • UsbDeviceConnection: This class facilitates communication with a connected USB device. It allows us to send and receive data through the device’s endpoints.

3. USB Permissions:

Accessing USB devices is a sensitive operation we need to declare the necessary permissions in AndroidManifest.xml file. To ensure that only authorized apps can interact with connected USB devices.

XML




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


4. USB Device Enumeration:

When a USB device is connected Android performs device enumeration to identify its capabilities and characteristics. We can use the UsbManager to obtain list of connected devices and iterate through them to find the one that matches our app requirements.

Java




UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> connectedDevices = usbManager.getDeviceList();
  
for (UsbDevice device : connectedDevices.values()) {
    // You can check permissions and more here
}


Kotlin




val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
val connectedDevices: HashMap<String, UsbDevice> = usbManager.deviceList
  
for (device in connectedDevices.values) {
  
}


5. Requesting Permission:

Before communicating with a USB device we need to request permission from the user using pending intent. It is a crucial security measure to ensure that only authorized apps can access the device and it is required.

Java




PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, permissionIntent);


Kotlin




val permissionIntent = PendingIntent.getBroadcast(this, 0, Intent(ACTION_USB_PERMISSION), 0)
usbManager.requestPermission(device, permissionIntent)


6. Managing Endpoints and Interfaces:

Once we have obtained permission to communicate with a device we can access its endpoints and interfaces. Using the UsbDevice and UsbDeviceConnection classes to send and receive data through the appropriate endpoints.

Example Project : Creating an App To Enumerate All the USB Devices List

In this project we are going to create an app to Get all the usb devices list that are connected to our android device with OTG.

What we are going to do:

Step By Step Implementation:

Step 1: Create a new Project and Select Kotlin/java As the programming language

Step 2: We have created a simple UI by adding one Button at Bottom

Step 3: Add Permissions To Interact With Usb that we have seen Earlier

XML




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


Step 4: Working on Kotlin File and When the button is clicked it retrieves a list of connected USB devices and displays them in bottom sheet dialog that i have created showing information like device name, vendor ID, manufacturer name, product name,you can add more things. Each device item is clickable and clicking on it displays a toast message indicating the selected device with device name and Vendor Id.

Java




package com.ayush.gfgapp;
  
import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
  
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
  
import com.google.android.material.bottomsheet.BottomSheetDialog;
  
import java.util.HashMap;
  
public class MainActivity2 extends AppCompatActivity {
  
    private Button getDevice;
    private UsbManager usbManager;
  
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
  
        // Initialize button and USB manager
        getDevice = findViewById(R.id.getDevice);
        usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
  
        // Set OnClickListener for the button
        getDevice.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Retrieve the list of connected USB devices
                HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
                showDevicesDialog(deviceList);
            }
        });
    }
  
    private void showDevicesDialog(HashMap<String, UsbDevice> deviceList) {
        if (deviceList.isEmpty()) {
            // Show a toast if no USB devices are found
            Toast.makeText(this, "No USB devices found", Toast.LENGTH_SHORT).show();
        } else {
            // Inflate the bottom sheet layout to display the list of devices
            View bottomSheetView = LayoutInflater.from(this).inflate(R.layout.bottom_sheet_device_list, null);
            LinearLayout devicesLayout = bottomSheetView.findViewById(R.id.devicesLayout);
  
            for (UsbDevice device : deviceList.values()) {
                // Inflate the layout for each device item
                View deviceItemLayout = LayoutInflater.from(this).inflate(R.layout.device_list_item, null);
                TextView deviceNameTextView = deviceItemLayout.findViewById(R.id.deviceNameTextView);
                TextView vendorIdTextView = deviceItemLayout.findViewById(R.id.vendorIdTextView);
                TextView manufacturerTextView = deviceItemLayout.findViewById(R.id.manufacturerTextView);
                TextView productNameTextView = deviceItemLayout.findViewById(R.id.ProductNameTextView);
                TextView emptyTV = deviceItemLayout.findViewById(R.id.emptyTV);
  
                // Set information about the device in the corresponding TextViews
                deviceNameTextView.setText("Device Name: " + device.getDeviceName());
                vendorIdTextView.setText("Vendor ID: " + device.getVendorId());
                manufacturerTextView.setText("Manufacturer Name: " + device.getManufacturerName());
                productNameTextView.setText("Product Name: " + device.getProductName());
                emptyTV.setText("Testing:- " + device.getProductId());
  
                // Add an OnClickListener to handle device selection
                deviceItemLayout.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity2.this, "Device Selected: " + device.getDeviceName() + " (Vendor ID: " + device.getVendorId() + ")", Toast.LENGTH_SHORT).show();
                    }
                });
  
                  // Add the device item to the layout
                devicesLayout.addView(deviceItemLayout); 
            }
  
            // Create and display the bottom sheet dialog with the list of devices
            BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(this);
            bottomSheetDialog.setContentView(bottomSheetView);
            bottomSheetDialog.show();
        }
    }
}


Kotlin




package com.ayush.gfgapp
  
import android.content.Context
import android.content.Intent
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.bottomsheet.BottomSheetDialog
  
class MainActivity2 : AppCompatActivity() {
  
    private lateinit var getDevice: Button
    private lateinit var usbManager: UsbManager
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
  
        getDevice = findViewById(R.id.getDevice)
          
        // Initialize the USB manager to access USB functionality
        usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
  
  
        getDevice.setOnClickListener {
            // Retrieve the list of connected USB devices
            val deviceList = usbManager.deviceList
            
              // Call function to show the list of devices
            showDevicesDialog(deviceList) 
        }
    }
  
    private fun showDevicesDialog(deviceList: HashMap<String, UsbDevice>) {
        if (deviceList.isEmpty()) {
            // Show a toast if no USB devices are found
            Toast.makeText(this, "No USB devices found", Toast.LENGTH_SHORT).show()
        } else {
            // Inflate the bottom sheet layout to display the list of devices
            val bottomSheetView = LayoutInflater.from(this).inflate(R.layout.bottom_sheet_device_list, null)
            val devicesLayout = bottomSheetView.findViewById<LinearLayout>(R.id.devicesLayout)
  
            for (device in deviceList.values) {
                // Inflate the layout for each device item
                val deviceItemLayout = LayoutInflater.from(this).inflate(R.layout.device_list_item, null) as LinearLayout
                val deviceNameTextView = deviceItemLayout.findViewById<TextView>(R.id.deviceNameTextView)
                val vendorIdTextView = deviceItemLayout.findViewById<TextView>(R.id.vendorIdTextView)
                val manufacturerTextView = deviceItemLayout.findViewById<TextView>(R.id.manufacturerTextView)
                val productNameTextView = deviceItemLayout.findViewById<TextView>(R.id.ProductNameTextView)
                val emptyTV = deviceItemLayout.findViewById<TextView>(R.id.emptyTV)
  
                // Set information about the device in the corresponding TextViews
                deviceNameTextView.text = "Device Name: ${device.deviceName}"
                vendorIdTextView.text = "Vendor ID: ${device.vendorId}"
                manufacturerTextView.text = "Manufacturer Name: ${device.manufacturerName}"
                productNameTextView.text = "Product Name: ${device.productName}"
                emptyTV.text = "Testing:- ${device.productId}"
  
                // Add an onClickListener to handle device selection
                deviceItemLayout.setOnClickListener {
                    Toast.makeText(this, "Device Selected: ${device.deviceName} (Vendor ID: ${device.vendorId})", Toast.LENGTH_SHORT).show()
                }
                  
                // Add the device item to the layout
                devicesLayout.addView(deviceItemLayout) 
            }
  
            val bottomSheetDialog = BottomSheetDialog(this)
            bottomSheetDialog.setContentView(bottomSheetView)
            // Display the bottom sheet 
              // dialog with the list of devices
            bottomSheetDialog.show() 
        }
    }
}


Layout For Bottom Sheets:

bottom_sheet_device_list.xml:

XML




<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/cardview_shadow_start_color"
    android:orientation="vertical">
  
    <LinearLayout
        android:id="@+id/devicesLayout"
        android:layout_width="match_parent"
        android:background="@color/cardview_shadow_start_color"
        android:layout_height="wrap_content"
        android:orientation="vertical" />
  
</LinearLayout>


device_list_item.xml:

XML




<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@color/cardview_shadow_start_color"
    android:padding="16dp">
  
    <TextView
        android:id="@+id/deviceNameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#E11919"
        android:textAppearance="?android:textAppearanceMedium" />
  
    <TextView
        android:id="@+id/vendorIdTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#0EEF12"
        android:layout_marginTop="4dp"
        android:textAppearance="?android:textAppearanceSmall" />
  
    <TextView
        android:id="@+id/manufacturerTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#0EEF12"
        android:layout_marginTop="4dp"
        android:textAppearance="?android:textAppearanceSmall" />
  
    <TextView
        android:id="@+id/ProductNameTextView"
        android:layout_width="wrap_content"
        android:textColor="#0EEF12"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:textAppearance="?android:textAppearanceSmall" />
  
    <TextView
        android:id="@+id/emptyTV"
        android:layout_width="wrap_content"
        android:textColor="#3F51B5"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:textAppearance="?android:textAppearanceSmall" />
  
</LinearLayout>


Output:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads