Android ermöglicht es Apps, dynamische Änderungen der Konnektivität zu erkennen. Verwende die folgenden Klassen, um Verbindungsänderungen zu verfolgen und darauf zu reagieren:
ConnectivityManager
informiert Ihre App über den Verbindungsstatus im System.- Die Klasse
Network
stellt eines der Netzwerke dar, mit denen das Gerät verbunden ist. Sie können dasNetwork
-Objekt als Schlüssel verwenden, um mitConnectivityManager
Informationen zum Netzwerk zu erfassen oder Sockets im Netzwerk zu binden. Wenn die Netzwerkverbindung getrennt wird, kann dasNetwork
-Objekt nicht mehr verwendet werden. Auch wenn das Gerät später wieder mit demselben Gerät verbunden wird, wird das neue Netzwerk durch ein neuesNetwork
-Objekt dargestellt. - Das Objekt
LinkProperties
enthält Informationen zum Link für ein Netzwerk, z. B. die Liste der DNS-Server, lokalen IP-Adressen und Netzwerkrouten, die für das Netzwerk installiert sind. - Das Objekt
NetworkCapabilities
enthält Informationen zu den Eigenschaften eines Netzwerks, z. B. zu den Übertragungsmethoden (WLAN, Mobilfunk, Bluetooth) und zu den Möglichkeiten des Netzwerks. Sie können das Objekt beispielsweise abfragen, um festzustellen, ob das Netzwerk MMS senden kann, sich hinter einem Captive Portal befindet oder getaktet ist.
Apps, die den aktuellen Verbindungsstatus jederzeit abrufen möchten, können ConnectivityManager
-Methoden aufrufen, um herauszufinden, welche Art von Netzwerk verfügbar ist. Diese Methoden sind hilfreich für das Debuggen und um gelegentlich einen aktuellen Snapshot der Verfügbarkeit der Verbindung zu überprüfen.
Die synchronen ConnectivityManager
-Methoden informieren Ihre App jedoch nicht über Ereignisse nach einem Aufruf, sodass Sie Ihre Benutzeroberfläche nicht aktualisieren können. Außerdem können sie das App-Verhalten nicht an die Netzwerkverbindung anpassen oder die Netzwerkfunktionen ändern.
Die Konnektivität kann sich jederzeit ändern und die meisten Apps benötigen einen aktuellen Überblick über den Netzwerkstatus des Geräts. Apps können bei ConnectivityManager
einen Rückruf registrieren, um über Änderungen informiert zu werden, die für die App relevant sind. Mit dem Rückruf kann Ihre App sofort auf jede relevante Änderung der Verbindung reagieren, ohne auf teures Polling zurückgreifen zu müssen, bei dem schnelle Updates möglicherweise verpasst werden.
Für die Verwendung von NetworkCallback
und anderen Möglichkeiten, den Verbindungsstatus des Geräts zu ermitteln, ist keine bestimmte Berechtigung erforderlich.
Für einige Netzwerke gelten jedoch bestimmte Berechtigungen.
Es kann beispielsweise eingeschränkte Netzwerke geben, die für Apps nicht verfügbar sind. Für die Bindung an ein Hintergrundnetzwerk ist die Berechtigung CHANGE_NETWORK_STATE
erforderlich. Für einige Aufrufe sind möglicherweise bestimmte Berechtigungen erforderlich. Weitere Informationen finden Sie in der jeweiligen Dokumentation zu den einzelnen Aufrufen.
Instantanen Status abrufen
Ein Android-Gerät kann viele Verbindungen gleichzeitig aufrechterhalten.
Wenn Sie Informationen zum aktuellen Netzwerkstatus abrufen möchten, müssen Sie zuerst eine Instanz von ConnectivityManager
abrufen:
Kotlin
val connectivityManager = getSystemService(ConnectivityManager::class.java)
Java
ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);
Verwenden Sie diese Instanz als Nächstes, um einen Verweis auf das aktuelle Standardnetzwerk für Ihre App abzurufen:
Kotlin
val currentNetwork = connectivityManager.getActiveNetwork()
Java
Network currentNetwork = connectivityManager.getActiveNetwork();
Mit einer Verweis auf ein Netzwerk kann Ihre App Informationen dazu anfordern:
Kotlin
val caps = connectivityManager.getNetworkCapabilities(currentNetwork) val linkProperties = connectivityManager.getLinkProperties(currentNetwork)
Java
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(currentNetwork); LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);
Wenn Sie weitere nützliche Funktionen nutzen möchten, registrieren Sie eine NetworkCallback
.
Weitere Informationen zum Registrieren von Netzwerk-Callbacks findest du unter Netzwerkereignisse abhören.
NetworkCapabilities und LinkProperties
Die Objekte NetworkCapabilities
und LinkProperties
enthalten Informationen zu allen Attributen, die dem System zu einem Netzwerk bekannt sind.
Das LinkProperties
-Objekt kennt die Routen, Linkadressen, den Namen der Schnittstelle, Proxy-Informationen (falls vorhanden) und DNS-Server. Rufen Sie die entsprechende Methode für das LinkProperties
-Objekt auf, um die benötigten Informationen abzurufen.
Das NetworkCapabilities
-Objekt enthält Informationen zu den Netzwerktransporten und ihren Funktionen.
Ein Transport ist eine Abstraktion eines physischen Mediums, über das ein Netzwerk betrieben wird. Gängige Beispiele für Transportschichten sind Ethernet, WLAN und Mobilgeräte.
Auch VPNs und Peer-to-Peer-WLAN können als Transportschicht verwendet werden.
Unter Android kann ein Netzwerk mehrere Transporte gleichzeitig haben. Ein Beispiel hierfür ist ein VPN, das sowohl über WLAN als auch über Mobilfunknetze funktioniert. Das VPN hat die Transportschichten WLAN, Mobilfunk und VPN. Wenn Sie wissen möchten, ob ein Netzwerk einen bestimmten Transport hat, verwenden Sie die Methode NetworkCapabilities.hasTransport(int)
mit einer der NetworkCapabilities.TRANSPORT_*
-Konstanten.
Eine Funktion beschreibt eine Eigenschaft des Netzwerks. Beispiele für Funktionen sind MMS
, NOT_METERED
und INTERNET
. Ein Netzwerk mit MMS-Funktion kann MMS-Nachrichten senden und empfangen, ein Netzwerk ohne diese Funktion nicht. Bei einem Netzwerk mit der Funktion NOT_METERED
werden dem Nutzer keine Daten in Rechnung gestellt. Ihre App kann mithilfe der Methode NetworkCapabilities.hasCapability(int)
und einer der NetworkCapabilities.NET_CAPABILITY_*
-Konstanten nach geeigneten Funktionen suchen.
Zu den nützlichsten NET_CAPABILITY_*
-Konstanten gehören:
NET_CAPABILITY_INTERNET
: Gibt an, dass das Netzwerk für den Zugriff auf das Internet eingerichtet ist. Es geht hier um die Einrichtung und nicht um die tatsächliche Möglichkeit, öffentliche Server zu erreichen. Ein Netzwerk kann beispielsweise so eingerichtet werden, dass es auf das Internet zugreifen kann, aber einem Captive Portal unterliegt.Das Mobilfunknetz eines Mobilfunkanbieters unterstützt in der Regel die
INTERNET
-Funktion, während dies bei einem lokalen P2P-WLAN in der Regel nicht der Fall ist. Informationen zur tatsächlichen Konnektivität finden Sie unterNET_CAPABILITY_VALIDATED
.NET_CAPABILITY_NOT_METERED
: gibt an, dass das Netzwerk nicht bewirtschaftet wird. Ein Netzwerk wird als getaktet eingestuft, wenn der Nutzer aufgrund von Kosten, Datenbeschränkungen oder Akkuleistungsproblemen empfindlich auf eine hohe Datennutzung über diese Verbindung reagiert.NET_CAPABILITY_NOT_VPN
: gibt an, dass es sich nicht um ein virtuelles privates Netzwerk handelt.NET_CAPABILITY_VALIDATED
: Gibt an, dass das Netzwerk bei der Prüfung tatsächlich Zugriff auf das öffentliche Internet bietet. Ein Netzwerk hinter einem Captive Portal oder ein Netzwerk, das keine Domainnamensauflösung bietet, bietet diese Funktion nicht. Das ist das Beste, was das System über ein Netzwerk sagen kann, das tatsächlich Zugriff gewährt. Ein validiertes Netzwerk kann jedoch grundsätzlich IP-basierter Filterung unterliegen oder aufgrund von Problemen wie einem schlechten Signal plötzlich die Verbindung verlieren.NET_CAPABILITY_CAPTIVE_PORTAL
: Gibt an, dass das Netzwerk ein Captive Portal hat, wenn es geprüft wird.
Es gibt noch weitere Funktionen, die für spezialisiertere Apps interessant sein könnten.
Weitere Informationen finden Sie in den Parameterdefinitionen unter NetworkCapabilities.hasCapability(int)
.
Die Funktionen eines Netzwerks können sich jederzeit ändern. Wenn das System ein Captive Portal erkennt, wird eine Benachrichtigung angezeigt, in der der Nutzer aufgefordert wird, sich anzumelden. Während dieser Vorgang läuft, bietet das Netzwerk die Funktionen NET_CAPABILITY_INTERNET
und NET_CAPABILITY_CAPTIVE_PORTAL
, aber nicht die Funktion NET_CAPABILITY_VALIDATED
.
Wenn der Nutzer eine Aktion ausführt und sich auf der Seite des Captive Portals anmeldet, kann das Gerät auf das öffentliche Internet zugreifen. Das Netzwerk erhält die NET_CAPABILITY_VALIDATED
-Funktion und verliert die NET_CAPABILITY_CAPTIVE_PORTAL
-Funktion.
Ebenso können sich die Übertragungen eines Netzwerks dynamisch ändern.
Ein VPN kann sich beispielsweise so neu konfigurieren, dass ein schnelleres Netzwerk verwendet wird, das gerade verfügbar geworden ist, z. B. vom Mobilfunknetz zu WLAN. In diesem Fall verliert das Netzwerk den TRANSPORT_CELLULAR
-Transport und erhält den TRANSPORT_WIFI
-Transport, während der TRANSPORT_VPN
-Transport beibehalten wird.
Auf Netzwerkereignisse warten
Informationen zu Netzwerkereignissen erhalten Sie mit der Klasse NetworkCallback
zusammen mit ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback)
und ConnectivityManager.registerNetworkCallback(NetworkCallback)
. Diese beiden Methoden dienen unterschiedlichen Zwecken.
Alle Android-Apps haben ein Standardnetzwerk, das vom System festgelegt wird. Das System bevorzugt in der Regel unbegrenzte Netzwerke gegenüber solchen mit begrenztem Datenvolumen und schnellere Netzwerke gegenüber langsameren.
Wenn eine App eine Netzwerkanfrage stellt, z. B. mit HttpsURLConnection
, erfüllt das System diese Anfrage über das Standardnetzwerk. Apps können auch Traffic über andere Netzwerke senden. Weitere Informationen finden Sie im Abschnitt zu zusätzlichen Netzwerken.
Das als Standardnetzwerk festgelegte Netzwerk kann sich während der Lebensdauer einer App jederzeit ändern. Ein typisches Beispiel ist, wenn sich das Gerät in Reichweite eines bekannten, aktiven, unbegrenzten und schnelleren WLAN-Zugangspunktes befindet. Das Gerät verbindet sich mit diesem Zugangspunkt und wechselt das Standardnetzwerk für alle Apps zum neuen WLAN.
Wenn ein neues Netzwerk als Standard festgelegt wird, wird für jede neue Verbindung, die die App öffnet, dieses Netzwerk verwendet. Später werden alle verbleibenden Verbindungen zum vorherigen Standardnetzwerk erzwungen beendet. Wenn es für die App wichtig ist zu wissen, wann sich das Standardnetzwerk ändert, registriert sie einen Standardnetzwerk-Callback so:
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); } });
Wenn ein neues Netzwerk zum Standardnetzwerk wird, erhält die App einen Aufruf zu onAvailable(Network)
für das neue Netzwerk. Implementiere onCapabilitiesChanged(Network,NetworkCapabilities)
, onLinkPropertiesChanged(Network,LinkProperties)
oder beides, um angemessen auf Änderungen der Konnektivität zu reagieren.
Bei einem mit registerDefaultNetworkCallback()
registrierten Callback bedeutet onLost()
, dass das Netzwerk nicht mehr das Standardnetzwerk ist. Möglicherweise ist die Verbindung getrennt.
Sie können zwar durch Abfragen von NetworkCapabilities.hasTransport(int)
Informationen zu den Transporten erhalten, die vom Standardnetzwerk verwendet werden, dies ist jedoch kein guter Proxy für die Bandbreite oder die Begrenzung des Netzwerks. Ihre App darf nicht davon ausgehen, dass WLAN immer unbegrenzt und immer eine bessere Bandbreite bietet als Mobilfunk.
Verwenden Sie stattdessen NetworkCapabilities.getLinkDownstreamBandwidthKbps()
, um die Bandbreite zu messen, und NetworkCapabilites.hasCapability(int)
mit den Argumenten NET_CAPABILITY_NOT_METERED
, um die Begrenzung zu bestimmen. Weitere Informationen finden Sie im Abschnitt zu NetworkCapabilities und LinkProperties.
Standardmäßig werden die Rückrufmethoden im Verbindungs-Thread Ihrer App aufgerufen. Dies ist ein separater Thread, der von ConnectivityManager
verwendet wird. Wenn bei der Implementierung der Rückrufe längere Aufgaben ausgeführt werden müssen, rufen Sie sie mit der Variante ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler)
in einem separaten Worker-Thread auf.
Wenn Sie den Callback nicht mehr benötigen, können Sie ihn ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
aufheben.
Der onPause()
Ihrer Hauptaktivität eignet sich gut dafür, insbesondere wenn Sie den Callback in onResume()
registrieren.
Zusätzliche Netzwerke
Das Standardnetzwerk ist zwar für die meisten Apps das einzige relevante Netzwerk, für einige Apps sind jedoch möglicherweise andere verfügbare Netzwerke interessant. Um diese Informationen zu erhalten, erstellen Apps eine NetworkRequest
, die ihren Anforderungen entspricht, und rufen ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback)
auf.
Der Vorgang ähnelt dem Abhören eines Standardnetzwerks. Auch wenn es für eine App jeweils nur ein Standardnetzwerk geben kann, kann diese Version alle verfügbaren Netzwerke gleichzeitig sehen. Ein Aufruf von onLost(Network)
bedeutet also, dass die Verbindung zum Netzwerk endgültig getrennt wurde, nicht, dass es nicht mehr das Standardnetzwerk ist.
Die App erstellt eine NetworkRequest
, um ConnectivityManager
darüber zu informieren, welche Art von Netzwerken sie hören möchte. Das folgende Beispiel zeigt, wie Sie eine NetworkRequest
für eine App erstellen, die nur an unbegrenzten Internetverbindungen interessiert ist:
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);
Das bedeutet, dass Ihre App über alle Änderungen informiert wird, die sich auf ein unbegrenztes Netzwerk auf dem System beziehen.
Wie beim standardmäßigen Netzwerk-Callback gibt es eine Version von registerNetworkCallback(NetworkRequest, NetworkCallback, Handler)
, die einen Handler
akzeptiert, sodass der Connectivity
-Thread Ihrer App nicht geladen wird.
Rufen Sie ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
an, wenn der Rückruf nicht mehr relevant ist. Eine App kann mehrere Netzwerk-Callbacks gleichzeitig registrieren.
Das NetworkRequest
-Objekt enthält die gängigen Funktionen, die die meisten Apps benötigen, darunter:
Prüfen Sie beim Erstellen Ihrer App, ob die Standardeinstellungen zu Ihrem Anwendungsfall passen. Löschen Sie sie, wenn Ihre App über Netzwerke informiert werden soll, die diese Funktionen nicht haben. Fügen Sie andererseits Funktionen hinzu, um zu vermeiden, dass bei jeder Netzwerkverbindungsänderung in Netzwerken, mit denen Ihre App nicht interagiert, eine Benachrichtigung gesendet wird.
Wenn Ihre App beispielsweise MMS-Nachrichten senden muss, fügen Sie NetworkRequest
die Zeichenfolge NET_CAPABILITY_MMS
hinzu, damit Sie nicht über alle Netzwerke informiert werden, über die keine MMS-Nachrichten gesendet werden können. Fügen Sie TRANSPORT_WIFI_AWARE
hinzu, wenn Ihre App nur eine P2P-WLAN-Verbindung benötigt.
NET_CAPABILITY_INTERNET
und NET_CAPABILITY_VALIDATED
sind hilfreich, wenn Sie Daten mit einem Server im Internet übertragen möchten.
Beispiel für eine Rückrufsequenz
In diesem Abschnitt wird die Abfolge der Callbacks beschrieben, die eine App erhalten kann, wenn sie sowohl einen Standard- als auch einen regulären Callback auf einem Gerät registriert, das eine mobile Verbindung hat. In diesem Beispiel verbindet sich das Gerät mit einem guten WLAN-Zugangspunkt und trennt sich dann wieder von ihm. Außerdem wird davon ausgegangen, dass auf dem Gerät die Einstellung Mobile Datennutzung immer aktiviert aktiviert ist.
Die Zeitleiste sieht so aus:
Wenn die App
registerNetworkCallback()
anruft, erhält der Rückruf sofort Anrufe vononAvailable()
,onNetworkCapabilitiesChanged()
undonLinkPropertiesChanged()
für das Mobilfunknetz, da nur dieses verfügbar ist. Wenn ein anderes Netzwerk verfügbar ist, erhält die App auch Rückrufe für das andere Netzwerk.
Abbildung 1: App-Status nach dem Aufruf vonregisterNetworkCallback()
.Anschließend ruft die App
registerDefaultNetworkCallback()
auf. Der Standardnetzwerk-Callback empfängt Anrufe anonAvailable()
,onNetworkCapabilitiesChanged()
undonLinkPropertiesChanged()
für das Mobilfunknetz, da das Mobilfunknetz das Standardnetzwerk ist. Wenn ein anderes, nicht standardmäßiges Netzwerk aktiv ist, kann die App keine Anrufe für das nicht standardmäßige Netzwerk empfangen.
Abbildung 2: App-Status nach der Registrierung eines StandardnetzwerksSpäter stellt das Gerät eine Verbindung zu einem (nicht befristeten) WLAN her. Der normale Netzwerk-Callback empfängt Anrufe an
onAvailable()
,onNetworkCapabilitiesChanged()
undonLinkPropertiesChanged()
für das WLAN.
Abbildung 3: App-Status nach der Verbindung mit einem unbegrenzten WLAN.Es kann einige Zeit dauern, bis das WLAN bestätigt wird. In diesem Fall enthalten die
onNetworkCapabilitiesChanged()
-Aufrufe für den regulären Netzwerk-Callback nicht die FunktionNET_CAPABILITY_VALIDATED
. Nach kurzer Zeit erhält es einen Aufruf anonNetworkCapabilitiesChanged()
, bei demNET_CAPABILITY_VALIDATED
zu den neuen Funktionen gehört. In den meisten Fällen ist die Überprüfung sehr schnell abgeschlossen.Wenn das WLAN-Netzwerk validiert wird, wird es vom System dem Mobilfunknetz vorgezogen, hauptsächlich weil es unbegrenzt nutzbar ist. Das WLAN wird zum Standardnetzwerk. Daher erhält der Rückruf des Standardnetzwerks einen Aufruf an
onAvailable()
,onNetworkCapabilitiesChanged()
undonLinkPropertiesChanged()
für das WLAN. Das Mobilfunknetz wird in den Hintergrund verschoben und der normale Netzwerk-Callback erhält einen Aufruf zuonLosing()
für das Mobilfunknetz.Da in diesem Beispiel davon ausgegangen wird, dass die mobilen Daten für dieses Gerät immer aktiviert sind, wird die Verbindung zum Mobilfunknetz nie getrennt. Wenn die Einstellung deaktiviert ist, wird die Verbindung zum Mobilfunknetz nach einiger Zeit getrennt und der reguläre Netzwerk-Callback erhält einen Anruf an
onLost()
.
Abbildung 4: App-Status nach der Validierung des WLANsSpäter wird die Verbindung des Geräts zum WLAN plötzlich getrennt, weil es sich außerhalb der Reichweite befindet. Da die WLAN-Verbindung getrennt wird, erhält der normale Netzwerk-Callback einen Aufruf an
onLost()
für das WLAN. Da das Mobilfunknetz das neue Standardnetzwerk ist, erhält der Standardnetzwerk-Callback Anrufe anonAvailable()
,onNetworkCapabilitiesChanged()
undonLinkPropertiesChanged()
für das Mobilfunknetz.
Abbildung 5: App-Status nach dem Trennen der WLAN-Verbindung
Wenn die Einstellung Mobile Daten immer aktiviert deaktiviert ist, versucht das Gerät nach einer WLAN-Trennung, sich wieder mit einem Mobilfunknetz zu verbinden. Das Bild ist ähnlich, aber mit einer kurzen zusätzlichen Verzögerung für die onAvailable()
-Anrufe. Der reguläre Netzwerk-Callback empfängt auch Anrufe an onAvailable()
, onNetworkCapabilitiesChanged()
und onLinkPropertiesChanged()
, da das Mobilfunknetz verfügbar ist.
Einschränkungen bei der Nutzung des Netzwerks für die Datenübertragung
Wenn Sie ein Netzwerk mit einem Netzwerk-Callback sehen können, bedeutet das nicht, dass Ihre App das Netzwerk für die Datenübertragung verwenden kann. Einige Netzwerke bieten keine Internetverbindung und andere sind möglicherweise auf privilegierte Apps beschränkt. Informationen zum Prüfen der Internetverbindung findest du unter NET_CAPABILITY_INTERNET
und NET_CAPABILITY_VALIDATED
.
Die Nutzung von Hintergrundnetzwerken unterliegt ebenfalls Berechtigungsprüfungen. Wenn Ihre App ein Hintergrundnetzwerk verwenden soll, benötigt sie die Berechtigung CHANGE_NETWORK_STATE
.
Apps mit dieser Berechtigung können versuchen, ein nicht verfügbares Netzwerk zu starten, z. B. das Mobilfunknetz, wenn das Gerät mit einem WLAN verbunden ist. Eine solche App ruft ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback)
mit einer NetworkCallback
auf, die aufgerufen werden soll, wenn das Netzwerk gestartet wird.