網路數據用量最佳化

使用智慧型手機的期間,行動數據方案費用很容易超出裝置本身的成本。在 Android 7.0 (API 級別 24) 以上版本中,使用者可以啟用裝置中的數據節省模式,藉此達到最佳化,並減少數據用量。這種模式對帳單週期結束時的漫遊用量,或是小型預付數據方案特別有效。

使用者在「設定」中啟用數據節省模式,且使用計量付費網路時,系統會阻斷背景數據使用和訊號,並盡可能減少應用程式在前景使用的數據量。即使啟用數據節省模式,使用者依舊能允許特定應用程式的背景計量數據用量。

Android 7.0 (API 級別 24) 透過擷取數據節省模式的使用者偏好設定,並監控偏好設定的變更,擴充了ConnectivityManager API 來提供應用程式。讓應用程式查看是否啟用數據節省模式,並盡力限制前景和背景數據的用量,這是相當不錯的做法。

查看數據節省模式偏好設定

在 Android 7.0 (API 級別 24) 以上版本中,應用程式可以使用 ConnectivityManager API,決定要執行的數據用量限制。使用 getRestrictBackgroundStatus() 方法時,下列其中一個值會傳回:

RESTRICT_BACKGROUND_STATUS_DISABLED
數據節省模式已停用。
RESTRICT_BACKGROUND_STATUS_ENABLED
使用者已啟用數據節省模式,並限制該應用程式的數據用量。應用程式應盡量減少前景數據用量,並妥善處理背景數據用量的限制。
RESTRICT_BACKGROUND_STATUS_WHITELISTED
使用者已啟用數據節省模式,該應用程式不受此限。但仍須盡量限制前景和背景的數據用量。

即使停用數據節省模式或應用程式不受此限,裝置使用計量付費網路時,須限制數據用量。以下為程式碼範例,說明如何使用 ConnectivityManager.isActiveNetworkMetered()ConnectivityManager.getRestrictBackgroundStatus() 來判斷應用程式應使用多少數據:

Kotlin

(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {
    // Checks if the device is on a metered network
    if (isActiveNetworkMetered) {
        // Checks user’s Data Saver settings.
        when (restrictBackgroundStatus) {
            RESTRICT_BACKGROUND_STATUS_ENABLED -> {
                // Background data usage is blocked for this app. Wherever possible,
                // the app should also use less data in the foreground.
            }
            RESTRICT_BACKGROUND_STATUS_WHITELISTED -> {
                // The app is allowed to bypass Data Saver. Nevertheless, wherever possible,
                // the app should use less data in the foreground and background.
            }
            RESTRICT_BACKGROUND_STATUS_DISABLED -> {
                // Data Saver is disabled. Since the device is connected to a
                // metered network, the app should use less data wherever possible.
            }
        }
    } else {
        // The device is not on a metered network.
        // Use data as required to perform syncs, downloads, and updates.
    }
}

Java

ConnectivityManager connMgr = (ConnectivityManager)
        getSystemService(Context.CONNECTIVITY_SERVICE);
// Checks if the device is on a metered network
if (connMgr.isActiveNetworkMetered()) {
  // Checks user’s Data Saver settings.
  switch (connMgr.getRestrictBackgroundStatus()) {
    case RESTRICT_BACKGROUND_STATUS_ENABLED:
    // Background data usage is blocked for this app. Wherever possible,
    // the app should also use less data in the foreground.

    case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
    // The app is allowed to bypass Data Saver. Nevertheless, wherever possible,
    // the app should use less data in the foreground and background.

    case RESTRICT_BACKGROUND_STATUS_DISABLED:
    // Data Saver is disabled. Since the device is connected to a
    // metered network, the app should use less data wherever possible.
  }
} else {
  // The device is not on a metered network.
  // Use data as required to perform syncs, downloads, and updates.
}

注意:Android TV 運作方式有所不同。Android TV 並不會禁止背景使用數據,而是會限制用量。前景應用程式用量限制為 800 Kbps,背景應用程式限制為 10 Kbps。如要偵測何時應限制電視數據用量,可使用 ConnectivityManager.isActiveNetworkMetered()

要求數據限制權限

如果應用程式需要在背景使用數據,可以傳送 Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS 意圖,內容包含該應用程式套件名稱的 URI,藉此要求數據限制權限,例如:package:MY_APP_ID

傳送意圖和 URI 會啟動「設定」應用程式,並顯示應用程式的數據用量設定。使用者依此決定是否授權,讓應用程式使用背景數據。較為妥當的做法是在傳送意圖前,先詢問使用者是否要啟動「設定」

監控數據節省模式的偏好設定變更

應用程式透過建立 BroadcastReceiver 來監聽 ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED,並使用 Context.registerReceiver() 進行接收器的動態記錄,從而監控數據節省模式的變更。收到這個廣播時,應用程式就會呼叫 ConnectivityManager.getRestrictBackgroundStatus()檢查新的數據節省模式偏好設定是否會影響其權限

注意:廣播只會傳送給 Context.registerReceiver() 動態記錄的應用程式。數據使用不受影響的應用程式不會收到這個廣播。

使用 Android Debug Bridge 指令進行測試

在數據節省模式條件下,Android Debug Bridge (ADB) 提供幾個測試應用程式的指令。您可以檢查並設定網路權限,或將無線網路設為計量付費,如此便能在非計量付費的環境中測試應用程式。

$ adb shell dumpsys netpolicy
會產生報表,內容包括目前全球背景網路限制設定、目前不受數據節省模式影響的套件 UID,以及其他已知套件的網路權限。
$ adb shell cmd netpolicy
會顯示 Network Policy Manager (netpolicy) 完整的指令清單。
$ adb shell cmd netpolicy set restrict-background <boolean>
在分別傳遞 truefalse 時,啟用或停用數據節省模式。
$ adb shell cmd netpolicy add restrict-background-whitelist <UID>
將指定套件 UID 加入許可清單 (whitelist),允許使用其背景計量付費數據。
$ adb shell cmd netpolicy remove restrict-background-whitelist <UID>
將指定套件 UID 從許可清單 (whitelist) 中移除,從而在啟用數據節省模式時,封鎖其背景計量付費數據的使用。
$ adb shell cmd netpolicy list wifi-networks
列出所有 Wi-Fi,顯示是否為計量付費網路。
$ adb shell cmd netpolicy set metered-network <WIFI_SSID> true
將指定 SSID 的 Wi-Fi 網路設為計量付費,這樣即可用非計量付費的網路,模擬使用計量付費網路的情境。