將網路數據用量最佳化

使用手機的期間,行動數據方案費用可能會超出裝置本身的費用。在 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() 來判斷應用程式應使用多少數據:

with(getSystemService(ConnectivityManager::class.java)) {
    // 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.
    }
}

注意:在 Android TV 上的運作方式有所不同。Android TV 並不會禁止背景使用數據,只會執行節流。前景應用程式的限制為 800 Kbps,背景應用程式則為 10 Kbps。如要偵測何時應限制 Android TV 上的數據用量,可使用 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>
在傳遞 true 或 false 時,分別啟用或停用數據節省模式。
$ 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 網路設為計量付費,這樣您就能在非計量付費網路上模擬計量付費網路。