Utilice el archivo de recursos device_filter.xml para filtrar resultados de enumeración USB
Siguiendo las instrucciones de la documentación de Android USB Host , logré detectar nuevos dispositivos USB a través de una intención USB_DEVICE_ATTACHED
. Para restringir las notificaciones a ciertos dispositivos, se puede especificar un archivo de recursos:
<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>
Device_filter.xml:
- Enviar datos desde android a PC vía USB
- Habilitar depuración USB en Android
- Escribir datos en USB HID usando Javascript, HTML5 o cualquier lenguaje de plataforma cruzada (compatible con Android)
- USB Accessory API en el Samsung Galaxy S2 Android
- ¿Cómo cambiar el modo de conexión USB de Android para cargar solo?
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="1234" product-id="5678" /> </resources>
El problema es, si el servicio se inicia después de que se inserta el dispositivo USB, no se recibe ninguna intención. Puedo usar getDeviceList
para obtener una lista de dispositivos, pero deseo evitar duplicar las condiciones de filtro del archivo device_filter.xml
. ¿Es eso posible?
- Uso de Android para comunicarse con un dispositivo USB HID
- Comunicación entre PhoneGap, dispositivo externo usb y modo host Android
- ¿Hay una manera de comunicarse con dispositivos USB en Android?
- Cómo enviar un mensaje de Android a Windows mediante USB
- Android USB API: cambia entre carga y envío de datos
- Android USB OTG: por programación, apague la alimentación del puerto
- Permisos de archivos Linux para dispositivos USB en Android
- Los controladores usb para adb no funcionan para Motorola mc40
La funcionalidad de filtrado se implementa en frameworks/base/services/java/com/android/server/usb/UsbSettingsManager.java
, pero éstos son desafortunadamente privados. He extraído parte de su implementación, se puede utilizar de esta manera:
private void scanDevices() { ArrayList<UsbDevice> devices; try { devices = UsbDeviceFilter.getMatchingHostDevices(this, R.xml.wifi_devices); } catch (Exception e) { Log.w(TAG, "Failed to parse devices.xml: " + e.getMessage()); return; } for (UsbDevice device : devices) { Log.d(TAG, "Matched device " + device); } }
Actualmente solo se aceptan dispositivos host, pero agregar soporte para dispositivos accesorios es trivial.
UsbDeviceFilter.xml:
import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; import android.content.res.XmlResourceParser; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; /** * Utility to test whether a USB device is accepted by a device filter. Heavily * based on com.android.server.usb.UsbSettingsManager. * @author Peter Wu <[email protected]> */ public class UsbDeviceFilter { private final List<DeviceFilter> hostDeviceFilters; public UsbDeviceFilter(XmlPullParser parser) throws XmlPullParserException, IOException { hostDeviceFilters = new ArrayList<UsbDeviceFilter.DeviceFilter>(); int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String tagName = parser.getName(); if ("usb-device".equals(tagName) && parser.getEventType() == XmlPullParser.START_TAG) { hostDeviceFilters.add(DeviceFilter.read(parser)); } eventType = parser.next(); } } public boolean matchesHostDevice(UsbDevice device) { for (DeviceFilter filter : hostDeviceFilters) { if (filter.matches(device)) { return true; } } return false; } /** * Get a list of connected USB Host devices matching the devices filter. * @param ctx A non-null application context. * @param resourceId The resource ID pointing to a devices filter XML file. * @return A list of connected host devices matching the filter. * @throws XmlPullParserException * @throws IOException */ public static ArrayList<UsbDevice> getMatchingHostDevices(Context ctx, int resourceId) throws XmlPullParserException, IOException { UsbManager usbManager = (UsbManager) ctx .getSystemService(Context.USB_SERVICE); XmlResourceParser parser = ctx.getResources().getXml(resourceId); UsbDeviceFilter devFilter; try { devFilter = new UsbDeviceFilter(parser); } finally { parser.close(); } ArrayList<UsbDevice> matchedDevices = new ArrayList<UsbDevice>(); for (UsbDevice device : usbManager.getDeviceList().values()) { if (devFilter.matchesHostDevice(device)) { matchedDevices.add(device); } } return matchedDevices; } public static class DeviceFilter { // USB Vendor ID (or -1 for unspecified) public final int mVendorId; // USB Product ID (or -1 for unspecified) public final int mProductId; // USB device or interface class (or -1 for unspecified) public final int mClass; // USB device subclass (or -1 for unspecified) public final int mSubclass; // USB device protocol (or -1 for unspecified) public final int mProtocol; private DeviceFilter(int vid, int pid, int clasz, int subclass, int protocol) { mVendorId = vid; mProductId = pid; mClass = clasz; mSubclass = subclass; mProtocol = protocol; } private static DeviceFilter read(XmlPullParser parser) { int vendorId = -1; int productId = -1; int deviceClass = -1; int deviceSubclass = -1; int deviceProtocol = -1; int count = parser.getAttributeCount(); for (int i = 0; i < count; i++) { String name = parser.getAttributeName(i); // All attribute values are ints int value = Integer.parseInt(parser.getAttributeValue(i)); if ("vendor-id".equals(name)) { vendorId = value; } else if ("product-id".equals(name)) { productId = value; } else if ("class".equals(name)) { deviceClass = value; } else if ("subclass".equals(name)) { deviceSubclass = value; } else if ("protocol".equals(name)) { deviceProtocol = value; } } return new DeviceFilter(vendorId, productId, deviceClass, deviceSubclass, deviceProtocol); } private boolean matches(int clasz, int subclass, int protocol) { return ((mClass == -1 || clasz == mClass) && (mSubclass == -1 || subclass == mSubclass) && (mProtocol == -1 || protocol == mProtocol)); } public boolean matches(UsbDevice device) { if (mVendorId != -1 && device.getVendorId() != mVendorId) return false; if (mProductId != -1 && device.getProductId() != mProductId) return false; // check device class/subclass/protocol if (matches(device.getDeviceClass(), device.getDeviceSubclass(), device.getDeviceProtocol())) return true; // if device doesn't match, check the interfaces int count = device.getInterfaceCount(); for (int i = 0; i < count; i++) { UsbInterface intf = device.getInterface(i); if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(), intf.getInterfaceProtocol())) return true; } return false; } } }
- Google Place API – autocompletar – cómo obtener código postal?
- Envío de datos desde un PC a un dispositivo Android mediante USB OTG