2011-02-18 9 views
10

Sto tentando di utilizzare un BroadcastReceiver per rilevare quando il telefono si è disconnesso da un punto di accesso WiFi. Per fare questo, ho registrato il mio BroadcastReceiver nel manifesto:rilevamento disconnessione da un punto di accesso WiFi

<receiver android:name="com.eshayne.android.WiFiBroadcastReceiver"> 
    <intent-filter> 
     <action android:name="android.net.wifi.STATE_CHANGE" /> 
    </intent-filter> 
</receiver> 

Nella mia classe WiFiBroadcastReceiver, sto controllando per un'azione NETWORK_STATE_CHANGED_ACTION e guardando lo stato dettagliato della NetworkInfo:

if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 
    NetworkInfo info = (NetworkInfo)intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 
    android.util.Log.d("com.eshayne.android.WiFiBroadcastReceiver", "network state change - detailedState=" + info.getDetailedState() + ": " + info.toString()); 
    if (info.getDetailedState() == DetailedState.DISCONNECTED) { 
     ... 
    } 
    else if (info.getDetailedState() == DetailedState.CONNECTED) { 
     ... 
    } 

Il problema che ho' vedendo che quando il telefono lascia il range del punto di accesso WiFi, il mio callback "disconnesso" viene chiamato 6 volte - piuttosto regolarmente a circa una volta ogni 15 secondi - prima che si fermi. Finora non sono stato in grado di trovare alcuna caratteristica distintiva tra NetworkInfo di ogni callback. Ogni oggetto NetworkInfo essere scritto nel registro è simile al seguente:

02-18 10:16:51.918 D/com.eshayne.android.WiFiBroadcastReceiver(1511): network state change - detailedState=DISCONNECTED: NetworkInfo: type: WIFI[], state: DISCONNECTED/DISCONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true 

Non è anche una questione di telefono vagare dentro e fuori dal campo di Wi-Fi, come la mia callback "connesso" non è chiamato tra callback "estratto" . Né vi sono altri stati che vengono attivati ​​nel mezzo. Basta una rapida serie di 6 callback ciascuno con uno stato dettagliato di DISCONNECTED.

C'è un modo migliore per rilevare quando il telefono ha perso la sua connessione WiFi, in modo che il mio callback venga chiamato una sola volta per disconnessione? O un modo per scoprire quale dei 6 callback che sto vedendo è quella "finale"?

+0

Qual è esattamente il problema qui? Quando dici che il telefono non si ricollega dopo la prima trasmissione, nessuno dei 6 è buono come l'altro? –

+0

Il problema è che non voglio che il mio ricevitore di trasmissione esegua la stessa logica di gestione della disconnessione sei volte. – eshayne

risposta

2

Si dice che si tratti di una "serie rapida di 6 callback disconnessi", ma il tuo if/else-if controlla solo per DISCONNECTED e CONNECTED, con quello che sembra un blocco predefinito per gestire tutti gli altri casi. Dalla pagina di API NetworkInfo.DetailedState, ci sono 10 possibili stati che potrebbero essere restituiti da NetworkInfo.getDetailedState(), tra cui "connessione", "scansione", "disconnessione", il che sarebbe un comportamento plausibile per un telefono appena disconnesso da un Rete.

Buttare giù un caso predefinito che avvisa di qualsiasi cambiamento nello stato wifi, non solo "CONNECTED" e "DISCONNECTED". Potresti scoprire che il telefono sta ruotando tra diversi stati diversi, e non solo sparare allo stesso modo contro di te sei volte. Speriamo da lì, come procedere nel tuo codice sarà un po 'più chiaro.

+0

Grazie. Avrei dovuto chiarire: in realtà sto registrando l'intero NetworkInfo, prima di controllare CONNECTED o DISCONNECTED. Sono tutti DISCONNECTED. Ho aggiornato il mio post originale per mostrare come appaiono tutte le voci del registro. Se riesci a pensare a qualcos'altro da controllare su ogni callback per cercare di distinguerli, farò un tentativo. – eshayne

0

Una soluzione alternativa che è possibile utilizzare è mantenere l'ultima azione di richiamata da qualche parte (stato globale, preferenze condivise, ecc.) E eseguire solo i callback se l'azione è stata modificata.

enum NetworkCallbackAction { None, Disconnected, Connected }; 
NetworkCallbackAction lastHandledAction = NetworkCallbackAction.None; 

// ... 

if (info.getDetailedState() == DetailedState.DISCONNECTED) { 
    if (lastHandledAction != NetworkCallbackAction.Disconnected) { 
    lastHandledAction = NetworkCallbackAction.Disconnected; 
    // ... 
    } 
} 
else if (info.getDetailedState() == DetailedState.CONNECTED) { 
    if (lastHandledAction != NetworkCallbackAction.Connected) { 
    lastHandledAction = NetworkCallbackAction.Connected; 
    // ... 
    } 
} 

Un'astrazione più bello di questa logica sarebbe quella di scrivere un ricevitore trasmissione il cui unico scopo è quello di normalizzare i cambiamenti di stato della rete in eventi coerenti e appianare le stranezze del mondo reale, e poi ri-trasmettere le proprie azioni . Questo ti consente di semplificare gli aggiornamenti grezzi in qualcosa che ha senso per la tua applicazione. Potrebbe, ad esempio, ricordare che sono le ultime trasmissioni e solo le modifiche di trasmissione (simili a ciò che fa il codice sopra). In caso di raffiche di intenti di modifica della rete potrebbe attendere alcuni secondi prima di trasmettere l'ultimo stato ricevuto.

Problemi correlati