Lettura dello stato della rete

Android consente alle app di apprendere i cambiamenti dinamici della connettività. Utilizza la le seguenti classi per monitorare e rispondere ai cambiamenti di connettività:

  • ConnectivityManager indica alla tua app lo stato della connettività nel sistema.
  • La classe Network rappresenta uno dei reti a cui è connesso il dispositivo. Puoi usare Network come chiave per raccogliere informazioni sulla rete ConnectivityManager o per associare i socket sulla rete. Quando la rete si disconnette, l'oggetto Network smette di essere utilizzabile. Anche se in un secondo momento si riconnette alla stessa appliance, un nuovo oggetto Network rappresenta nuova rete.
  • L'oggetto LinkProperties contiene informazioni sul collegamento di una rete, come l'elenco DNS server, indirizzi IP locali e route di rete installati per la rete.
  • La NetworkCapabilities contiene informazioni sulle proprietà di una rete, come (Wi-Fi, mobile, Bluetooth) e le capacità della rete. Ad esempio, puoi eseguire una query sull'oggetto per determinare se la rete è in grado di inviare MMS, si trova dietro un captive portal o a consumo.

Le app interessate allo stato immediato della connettività in un dato momento possono chiama i metodi ConnectivityManager per scoprire che tipo di rete è disponibili. Questi metodi sono utili per il debug e per esaminare occasionalmente un'istantanea della connettività disponibile in un dato momento.

Tuttavia, l'architettura sincrona I metodi di ConnectivityManager non comunicano nulla alla tua app dopo una chiamata, così non ti permettono di aggiornare l'UI. Inoltre, non può modificare l'app comportamento basato sulla disconnessione della rete o quando le funzionalità di rete modifica.

La connettività può cambiare in qualsiasi momento e la maggior parte delle app richiede vista sempre aggiornata e aggiornata dello stato del networking sul dispositivo. Le app possono registrare un callback con ConnectivityManager per ricevere avvisi sulle modifiche all'app. Grazie al callback, l'app può reagire immediatamente a qualsiasi un cambiamento significativo nella connettività, senza dover ricorrere a costosi sondaggi che potrebbero non essere aggiornati rapidamente.

Utilizzare NetworkCallback e altri modi per scoprire di più sul lo stato di connettività del dispositivo non richiede autorizzazioni particolari. Tuttavia, alcune reti sono soggette a autorizzazioni specifiche. Per Ad esempio, potrebbero esserci reti con limitazioni non disponibili per le app. Associazione a un rete in background richiede l'autorizzazione CHANGE_NETWORK_STATE. E alcuni potrebbero richiedere autorizzazioni specifiche per l'esecuzione. Fai riferimento alle documentazione per ogni chiamata per maggiori dettagli.

Ottieni stato istantaneo

Un dispositivo Android è in grado di mantenere molte connessioni contemporaneamente. Per ottenere informazioni sullo stato attuale della rete, devi prima ottenere un'istanza di ConnectivityManager:

Kotlin

val connectivityManager = getSystemService(ConnectivityManager::class.java)

Java

ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);

Quindi, utilizza questa istanza per ottenere un riferimento alla rete predefinita attuale per dell'app:

Kotlin

val currentNetwork = connectivityManager.getActiveNetwork()

Java

Network currentNetwork = connectivityManager.getActiveNetwork();

Quando fai riferimento a una rete, l'app può richiedere informazioni in merito:

Kotlin

val caps = connectivityManager.getNetworkCapabilities(currentNetwork)
val linkProperties = connectivityManager.getLinkProperties(currentNetwork)

Java

NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(currentNetwork);
LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);

Per funzionalità più utili, registra un NetworkCallback Per ulteriori informazioni sulla registrazione dei callback di rete, vedi Ascoltare eventi di rete.

NetworkCapabilities e LinkProperties

Gli oggetti NetworkCapabilities e LinkProperties forniscono informazioni su tutti gli attributi di una rete noti al sistema.

LinkProperties conosce route, indirizzi dei link, nome dell'interfaccia, informazioni proxy (se qualsiasi) e server DNS. Chiama il metodo pertinente sull'oggetto LinkProperties per recuperare le informazioni di cui hai bisogno.

L'oggetto NetworkCapabilities contiene informazioni sui trasporti della rete e sulle relative funzionalità.

Un trasporto è un'astrazione di un mezzo fisico su cui una rete dell'IA. Esempi comuni di trasporti sono Ethernet, Wi-Fi e dispositivi mobili. Anche le VPN e il Wi-Fi peer-to-peer possono essere mezzi di trasporto. Su Android, una rete può supportare più trasporti contemporaneamente. Esempio di questa è una VPN che opera sia su reti Wi-Fi che su reti mobili. La VPN ha Trasporti Wi-Fi, mobili e VPN. Per scoprire se un rete ha un determinato trasporto, utilizza NetworkCapabilities.hasTransport(int) con una delle costanti NetworkCapabilities.TRANSPORT_*.

Una funzionalità descrive una proprietà della rete. Le funzionalità di esempio includono MMS, NOT_METERED e INTERNET. Una rete con la funzionalità MMS può inviare e ricevere messaggi da Multimedia Messaging Service e una rete senza non è possibile. Una rete con funzionalità NOT_METERED non addebita la l'utente per i dati. La tua app può verificare le funzionalità appropriate usando la NetworkCapabilities.hasCapability(int) con una delle costanti NetworkCapabilities.NET_CAPABILITY_*.

Le costanti NET_CAPABILITY_* più utili includono:

  • NET_CAPABILITY_INTERNET: indica che la rete è configurata per accedere a internet. Si tratta della configurazione, non della configurazione capacità di raggiungere server pubblici. Ad esempio, una rete può essere impostata accedono a internet ma devono essere soggetti a un captive portal.

    La rete mobile di un operatore in genere ha la funzionalità INTERNET, mentre una in genere non avviene con la rete Wi-Fi P2P locale. Per la connettività effettiva, vedi NET_CAPABILITY_VALIDATED.

  • NET_CAPABILITY_NOT_METERED: indica che la rete non è a consumo. Una rete è classificati come a consumo quando l'utente è sensibile all'utilizzo intensivo dei dati Connessione a causa di costi monetari, limitazioni dei dati o prestazioni della batteria che le applicazioni presentino problemi di prestazioni.

  • NET_CAPABILITY_NOT_VPN: indica che la rete non è una rete privata virtuale.

  • NET_CAPABILITY_VALIDATED: indica che la rete fornisce l'accesso effettivo alla rete internet pubblica. Una rete dietro un prigioniero un portale o una rete che non fornisce la risoluzione dei nomi di dominio questa funzionalità. Si tratta del valore più vicino che il sistema può rilevare riguardo a una rete di fornire effettivamente l'accesso, sebbene una rete convalidata possa comunque in linea di principio, essere soggetti a filtri basati sugli IP o subire perdite improvvise a causa di problemi quali segnale scarso.

  • NET_CAPABILITY_CAPTIVE_PORTAL: indica che la rete ha un captive portal quando viene sottoposta a sonda.

Esistono altre funzionalità che potrebbero essere interessate alle app più specializzate. Per ulteriori informazioni, leggi le definizioni dei parametri in NetworkCapabilities.hasCapability(int)

Le funzionalità di una rete possono cambiare in qualsiasi momento. Quando il sistema rileva captive portal, mostra una notifica che invita l'utente ad accedere. Anche se questo è continua, la rete ha NET_CAPABILITY_INTERNET NET_CAPABILITY_CAPTIVE_PORTAL, ma non le funzionalità funzionalità NET_CAPABILITY_VALIDATED.

Quando l'utente intraprende un'azione e accede a pagina del captive portal, il dispositivo diventa in grado di accedere alla rete internet pubblica e la rete acquisisce la funzionalità NET_CAPABILITY_VALIDATED e perde NET_CAPABILITY_CAPTIVE_PORTAL.

Analogamente, i trasporti di una rete possono cambiare in modo dinamico. Ad esempio, una VPN può riconfigurarsi per utilizzare una rete più veloce appena creata, come il passaggio dalla rete mobile al Wi-Fi alla rete sottostante. In questo caso, la rete perde TRANSPORT_CELLULAR trasporta e guadagna il trasporto TRANSPORT_WIFI, mantenendo il Trasporto di TRANSPORT_VPN.

Ascoltare eventi di rete

Per informazioni sugli eventi di rete, utilizza il NetworkCallback classe insieme a ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback) e ConnectivityManager.registerNetworkCallback(NetworkCallback) Questi due metodi offrono scopi.

Tutte le app per Android hanno una rete predefinita, determinata dal sistema. In genere il sistema preferisce le reti unmetered quelle a consumo e le reti più veloci su quelle più lente.

Quando un'app invia una richiesta di rete, ad esempio con HttpsURLConnection, il soddisfa questa richiesta utilizzando la rete predefinita. Le app possono inviare traffico anche su altre reti. Per ulteriori informazioni, consulta la sezione Ulteriori reti.

La rete impostata come rete predefinita può cambiare in qualsiasi momento durante la per tutta la durata di un'app. Un esempio tipico è che un dispositivo che rientra nel raggio d'azione Un punto di accesso Wi-Fi noto, attivo, non a consumo e più veloce di quanto non sia una rete mobile. La dispositivo si connette a questo punto di accesso e cambia la rete predefinita le app alla nuova rete Wi-Fi.

Quando una nuova rete diventa predefinita, viene utilizzata ogni nuova connessione aperta dall'app su questa rete. In un determinato momento, tutte le connessioni rimanenti sull'account la rete predefinita viene terminata in modo forzato. Se è importante che l'app quando cambia la rete predefinita, registra una rete predefinita il callback seguente:

Kotlin

connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network : Network) {
        Log.e(TAG, "The default network is now: " + network)
    }

    override fun onLost(network : Network) {
        Log.e(TAG, "The application no longer has a default network. The last default network was " + network)
    }

    override fun onCapabilitiesChanged(network : Network, networkCapabilities : NetworkCapabilities) {
        Log.e(TAG, "The default network changed capabilities: " + networkCapabilities)
    }

    override fun onLinkPropertiesChanged(network : Network, linkProperties : LinkProperties) {
        Log.e(TAG, "The default network changed link properties: " + linkProperties)
    }
})

Java

connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        Log.e(TAG, "The default network is now: " + network);
    }

    @Override
    public void onLost(Network network) {
        Log.e(TAG, "The application no longer has a default network. The last default network was " + network);
    }

    @Override
    public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
        Log.e(TAG, "The default network changed capabilities: " + networkCapabilities);
    }

    @Override
    public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
        Log.e(TAG, "The default network changed link properties: " + linkProperties);
    }
});

Quando una nuova rete diventa predefinita, l'app riceve una chiamata a onAvailable(Network) per la nuova rete. Implementa onCapabilitiesChanged(Network,NetworkCapabilities), onLinkPropertiesChanged(Network,LinkProperties), o entrambe le cose, per reagire in modo appropriato ai cambiamenti nella connettività.

Per una richiamata registrata con registerDefaultNetworkCallback(), onLost() significa che la rete ha perso lo stato di rete predefinita. Potrebbe essere disconnesso.

Anche se puoi trovare informazioni sui trasporti utilizzati dalla rete predefinita fare query NetworkCapabilities.hasTransport(int), Questo è un proxy non valido per la larghezza di banda o il livello di misurazione della rete. La tua app non è possibile presumere che la rete Wi-Fi sia sempre illimitata e che fornisca sempre una larghezza di banda migliore rispetto ai dispositivi mobili.

Usa invece NetworkCapabilities.getLinkDownstreamBandwidthKbps() per misurare la larghezza di banda NetworkCapabilites.hasCapability(int) con NET_CAPABILITY_NOT_METERED per determinare la misurazione. Per ulteriori informazioni, consulta la sezione su NetworkCapabilities e LinkProperties.

Per impostazione predefinita, i metodi di callback vengono chiamati nel thread di connettività di la tua app, che è un thread separato usato da ConnectivityManager. Se le tue dei callback deve fare più lavoro, chiamarli separa il thread worker usando la variante ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler)

Annulla la registrazione del callback quando non lo utilizzi più chiamando ConnectivityManager.unregisterNetworkCallback(NetworkCallback) La tua attività principale: onPause() è un buon posto per farlo, soprattutto se registri il callback in onResume().

Altre reti

Sebbene la rete predefinita sia l'unica pertinente per la maggior parte delle app, alcune app potrebbero essere interessati ad altre reti disponibili. Per scoprire di più, le app a creare una NetworkRequest che corrisponda esigenze e chiama ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback).

La procedura è simile all'ascolto a una rete predefinita. Tuttavia, anche se può esserci solo uno rete predefinita applicabile a un'app in un determinato momento, questa versione consente l'app vede tutte le reti disponibili contemporaneamente, quindi una chiamata a onLost(Network) indica che la rete si è disconnessa definitivamente, ma che non è quella predefinita più tardi.

L'app crea un NetworkRequest per informare ConnectivityManager del tipo delle emittenti che vuole ascoltare. L'esempio seguente mostra come creare un NetworkRequest per un'app interessata solo a internet senza limiti connessioni:

Kotlin

val request = NetworkRequest.Builder()
  .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
  .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
  .build()

connectivityManager.registerNetworkCallback(request, myNetworkCallback)

Java

NetworkRequest request = new NetworkRequest.Builder()
  .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
  .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
  .build();

connectivityManager.registerNetworkCallback(request, myNetworkCallback);

Ciò significa che la tua app viene a conoscenza di tutte le modifiche relative alle rete sul sistema.

Per quanto riguarda il callback di rete predefinito, è disponibile una versione registerNetworkCallback(NetworkRequest, NetworkCallback, Handler) che accetta Handler in modo che non carichi il thread Connectivity del tuo dell'app.

Chiama ConnectivityManager.unregisterNetworkCallback(NetworkCallback) quando il callback non è più pertinente. Un'app può registrare contemporaneamente più callback di rete.

Per praticità, L'oggetto NetworkRequest contiene l'oggetto funzionalità comuni richieste dalla maggior parte delle app, tra cui:

Quando scrivi l'app, controlla i valori predefiniti per vedere se corrispondono caso d'uso e cancellale se vuoi che la tua app riceva notifiche relative alle reti che non dispongono di queste funzionalità. Invece, aggiungi per evitare di dover cambiare la connettività nelle reti che con cui l'app non interagisce.

Ad esempio, se la tua app deve inviare messaggi MMS, aggiungi NET_CAPABILITY_MMS NetworkRequest per evitare di ricevere notifiche su tutte le reti che non possono inviare messaggi MMS. Aggiungi TRANSPORT_WIFI_AWARE se alla tua app interessa soltanto la connettività Wi-Fi P2P. NET_CAPABILITY_INTERNET e NET_CAPABILITY_VALIDATED sono utili se ti interessa poter trasferire dati con un server su internet.

Esempio di sequenza di callback

Questa sezione descrive la sequenza di callback che un'app potrebbe ricevere se registra sia un callback predefinito sia un callback regolare su un dispositivo che dispone di connettività mobile. In questo esempio, il dispositivo si connette buon punto di accesso Wi-Fi, quindi si disconnette. L'esempio presuppone anche che Sul dispositivo in cui è attiva l'impostazione Dati mobili sempre attivi è attivata.

Le tempistiche sono le seguenti:

  1. Quando l'app chiama il numero registerNetworkCallback(), viene richiamato immediatamente riceve chiamate da onAvailable(), onNetworkCapabilitiesChanged() e onLinkPropertiesChanged() per la rete mobile, perché solo questo di rete è disponibile. Se è disponibile un'altra rete, l'app riceve anche i callback per l'altra rete.

    Diagramma di stato che mostra l'evento di callback di rete del registro e i callback attivati dall'evento e
    Figura 1. Stato dell'app dopo la chiamata a registerNetworkCallback().

  2. Poi l'app chiama registerDefaultNetworkCallback(). La rete predefinita la richiamata inizia a ricevere chiamate al numero onAvailable(), onNetworkCapabilitiesChanged() e onLinkPropertiesChanged() per rete mobile, perché la rete mobile è la rete predefinita. Se un'altra rete non predefinita, l'app non può ricevere per la rete non predefinita.

    Diagramma di stato che mostra la registrazione dell'evento di callback di rete predefinito e
callback attivati dall'evento e
    Figura 2. Stato dell'app dopo la registrazione di una rete predefinita.

  3. In seguito, il dispositivo si connetterà a una rete Wi-Fi (non a consumo). Il normale la richiamata di rete riceve chiamate al numero onAvailable(), onNetworkCapabilitiesChanged() e onLinkPropertiesChanged() per Rete Wi-Fi.

    Diagramma di stato che mostra i callback attivati quando l'app si connette a un
nuova rete e
    Figura 3. Stato dell'app dopo la connessione a una rete Wi-Fi senza limiti.

  4. A questo punto, la convalida della rete Wi-Fi potrebbe richiedere un po' di tempo. Nella in questo caso, onNetworkCapabilitiesChanged() chiama la rete normale non includono la funzionalità NET_CAPABILITY_VALIDATED. Dopo un poco tempo, riceve una chiamata al numero onNetworkCapabilitiesChanged(), dove le nuove funzionalità includono NET_CAPABILITY_VALIDATED. Nella maggior parte dei casi, la convalida è molto rapida.

    Dopo la convalida della rete Wi-Fi, il sistema la preferisce rispetto alla rete mobile principalmente perché non è a consumo. La rete Wi-Fi diventa rete predefinita, in modo che il callback di rete predefinito riceva una chiamata a onAvailable(), onNetworkCapabilitiesChanged() e onLinkPropertiesChanged() per la rete Wi-Fi. La rete mobile sullo sfondo e il normale callback di rete riceve una chiamata onLosing() per la rete mobile.

    Poiché in questo esempio si parte dal presupposto che i dati mobili siano sempre attivi per il dispositivo, la rete mobile non si disconnette mai. Se l'impostazione è disattivata, dopo un mentre la rete mobile si disconnette e il normale callback di rete riceve una chiamata al numero onLost().

    Diagramma di stato che mostra i callback attivati quando una rete Wi-Fi
convalida connessione e
    Figura 4. Stato dell'app dopo la convalida della rete Wi-Fi.

  5. In seguito, il dispositivo si è comunque disconnesso improvvisamente dalla rete Wi-Fi perché è stato spento dell'intervallo. Poiché la rete Wi-Fi si disconnette, il normale callback di rete riceve un chiama onLost() per il Wi-Fi. Poiché la rete mobile è la nuova rete predefinita, il callback di rete predefinito riceve chiamate al numero onAvailable(), onNetworkCapabilitiesChanged() e onLinkPropertiesChanged() per rete mobile.

    Diagramma di stato che mostra i callback attivati quando una rete Wi-Fi
connessione interrotta e
    Figura 5. Stato dell'app dopo la disconnessione dalla rete Wi-Fi.

Se l'impostazione Dati mobili sempre attivi è disattivata, quando il Wi-Fi è disconnette il dispositivo e riprova a riconnettersi a una rete mobile. L'immagine è simile, ma con un breve ritardo aggiuntivo per le chiamate onAvailable() e il callback di rete standard riceve anche chiamate al numero onAvailable(), onNetworkCapabilitiesChanged() e onLinkPropertiesChanged() perché mobile diventa disponibile.

Restrizioni relative all'uso della rete per il trasferimento di dati

Se riesci a vedere una rete con un callback di rete, non significa che l'app possa utilizzare la rete per il trasferimento di dati. Alcune reti non offrono la connessione a internet e alcune reti potrebbero essere limitate con privilegi elevati. Per controllare la connettività a internet, consulta la pagina NET_CAPABILITY_INTERNET e NET_CAPABILITY_VALIDATED.

Anche l'utilizzo di reti in background è soggetto a controlli delle autorizzazioni. Se la tua app desidera utilizzare una rete in background, CHANGE_NETWORK_STATE autorizzazione.

Le app con questa autorizzazione consentono al sistema di provare per visualizzare una rete non attiva, come la rete mobile, quando il dispositivo è connesso a una rete Wi-Fi. Un'app del genere chiama ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback) con NetworkCallback da chiamare quando viene visualizzata la rete.