ネットワーク データ使用量を最適化する

スマートフォンのライフサイクル全体では、モバイルデータ通信プランのコストがデバイス自体のコストを簡単に上回ります。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() を使用します。

データ制限の権限をリクエストする

アプリがバックグラウンドでデータを使用する必要がある場合は、アプリのパッケージ名の URI を含む Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS インテントを送信することで、データ制限の権限をリクエストできます(例: 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 を従量制に設定し、定額制ネットワークで従量制ネットワークをシミュレートできるようにします。