2013-04-02 14 views
6

Ho un'app Android che deve rilevare quando una periferica USB è collegata o scollegata. Funziona correttamente quando la periferica viene collegata per la prima volta, ma non ricevo alcuna notifica (ad esempio, non ricevo uno Intent la cui azione è ACTION_USB_DEVICE_DETACHED) quando viene successivamente rimosso.Rilevamento quando un dispositivo USB è scollegato su Android

Ecco la parte rilevante della mia AndroidManifest.xml:

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

Può anche essere interessante notare che LauncherActivity esiste solo per iniziare una Service quando il dispositivo è collegato, e per arrestare il servizio quando si è staccato. In entrambi i casi, LauncherActivity è sempre finish stesso. Tutto ciò si verifica in LauncherActivity.onCreate.

Qualche idea?

+0

Ciao controlla questo post http://stackoverflow.com/a/9814826/760489 – Pratik

risposta

10

USB_DEVICE_DETACHED è una trasmissione broadcast, quindi è possibile dichiarare BroadcastReceiver in manifest con il filtro intent-intent appropriato per l'azione distaccata, anche con i metadati allegati. Lo stesso vale per USB_ACCESSORY_DETACHED, per chi è interessato.

Sommario:
USB_XXX_ATTACHED è un intento un'attività
USB_XXX_DETACHED è un intento trasmissione

(dove XXX = DISPOSITIVO | ACCESSORIO)

See: http://developer.android.com/guide/components/intents-filters.html

"C'è nessuna sovrapposizione all'interno di questi sistemi di messaggistica: gli intenti di trasmissione vengono inviati solo ai ricevitori di trasmissione , mai alle attività o ai servizi "

+0

Questo non è corretto. Le azioni 'DEVICE' sono entrambe trasmissioni. Per 'ACCESSORY', l'allegato è un'azione di attività, ma il distaccato in un'azione broadcast. –

+0

L'intento USB_XXX_ATTACHED può essere utilizzato anche come intento di trasmissione, l'ho provato e funziona correttamente per me. –

3

Quindi, non ho mai ricevuto il ACTION_USB_DEVICE_DETACHEDIntent per andare a LauncherActivity; Non so quale sia l'accordo, probabilmente qualcosa che non capisco correttamente sui filtri intent o sui callback del ciclo di vita Activity.

La soluzione che ho utilizzato viene dal post collegato da Pratik. Fondamentalmente ho preso tutto su USB_DEVICE_DETACHED su AndroidManifest.xml. Poi, nel metodo della ServiceonCreate, ho registrato un BroadcastReceiver come questo:

@Override 
public void onCreate() { 
    detachReceiver = new BroadcastReceiver() { 
     public void onReceive(Context context, Intent intent) { 
      if(intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) 
       stopSelf(); 
     } 
    }; 

    IntentFilter filter = new IntentFilter(); 
    filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); 
    registerReceiver(detachReceiver, filter); 
} 

Un po 'goffo, e io sono ancora curioso di sapere perchè semplicemente aggiungendo USB_DEVICE_DETACHED alla <intent-filter> di LauncherActivity non funzionava, ma è fa quello che mi serve.

+0

Funziona alla grande. Il trucco per me era rimuovere USB_DEVICE_DETACHED da AndroidManifest.xml. – Frank

6

Provare con USB_STATE come di seguito.

Attiverà sia collegato che detaricato allo stesso ricevitore e nel ricevitore è possibile identificare se è stato collegato o evento non rilevato.

IntentFilter filter = new IntentFilter(); 
filter.addAction("android.hardware.usb.action.USB_STATE"); 

Ricevitore:

public class USBReceiver extends BroadcastReceiver { 
    public void onReceive(Context context, Intent intent) { 
     if (intent.getExtras().getBoolean("connected")) { 
      //do your stuff 
     } 
    } 
} 
+0

Funziona come un fascino! Grazie –

+0

Grazie. Ma sto diventando sempre falso. Controllerò. – Herman

0

Per quello che vale, ho avuto questo stesso problema perché l'attività è in pausa poi riprende quando il dispositivo è scollegato.
Poiché il ricevitore non è registrato nel metodo appena prima della ricezione dello ACTION_USB_DEVICE_DETACHED, l'app non viene mai notificata.

+0

Sarebbe fantastico se tu scrivessi come hai risolto questo problema. –

0

La correzione che ha funzionato per me è stato quello di annullare la registrazione in onPause() e registrare di nuovo in onResume():

@Override 
public void onPause() 
{ 
    super.onPause(); 
    stopIOManager(); 
    if(m_UsbReceiver!=null) unregisterReceiver(m_UsbReceiver); 
} 

@Override 
public void onResume() 
{ 
    super.onResume(); 
    startIOManager(); 
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); 
    filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); 
    filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); 
    registerReceiver(m_UsbReceiver, filter); 
} 

Tuttavia, anche se l'applicazione sembra ricevere sempre l'evento staccare, una volta ogni tanto non ottiene l'evento ATTACCATO. Poi ho bisogno di collegare e scollegare il connettore USB, e di solito funziona dopo uno o due tentativi. Ho dato la colpa di questo strano comportamento al sistema operativo, senza certezza.

Problemi correlati