Android USB

1,809 阅读4分钟

Usb开发

一、清单文件的配置

【1】 usb开发需要sdk是12以上,低于12的sdk,没有usb的api

【2】 因为并不是所有android驱动的设备都保证支持USB主机api,所以要包含一个元素,该元素声明您的应用程序使用android.hardware.usb。

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

【3】 如果希望应用程序收到附加USB设备的通知,请为android.hardware.us .action指定一个和元素对。USB_DEVICE_ATTACHED意图在您的主活动中。元素指向一个外部XML资源文件,该文件声明关于要检测的设备的标识信息

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

【4】 在res下新建xml文件夹,新建文件device_filter.xml。 在XML资源文件中,为要筛选的USB设备声明< USB -device>元素。下面的列表描述了的属性。一般来说,如果您想对特定的设备进行筛选,请使用vendor和product ID;如果您想对一组USB设备(如大规模存储设备或数码相机)进行筛选,请使用class、subclass和protocol。您可以指定一个或所有这些属性。没有指定与每个USB设备匹配的属性,所以只有在应用程序需要时才这样做:

vendor-id
product-id
class
subclass
protocol (device or interface)

<?xml version="1.0" encoding="utf-8"?>
<resources>
	<usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>		

二、java文件中

【1】 首先获取当前设备连接的usb设备

UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
for (Map.Entry<String, UsbDevice> entry : deviceList.entrySet()) {
    System.out.println(entry.getKey() + "----" + entry.getValue());
}

【2】 定义一个广播来接收usb权限,是否连接等事件

public class UsbReceiver extends BroadcastReceiver {

public static final String ACTION_USB_PERMISSION =
        "com.android.example.USB_PERMISSION";

@Override
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) {
                    System.out.println("设备已连接:" + device.getDeviceName());
                    //call method to set up device communication
                }
            } else {
                Log.d("UsbReceiver", "permission denied for device " + device);
            }
        }
    }
}
}	

【3】 动态注册广播

mUsbReceiver = new UsbReceiver();
IntentFilter intentFilter = new IntentFilter(UsbReceiver.ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, intentFilter);

【4】 申请usb权限

PendingIntent broadcast = PendingIntent.getBroadcast(this, 0, new Intent(UsbReceiver.ACTION_USB_PERMISSION), 0);
UsbDevice usbDevice = deviceList.get("/dev/bus/usb/001/003");
usbManager.requestPermission(usbDevice, broadcast);

三、usb通信

【1】 与USB设备的通信可以是同步的,也可以是异步的。在这两种情况下,都应该创建一个新线程来执行所有数据传输,这样就不会阻塞UI线程。要正确地设置与设备的通信,您需要获得希望在其上通信的设备的适当UsbInterface和UsbEndpoint,并使用UsbDeviceConnection在该端点上发送请求。检查UsbDevice对象的属性,如产品ID、供应商ID或设备类,以确定是否希望与设备通信。 当确定要与设备通信时,请找到要用于与该接口的适当UsbEndpoint通信的适当UsbInterface。接口可以有一个或多个端点,通常会有一个用于双向通信的输入和输出端点。 找到正确的端点后,在该端点上打开UsbDeviceConnection。 使用bulkTransfer()或controlTransfer()方法提供希望在端点上传输的数据。您应该在另一个线程中执行此步骤,以防止阻塞主UI线程

【2】 usb的api解释

UsbDevice:表示已连接的USB设备,并包含访问其标识信息、接口和端点的方法。

UsbInterface:表示USB设备的接口,该接口为设备定义一组功能。一个设备可以有一个或多个接口进行通信

UsbEndpoint:表示接口端点,它是此接口的通信通道。接口可以有一个或多个端点,并且通常具有用于与设备进行双向通信的输入和输出端点。

UsbDeviceConnection:表示到设备的连接,该设备在端点上传输数据。这个类允许您同步或异步地来回发送数据。

/dev/bus/usb/001/003----UsbDevice[mName=/dev/bus/usb/001/003,mVendorId=7427,mProductId=35,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=iCON,mProductName=ICON Neuron 3 G2 Ver1.00,mSerialNumber=2009-10-30,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=128,mMaxPower=15,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=1,mSubclass=1,mProtocol=0,mEndpoints=[]
UsbInterface[mId=1,mAlternateSetting=0,mName=null,mClass=1,mSubclass=3,mProtocol=0,mEndpoints=[
UsbEndpoint[mAddress=130,mAttributes=2,mMaxPacketSize=4,mInterval=0]
UsbEndpoint[mAddress=2,mAttributes=2,mMaxPacketSize=4,mInterval=0]]]]

【3】 发送数据

UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
// 获取usb接口,可以有多组,用户通信
int interfaceCount = device.getInterfaceCount();
// 遍历usb接口,查询哪组可以通讯
for (int i = 0; i < interfaceCount; i++) {
    UsbInterface usbInterface = device.getInterface(i);
    // 获取通信端点,可以有多个
    int endpointCount = usbInterface.getEndpointCount();
    if (endpointCount > 0) {
        for (int j = 0; j < endpointCount; j++) {
            final UsbEndpoint endpoint = usbInterface.getEndpoint(j);
            System.out.println("endpoint:" + endpoint);

            if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
                System.out.println("in endpoint:" + endpoint);
                final UsbDeviceConnection usbDeviceConnection = manager.openDevice(device);
                usbDeviceConnection.claimInterface(usbInterface, true);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        byte[] buf = new byte[4];
                        int dataLength=usbDeviceConnection.bulkTransfer(endpoint, buf, buf.length, 2000);
						// dataLength>0表示成功 数据都存在buf中
                    }
                }).start();
            }
        }
        break;
    }
}