android - usbdevice - otg xml
USB_DEVICE_ATTACHED IntenciĆ³n no disparar (11)
Así que encontré una solución a mi problema y aprendí mucho, espero que pueda ayudar a alguien más.
Así que primero los dispositivos HID no inician ninguna intención . Tampoco aparecen en la lista mUsbManager.getDeviceList()
. Sin embargo, otras cosas hacen. Le di una oportunidad a una memoria USB y, ¿qué sabe, el dispositivo aparece en la lista de dispositivos? También descubrí que el dispositivo devuelto no tiene una clase, subclase o protocolo. La depuración reveló que la interfaz principal tenía, sin embargo, la clase / subclase / y protocolo adecuados. También si debe tener un filtro de dispositivo. Terminé con una class=0008 (USB STORAGE)
para trabajar para mis propósitos. Supongo que otras clases también funcionarían.
Así que ahora a averiguar intenciones. Resulta que la intención debe estar vinculada a una actividad de lanzador. Mis intentos de adjuntarlo a un servicio o receptor no darán ningún fruto. Así que ahora que tengo intenciones de disparar, ahora veo notificaciones emergentes cuando adjunto mi dispositivo (dispositivo de memoria USB) me pide que configure mi aplicación como la predeterminada para ese dispositivo. Perfecto ahora mi aplicación se ejecuta cada vez que adjunto ese dispositivo. Tenga en cuenta que se le solicitará cada dispositivo único. Pero solo una vez. Parece estar registrado como programas por defecto.
Bueno, creo que eso resume lo que encontré. Lástima que no pueda recibir una notificación cuando se conecte un teclado / mouse. Ah, y una cosa más. No hay ningún problema con el kernel tiamat, ejecutándolo ahora y sin problemas.
¿Alguien ha podido conseguir que "android.hardware.usb.action.USB_DEVICE_ATTACHED" funcione?
Ok, estoy intentando usar las nuevas funciones del modo host de usb para detectar cuándo se conecta un dispositivo usb. Para mis propósitos, quiero ser notificado cada vez que se adjunte un dispositivo. No pude verlo pasar. Estoy usando un receptor de televisión que sé que funciona (cuando lo tengo, escucha otras cosas, como presionar el botón de inicio. No importa lo que intente, no puedo tener la intención de disparar ... Así que para simplificar las cosas, decidí olvidarme de mi proyecto e intentar usar el código de muestra propio de Google y ver si al menos podía hacer que funcionara. No tengo uno de los lanzadores de misiles, pero pensé que al menos podría obtener el dispositivo USB_Device_Attached No disparé. Adapté el código para que funcione con otros dispositivos. Primero intenté ajustar el xml del filtro del dispositivo. Agregué mi dispositivo (un teclado):
<usb-device vendor-id="1050" product-id="0010" />
Obtuve el proveedor y el producto de un comando lsusb. Cuando el dispositivo está conectado, el logcat muestra que se encuentra el dispositivo
D/EventHub( 144): No input device configuration file found for device ''Yubico Yubico Yubikey II''.
I/EventHub( 144): New device: id=43, fd=219, path=''/dev/input/event8'', name=''Yubico Yubico Yubikey II'', classes=0x80000003, configuration='''', keyLayout=''/system/usr/keylayout/Generic.kl'', keyCharacterMap=''/system/usr/keychars/Generic.kcm'', builtinKeyboard=false
I/InputReader( 144): Device added: id=43, name=''Yubico Yubico Yubikey II'', sources=0x00000101
I/ActivityManager( 144): Config changed: { scale=1.0 imsi=0/0 loc=en_US touch=3 keys=2/1/1 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=47}
D/MissileLauncherActivity(16191): intent: android.intent.action.MAIN
I/EventHub( 144): Removed device: path=/dev/input/event8 name=Yubico Yubico Yubikey II id=43 fd=219 classes=0x80000003
I/InputReader( 144): Device removed: id=43, name=''Yubico Yubico Yubikey II'', sources=0x00000101
I/ActivityManager( 144): Config changed: { scale=1.0 imsi=0/0 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=48}
D/dalvikvm( 144): GC_EXPLICIT freed 78K, 26% free 14717K/19719K, paused 3ms+3ms
D/MissileLauncherActivity(16191): intent: android.intent.action.MAIN
El xoom encuentra el teclado y se puede usar desde el dispositivo (puedo usarlo en el navegador para escribir letras). Y el tipo de intención de incendios (pero solo dispara el android.intent.action.MAIN) nunca obtengo el DEVICE_ATTACHED Intent. La entrada de registro proviene del código de ejemplo:
Log.d(TAG, "intent: " + intent.getAction().toString());
En la función de reanudar. Después de seguir investigando y eliminando cualquier referencia a usb, descubrí que cada aplicación que obtengo se llama al currículum cuando se conecta / desconecta un teclado (de ahí la intención: entrada de registro android.intent.action.MAIN). En este momento, lo único que puedo imaginar es que es un error en la fuente de Android. Por cierto, estoy usando un wifi xoom con OS 3.1.
Conecte el teclado USB. NO dispare USB_DEVICE_ATTACHED .
En su lugar, el sistema activará Intent.ACTION_CONFIGURATION_CHANGED . Sin embargo, como hay un cambio de configuración, el sistema reiniciará la Actividad. No capturarás la acción con la actividad reiniciada. En este caso, debe agregar android: configChanges = "keyboard | keyboardHidden" en su manifiesto de Android para que la actividad no se reinicie una vez que se conecte un teclado externo.
Desde mis pruebas, Android puede disparar una intención cuando se conecta un dispositivo HID. (La aplicación de ejemplo MissileLauncher hace precisamente eso. Consulte el código fuente de ejemplo para obtener más información).
El dispositivo HID de Missile Launcher (Dream Cheeky USB Missle Launcher) tiene su subclase y protocolo configurados en 0x00. Para obtener más información, consulte: http://www.mattcutts.com/blog/playing-with-a-usb-missile-launcher/
La advertencia es que Android no lanza una intención específica para dispositivos de mouse y teclado (quizás más). Sin embargo, puedo detectar dispositivos HID que tienen su InterfaceClass = 0x03, InterfaceSubClass = 0x00, InterfaceProtocol = 0x00. Para mi aplicación, mi dispositivo HID es un controlador integrado, por lo que configurar la subclase y el protocolo no es un problema.
Dispositivos de enumeración
Si su aplicación está interesada en inspeccionar todos los dispositivos USB conectados actualmente mientras se está ejecutando, puede enumerar los dispositivos en el bus. Utilice el método getDeviceList () para obtener un mapa hash de todos los dispositivos USB que están conectados. El mapa hash está marcado por el nombre del dispositivo USB si desea obtener un dispositivo del mapa.
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Si lo desea, también puede obtener un iterador del mapa hash y procesar cada dispositivo uno por uno:
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
UsbDevice device = deviceIterator.next()
//your code
}
Esto es lo que hice para detectar USB / Media Connect.
Archivo de manifiesto
<receiver
android:name=".UsbReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
<data android:scheme="file"/>
</intent-filter>
</receiver>
No hice nada en la actividad ni mi receptor.
Parece que esta línea está haciendo las cosas.
<data android:scheme="file"/>
OK más trabajo, más fracaso, pero algo de progreso.
Me enteré más de la documentación de SDK. parece que tienes que tener el filtro del dispositivo para usar los intentos. así que decidí intentar usar un filtro de clase en lugar de los identificadores de proveedor / producto. Me imagino que sería más general y con suerte atraparía el dispositivo escondido. Utilicé 03h como el ID de clase, probé varios formatos, probé las subclases, incluso usé lsusb para descubrir, clase, subclase y protocolo de mi dispositivo. Estos no parecían ayudar en absoluto. así que fui más lejos en la documentación de sdk y decidí intentar enumerar todos los dispositivos para ver qué os veían los enteros de clase / subclase / protocolo. Copié el código y lo pegué en el detector de clics y agregando las declaraciones log.v. nada se muestra en el logcat.
Parece que el sistema de Estados Unidos no está viendo ningún dispositivo (aunque el dispositivo realmente funciona). Ahora bien, esto es muy indicativo de que el dispositivo USB conectado no intenta disparar. ahora debo decir que estoy usando un kernel personalizado en mi xoom (tiamat). Pensé que esto podría tener algo que ver con el problema hace un tiempo, así que volví al stock 3.1. y todavía ahora el progreso. ahora esto fue hace un tiempo, antes de que tratara de enumerar, ahora revertiré de nuevo y seguiré trabajando con stock hasta que esté seguro de que el núcleo no es el problema. Voy a comprobar de nuevo cuando me enteré de más. éxito o fracaso. por supuesto, si alguien más lo entiende mejor que yo, por favor agregue una última nota. Estoy muy preocupado por el modo de host otg completo cuando vi esto en la documentación. Observe que el número es idéntico, incluso que se refiere a dos métodos de enumeración. Probablemente solo un autor de la copia se haya equivocado, pero todavía se preocupa a la luz de todo este fracaso.
Otra solución es usar
new FileObserver("/dev/input") {
@Override public void onEvent(int event, String path) {
//gets called on input device insert / remove
}
};
que funcionará para algunos dispositivos usb (teclado, mouse)
Recientemente descubrí una solución a un problema similar.
Como alguien ya ha notado, HID devices
no inician una intención , que creo que fue su problema.
Sin embargo, un problema relacionado es que, si su programa está configurado para ejecutarse cuando se conecta un dispositivo USB, incluso una vez que su aplicación se esté ejecutando, no podrá capturar la acción USB_DEVICE_ATTACHED
. En su lugar, el sistema ve esa intención y dice "oh, eso significa que esta aplicación quiere ejecutarse (como se declara en su manifiesto) y luego le envía la acción android.intent.action.MAIN en lugar de la acción USB_DEVICE_ATTACHED
, y llama a onResume()
. Incluso si su aplicación se está ejecutando. Por lo que puedo decir, usted NO PUEDE capturar la intención de USB_DEVICE_ATTACHED
si su manifiesto declara que su aplicación se ejecutará cuando se conecten dispositivos USB. Solo tiene que poner algo de código en el onResume()
para verificar si el USB está conectado. Incluso si su programa se está ejecutando, onResume se llamará nuevamente cuando se conecte un dispositivo USB.
Anoto mi solución con más detalle aquí: Android 3.1 USB-Host - BroadcastReceiver no recibe USB_DEVICE_ATTACHED
También tuve el mismo problema. Finalmente descubrí que en el filtro de dispositivo xml deberíamos agregar la siguiente línea.
<usb-device vendor-id-"xxxxx" product-id="yyyyy">
xxxxx y yyyyy deben ser números decimales. NO HEX CODIGOS. Entonces todo funciona como se anuncia! Sé que es tarde pero espero que ayude.
Tengo mi aplicación configurada como launchMode="singleTop"
y en ese modo parece que getIntent().getAction()
siempre es igual a la acción que inició la aplicación por primera vez.
Entonces, si inicia la aplicación manualmente y luego conecta un dispositivo (incluso después de haber cambiado de esa aplicación), recibirá android.intent.action.MAIN
.
Si mata la aplicación y luego conecta el dispositivo, siempre obtendrá android.hardware.usb.action.USB_DEVICE_ATTACHED
, incluso al cambiar de dispositivo a otro, o incluso para rotar el dispositivo .
En realidad, recibo intenciones extrañas cuando desconecto el dispositivo USB, lo cual no creo que esté documentado, pero, por supuesto, recibo USB_DEVICE_ATTACHED
cuando mi dispositivo está desconectado.
Sin singleTop
, funciona como se espera, pero luego obtienes otra actividad adicional estúpida si tu aplicación ya está abierta y conectas el dispositivo.
Una vez más, la API de Android tiene muchos errores, es demasiado complicada y difícil de usar.
Yo tuve el mismo problema. Mi última solución fue utilizar la antigua técnica de sondeo. Aquí hay una clase bastante mínima que resuelve el problema a mi entera satisfacción.
package com.YourCompancy.YourProduct;
import android.app.*;
import android.content.*;
import android.hardware.usb.*;
import java.util.*;
import android.util.*;
import android.os.*;
public class UsbDeviceWatcher extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED))
{
UsbDevice d = (UsbDevice)
intent.getExtras().get(UsbManager.EXTRA_DEVICE);
DeviceConnect(d, false);
}
}
public void DeviceConnect(UsbDevice device, boolean Attached)
{
if (Attached)
{
// Some suggestions ...
// play sound effect
// notify consumer software
// determine if interested in device
// etc
Log.i("usb", "device attached");
} else
{
Log.i("usb", "device detached");
}
}
public UsbManager manager;
public Handler handler;
public UsbDeviceWatcher(Context context, Handler handle)
{
this.handler = handle;
manager = (UsbManager)
context.getSystemService(Context.USB_SERVICE);
IntentFilter dev = new IntentFilter();
dev.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
context.registerReceiver(this, dev);
final UsbDeviceWatcher _this = this;
Thread thread = new Thread(new Runnable()
{
public void run()
{
LinkedList<UsbDevice> seen = new LinkedList<UsbDevice>();
LinkedList<UsbDevice> attached = new LinkedList<UsbDevice>();
//there is a need for multithread support here
// so the thread can watch for an exit condition
while (true)
{
HashMap<String, UsbDevice>
D = manager.getDeviceList();
for (UsbDevice d : D.values())
{
if (!seen.contains(d))
{
if (!attached.contains(d))
{
final UsbDevice dev = d;
handler.post(new Runnable(){
public void run()
{
DeviceConnect(dev, true);
}
});
}
seen.add(d);
}
}
for (UsbDevice d : seen)
{
if (!D.values().contains(d)) seen.remove(d);
}
try
{
Thread.sleep(500);
} catch (InterruptedException exception)
{
return;
}
}
}
});
thread.start();
}
}