將網路數據用量最佳化

使用智慧型手機的期間,行動數據方案費用很容易超出裝置本身的費用。在 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
顯示「網路政策管理工具」(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 網路設為計量付費,這樣您就能在非計量付費網路上模擬計量付費網路。