讀取網路狀態

Android 系統可讓應用程式瞭解網路連線的動態變化。請使用下列類別來追蹤及回應網路連線改變的情況:

  • ConnectivityManager 會向應用程式告知系統的連線狀態。
  • Network 類別代表 裝置所連接的網路您可以使用 Network 物件做為鍵,以透過 ConnectivityManager 收集網路相關資訊,或繫結網路的通訊端。連上網路後 連線中斷,Network 物件即無法使用。即使之後使用裝置也沒問題 會重新連線到同一設備,新的 Network 物件代表 Kubernetes 環境
  • LinkProperties 物件 包含網路連結的相關資訊,例如 DNS 清單 伺服器、本機 IP 位址和網路路徑
  • NetworkCapabilities 物件包含網路屬性的相關資訊,例如 以及網路支援的連線方式 (Wi-Fi、行動網路、藍牙)。 舉例來說,您可以查詢物件,以判斷網路是否 能夠傳送多媒體訊息、設有網頁認證入口,或為計量付費

如果應用程式希望在任何時間點都能取得即時連線狀態,只要呼叫 ConnectivityManager 方法即可得知可用的網路類型。對於偵錯以及偶爾檢閱 任一特定時間點的可用連線快照

不過,非同步的 ConnectivityManager 方法未向應用程式說明任何狀況 因此無法讓您更新使用者介面,他們也無法調整應用程式 根據網路連線中斷或網路功能的狀況 變更。

網路連線隨時可能改變,大多數應用程式都必須 裝置的最新網路狀態資訊。應用程式可以 向 ConnectivityManager 註冊回呼,讓系統在 使用者在乎的事情應用程式可透過回呼立即回應任何 導致相關網路能力變化,而不需改用昂貴的輪詢作業 以免錯過快速更新

使用 NetworkCallback 和其他來找出 連線狀態不需要任何特定權限, 不過,使用某些網路需具備特定權限。 適用對象 舉例來說,應用程式可能無法在某些受限制的網路下使用。繫結至 背景網路需要CHANGE_NETWORK_STATE權限。還有 呼叫可能需要特定權限才能執行請參閱 來取得詳細資料。

取得即時狀態

Android 裝置可以同時保持多個網路連線。 如要取得目前網路狀態的資訊,請先取得 ConnectivityManager 的執行個體:

Kotlin

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

Java

ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);

接著,透過這個執行個體取得目前預設網路的參照 應用程式:

Kotlin

val currentNetwork = connectivityManager.getActiveNetwork()

Java

Network currentNetwork = connectivityManager.getActiveNetwork();

應用程式可透過對網路的參照,要求取得網路的相關資訊:

Kotlin

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

Java

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

如需更實用的功能,請註冊 NetworkCallback。 如要進一步瞭解如何註冊網路回呼,請參見 監聽網路事件

NetworkCapabilities 和 LinkProperties

NetworkCapabilitiesLinkProperties 物件會提供 系統瞭解的網路屬性

LinkProperties 物件可取得路徑、連結位址、介面名稱、Proxy 資訊 (如果 和 DNS 伺服器對 LinkProperties 物件呼叫相關方法 擷取所需資訊

NetworkCapabilities 物件 封裝網路的「傳輸」及「功能」相關資訊。

傳輸是一種實體媒介的抽象層,而網路會在其上運作。常見的傳輸方式包括乙太網路、Wi-Fi 和行動裝置。 VPN 和點對點 Wi-Fi 也可以做為傳輸方式。 在 Android 裝置上,網路可以同時提供多種傳輸方式。範例 是同時支援 Wi-Fi 和行動網路的 VPNVPN 提供 Wi-Fi、行動裝置和 VPN 傳輸方式。要瞭解 如果有特定傳輸路徑,則請使用 NetworkCapabilities.hasTransport(int)敬上 方法搭配其中一個 NetworkCapabilities.TRANSPORT_* 常數。

功能可描述網路的屬性,例如 MMSNOT_METEREDINTERNET 等功能。支援 MMS 功能的網路 以及接收多媒體訊息服務的訊息和網路 具備 NOT_METERED 功能的網路不會針對 使用者資料。應用程式可使用 NetworkCapabilities.hasCapability(int)敬上 方法搭配其中一個 NetworkCapabilities.NET_CAPABILITY_* 常數。

最實用的 NET_CAPABILITY_* 常數包括:

  • NET_CAPABILITY_INTERNET: 表示網路已設定完成 存取網際網路。這是關於設定的問題,而不是實際的 能力連線至公用伺服器舉例來說,網路可以設為 連上網際網路,但須透過網頁認證入口驗證身分。

    電信業者的行動網路通常具有 INTERNET 功能, 本機 P2P Wi-Fi 網路通常不會這麼做如需實際連線相關說明,請參閱 NET_CAPABILITY_VALIDATED

  • NET_CAPABILITY_NOT_METERED: 表示網路並非計量付費網路 如果使用者對具體用量很敏感,則屬於「計量付費」 連線費用、數據用量限製或電池效能等問題 以負載平衡機制分配流量 即可降低應用程式發生效能問題的風險

  • NET_CAPABILITY_NOT_VPN: 表示網路並非虛擬私人網路。

  • NET_CAPABILITY_VALIDATED: 表示網路會提供 都會在探測器時連線至公開網際網路網路不受到監控的網路 或網路沒有提供網域名稱解析服務, 這項功能這是系統能判斷出最接近網路的網路資訊 雖然經過驗證的網路仍可存取 原則上,就算是按照 IP 進行篩選,還是在 造成連線速度過慢等問題

  • NET_CAPABILITY_CAPTIVE_PORTAL: 表示系統在探測網路時,網路有網頁認證入口。

系統還提供適用於更專門領域應用程式的其他功能。詳情請參閱 NetworkCapabilities.hasCapability(int)

網路的功能可能隨時變動。當系統偵測到網頁認證入口時,會顯示邀請使用者登入的通知。雖然這是 進行中,網路已具備 NET_CAPABILITY_INTERNET NET_CAPABILITY_CAPTIVE_PORTAL 功能,但沒有 NET_CAPABILITY_VALIDATED 功能。

使用者採取行動並登入 進入網頁認證入口頁面後,裝置就能存取公開網際網路 而網路會取得 NET_CAPABILITY_VALIDATED 功能,並失去 NET_CAPABILITY_CAPTIVE_PORTAL 功能。

同樣地,網路的傳輸方式可能會以動態方式變動。 例如,VPN 可以自行重新設定 例如從行動網路改用 Wi-Fi 對基礎網路造成影響在此情況下,網路會失去 TRANSPORT_CELLULAR 移動和取得 TRANSPORT_WIFI 傳輸功能,同時保留 搭乘「TRANSPORT_VPN

監聽網路事件

如要得知網路事件,請將 NetworkCallback 類別與 ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback)ConnectivityManager.registerNetworkCallback(NetworkCallback) 搭配使用。這兩種方法提供的用途不同。

所有 Android 應用程式都有由系統決定的預設網路。 系統通常會偏好使用非計量付費的網路 。

當應用程式發出網路要求時 (例如: HttpsURLConnection、 讓系統使用預設網路來滿足這項要求此外,應用程式也可以透過其他網路傳送流量。如需詳細資訊,請參閱「 網路

在運作期間, 設為預設網路的網路可能隨時變更 應用程式的生命週期典型例子就是裝置的運作範圍 已知、使用中、非計量付費且速度比行動網路更快的 Wi-Fi 存取點。 裝置 會連線至這個存取點,並切換所有 轉移到新的 Wi-Fi 網路。

當新的網路成為預設網路時,應用程式開啟的所有新連線都會使用這個網路。一段時間後,上一個連線的所有剩餘連線 系統會強制終止預設網路如果應用程式必須 一旦預設網路有所變更,它就會註冊預設網路 回呼,如下所示:

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);
    }
});

當新網路成為預設網路時,應用程式會收到針對新網路的 onAvailable(Network) 呼叫。請實作 onCapabilitiesChanged(Network,NetworkCapabilities) 和/或 onLinkPropertiesChanged(Network,LinkProperties),以適當因應連線變更的狀況。

如果是向 registerDefaultNetworkCallback() 註冊的回呼,onLost() 代表網路已失去做為預設網路的狀態,可能會中斷連線。

雖然您可以瞭解預設網路目前採用的傳輸方式 查詢 NetworkCapabilities.hasTransport(int)、 至於網路頻寬或計量付費範圍,這個 Proxy 的效能較差。您的應用程式 無法假設 Wi-Fi 一律為非計量付費方式 相較於行動裝置

請改用 NetworkCapabilities.getLinkDownstreamBandwidthKbps()敬上 測量頻寬 NetworkCapabilites.hasCapability(int)。 同時 NET_CAPABILITY_NOT_METERED 決定計量付費的引數詳情請參閱 NetworkCapabilities 和 LinkProperties

根據預設,系統會透過應用程式的連線執行緒呼叫回呼方法,這類執行緒與 ConnectivityManager 所用的執行緒不同。如果您的 實作回呼需要進行較長的作業, 個別的背景工作執行緒 ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler)

如果您不再需要使用回呼,請呼叫 ConnectivityManager.unregisterNetworkCallback(NetworkCallback) 來取消註冊。建議您透過主要活動的 onPause() 取消註冊,特別是在 onResume() 中註冊回呼的情況。

其他網路

雖然預設網路是大多數應用程式唯一的相關網路,但部分應用程式 應用程式 可能會感興趣的其他可用網路想知道哪些應用程式 建立 NetworkRequest 需求並致電 ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback)

這套程序與監聽預設網路類似,然而 此版本可讓應用程式 應用程式會同時查看所有可用網路,因此呼叫 onLost(Network)敬上 表示網路已中斷連線,不是預設連線

應用程式會建立 NetworkRequest 以通知 ConnectivityManager 要監聽哪種類型的網路。以下範例說明如何建立 NetworkRequest:只對使用非計量付費網路的應用程式 連線:

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);

這表示您的應用程式知道所有關於非計量付費的變更 連線至系統的網路

對於預設網路回呼,會有 registerNetworkCallback(NetworkRequest, NetworkCallback, Handler)敬上 接受 Handler,因此不會載入您的 Connectivity 執行緒 應用程式。

致電 ConnectivityManager.unregisterNetworkCallback(NetworkCallback)敬上 當回呼不再相關時。一個應用程式可以同時註冊多個網路回呼。

為方便起見,NetworkRequest 物件包含多數應用程式需要的常用功能,包括:

編寫應用程式時,請檢查預設設定,確認是否與您的 如果想讓應用程式收到網路相關通知,請清除這些設定 不具備這些功能另一方面, 避免網路發生任何連線變更 使用者就無法與應用程式互動

舉例來說,如果您的應用程式需要傳送多媒體訊息,請在 NET_CAPABILITY_MMS敬上 傳送至NetworkRequest,以避免收到所有無法 傳送多媒體訊息。新增 TRANSPORT_WIFI_AWARE敬上 (如果應用程式只想使用 P2P Wi-Fi 連線)。 「NET_CAPABILITY_INTERNET」和 NET_CAPABILITY_VALIDATED 如果您想透過伺服器傳輸資料,可以使用 網際網路上

回呼順序範例

本節說明如果應用程式可以取得的回呼順序 在已連線的 裝置上,註冊預設回呼和一般回呼 具備行動連線能力。在此範例中,裝置會連線至有效的 Wi-Fi 存取點,然後再中斷連線。本範例也假設 裝置已啟用「行動數據一律開啟」設定。

時間軸如下:

  1. 當應用程式呼叫 registerNetworkCallback() 時,系統會立即回呼 接聽 onAvailable()onNetworkCapabilitiesChanged() 和 行動網路的 onLinkPropertiesChanged(),因為只有行動網路 可以使用網路。如有其他可用網路,應用程式將 也會接收其他網路的回呼。

    此狀態圖表顯示註冊網路回呼事件以及由事件觸發的回呼
    圖1. 呼叫 registerNetworkCallback() 後的應用程式狀態。

  2. 接著,應用程式會呼叫 registerDefaultNetworkCallback()。預設網路 回呼會開始收到對 onAvailable() 的呼叫, onNetworkCapabilitiesChanged(),以及 onLinkPropertiesChanged() 的 行動網路,因為行動網路為預設網路。如果 其他非預設網路啟用時,應用程式無法接收 對非預設網路的呼叫

    此狀態圖表顯示註冊預設網路回呼事件以及
由事件觸發的回呼
    圖2. 註冊預設網路後的應用程式狀態。

  3. 稍後,裝置會連線至 (非計量付費) Wi-Fi 網路。一般網路回呼會收到針對 Wi-Fi 網路的 onAvailable()onNetworkCapabilitiesChanged()onLinkPropertiesChanged() 呼叫。

    此狀態圖表顯示應用程式連線至新的網路時觸發的回呼
    圖3.連線至非計量付費 Wi-Fi 網路後的應用程式狀態。

  4. 這時 Wi-Fi 網路可能需要一些時間進行驗證。於 本例中,onNetworkCapabilitiesChanged() 會呼叫一般網路 回呼不含 NET_CAPABILITY_VALIDATED 功能。執行 短時間,系統就會呼叫 onNetworkCapabilitiesChanged(),而 新功能包括 NET_CAPABILITY_VALIDATED在多數情況下,驗證作業非常快速。

    Wi-Fi 網路通過驗證後,系統會偏好使用 Wi-Fi 網路而非行動網路 主要原因為非計量付費網路Wi-Fi 網路會成為預設網路,因此預設網路回呼會收到針對 Wi-Fi 網路的 onAvailable()onNetworkCapabilitiesChanged()onLinkPropertiesChanged() 呼叫。行動網路採用 而一般網路回呼會收到 行動網路的「onLosing()」。

    由於本範例假設此裝置的行動數據一律處於開啟狀態,因此行動網路連線不會中斷。如果關閉這項設定 行動網路連線中斷時,以及一般網路回呼 會收到對 onLost() 的呼叫。

    此狀態圖表顯示 Wi-Fi 網路連線通過驗證時觸發的回呼
    圖4. Wi-Fi 網路通過驗證後的應用程式狀態。

  5. 後來,由於裝置離開連線範圍,因此 Wi-Fi 連線突然中斷。因為 Wi-Fi 連線中斷,一般網路回呼 收到 撥打 onLost() 連上 Wi-Fi。行動裝置是新的預設網路 預設網路回呼會收到對 onAvailable() 的呼叫。 onNetworkCapabilitiesChanged(),以及 onLinkPropertiesChanged() 的 行動網路。

    此狀態圖表顯示 Wi-Fi 網路連線中斷時觸發的回呼
    圖5.Wi-Fi 網路連線中斷後的應用程式狀態。

如果「行動數據一律開啟」設定關閉,則裝置連上 Wi-Fi 時 中斷連線時,裝置會嘗試重新連上行動網路。圖片是 類似,但 onAvailable() 呼叫會有短暫延遲。 一般網路回呼也會接收對 onAvailable() 的呼叫。 onNetworkCapabilitiesChanged()onLinkPropertiesChanged(),因為 還有行動裝置。

網路資料傳輸的使用限制

能透過網路回呼看到網路,不代表應用程式可以 透過網路傳輸資料部分網路不提供網際網路 且部分網路可能會 具有特殊權限的應用程式如要檢查網際網路連線,請參閱 NET_CAPABILITY_INTERNET敬上 和 NET_CAPABILITY_VALIDATED

此外,使用背景網路也必須通過權限檢查。如果您的應用程式 想要使用背景網路,需要 CHANGE_NETWORK_STATE敬上 權限。

具備這項權限的應用程式可讓系統嘗試 啟動未啟用的網路,例如行動網路 裝置連線 Wi-Fi 網路時。這類應用程式呼叫 ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback)敬上 以及要在網路啟動時呼叫的 NetworkCallback