インターネット接続のための Wi-Fi サジェスチョン API

Android 10(API レベル 29)以降を搭載したデバイスでは、Wi-Fi アクセス ポイントに自動接続するためのネットワーク認証情報をアプリで追加できます。WifiNetworkSuggestion を使用すると、接続するネットワークの候補を指定できます。プラットフォームは、アプリとその他の入力に基づいて、受け入れるアクセス ポイントを選択します。

Android 11(API レベル 30)以降:

  • PasspointConfiguration のプロビジョニングは、Suggestion API でサポートされています。Android 11 より前では、PasspointConfiguration をプロビジョニングするには addOrUpdatePasspointConfiguration() API を使用する必要があります。
  • フレームワークは、TLS ベースのエンタープライズの提案(EAP-TLS、EAP-TTLS、EAP-PEAP)にセキュリティ要件を適用します。このようなネットワークに対する提案では、Root CA certificateserver domain name を設定する必要があります。
  • フレームワークは、EAP-SIM ベースのエンタープライズの提案(EAP-SIM、EAP-AKA、EAP-AKA-PRIME)の所有権要件を適用します。このような提案は、携帯通信会社によって署名されたアプリのみが許可します。
  • 携帯通信会社によって署名されたアプリから提案された場合、フレームワークは、アプリの携帯通信会社署名に対応する携帯通信会社 ID を自動的に割り当てます。このような候補は、対応する SIM がデバイスから削除されると自動的に無効になります。

Android 12(API レベル 31)以降:

  • ランダム化された MAC アドレスを定期的に再ランダム化する非永続的 MAC ランダム化により、プライバシーをさらに有効にできます。setMacRandomizationSetting を使用して、ネットワークのランダム化レベルを指定します。

  • isPasspointTermsAndConditionsSupported(): 利用規約Passpoint 機能であり、ネットワーク デプロイにおいて、オープン ネットワークを使用する安全でないキャプティブ ポータルを安全な Passpoint ネットワークに置き換えることができます。利用規約への同意が必要な場合は、通知が表示されます。利用規約によって制限される Passpoint ネットワークを提案するアプリでは、まずこの API を呼び出して、デバイスが機能をサポートしていることを確認する必要があります。デバイスが機能をサポートしていない場合、このネットワークには接続できず、代替ネットワークまたはレガシー ネットワークを提案する必要があります。

  • isDecoratedIdentitySupported(): プレフィックス装飾でネットワークの認証を行う場合、装飾された ID プレフィックスにより、ネットワーク事業者はネットワーク アクセス識別子(NAI)を更新して、AAA ネットワーク内の複数のプロキシを経由して明示的なルーティングを行えます(詳細については RFC 7542 をご覧ください)。

    Android 12 では、PPS-MO 拡張の WBA 仕様に適合するようにこの機能が実装されています。装飾された ID を必要とする Passpoint ネットワークを提案するアプリでは、まずこの API を呼び出して、デバイスが機能をサポートしていることを確認する必要があります。デバイスが機能をサポートしていない場合、ID が装飾されず、ネットワークの認証が失敗する可能性があります。

Passpoint の提案を作成するには、アプリで PasspointConfigurationCredentialHomeSp クラスを使用する必要があります。これらのクラスは、Wi-Fi Alliance Passpoint 仕様で定義されている Passpoint プロファイルを記述します。

次のコードサンプルは、1 つのオープン ネットワーク、1 つの WPA2、1 つの WPA3 ネットワーク、1 つの Passpoint ネットワークに対して認証情報を提供する方法を示しています。

Kotlin

val suggestion1 = WifiNetworkSuggestion.Builder()
        .setSsid("test111111")
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val suggestion2 = WifiNetworkSuggestion.Builder()
        .setSsid("test222222")
        .setWpa2Passphrase("test123456")
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val suggestion3 = WifiNetworkSuggestion.Builder()
        .setSsid("test333333")
        .setWpa3Passphrase("test6789")
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val passpointConfig = PasspointConfiguration(); // configure passpointConfig to include a valid Passpoint configuration
val suggestion4 = WifiNetworkSuggestion.Builder()
        .setPasspointConfig(passpointConfig)
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val suggestionsList = listOf(suggestion1, suggestion2, suggestion3, suggestion4);

val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager;

val status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
    // do error handling here
}

// Optional (Wait for post connection broadcast to one of your suggestions)
val intentFilter = IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

val broadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
            return;
        }
        // do post connect processing here
    }
};
context.registerReceiver(broadcastReceiver, intentFilter);

Java

final WifiNetworkSuggestion suggestion1 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test111111")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final WifiNetworkSuggestion suggestion2 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test222222")
  .setWpa2Passphrase("test123456")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final WifiNetworkSuggestion suggestion3 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test333333")
  .setWpa3Passphrase("test6789")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final PasspointConfiguration passpointConfig = new PasspointConfiguration();
// configure passpointConfig to include a valid Passpoint configuration

final WifiNetworkSuggestion suggestion4 =
  new WifiNetworkSuggestion.Builder()
  .setPasspointConfig(passpointConfig)
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final List<WifiNetworkSuggestion> suggestionsList =
  new ArrayList<WifiNetworkSuggestion> {{
    add(suggestion1);
    add(suggestion2);
    add(suggestion3);
    add(suggestion4);
  }};

final WifiManager wifiManager =
  (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

final int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
// do error handling here…
}

// Optional (Wait for post connection broadcast to one of your suggestions)
final IntentFilter intentFilter =
  new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    if (!intent.getAction().equals(
      WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
      return;
    }
    // do post connect processing here...
  }
};
context.registerReceiver(broadcastReceiver, intentFilter);

アプリが初めて候補を提示するとすぐに、ユーザーに通知されます。通知の種類は、デバイスに搭載されている Android のバージョンによって異なります。

  • Android 11(API レベル 30)以降では、アプリがフォアグラウンドで実行されている場合はダイアログが表示され、アプリがバックグラウンドで実行されている場合は通知が表示されます。
  • Android 10(API レベル 29)では、アプリがフォアグラウンドとバックグラウンドのどちらで実行されているかにかかわらず、ユーザーに通知が表示されます。

プラットフォームがネットワーク候補のいずれかに接続すると、そのネットワーク接続を対応する候補アプリに関連付けるテキストが設定に表示されます。

ユーザーが接続を解除した場合の処理

ユーザーが Wi-Fi 選択ツールを使用して、接続中にネットワーク候補のいずれかから明示的に切断した場合、そのネットワークがまだ範囲内にある場合は無視されます。この期間中は、アプリがネットワークに対応するネットワーク候補を削除して追加し直しても、そのネットワークは自動接続の対象とはみなされません。ユーザーが Wi-Fi 選択ツールを使用して、以前に切断されたネットワークに明示的に接続すると、そのネットワークは直ちに自動接続とみなされます。

アプリの承認ステータスの変更

ユーザーがネットワーク候補の通知を拒否すると、アプリから CHANGE_WIFI_STATE 権限が削除されます。ユーザーは、後で Wi-Fi 管理メニュー([設定] > [アプリと通知] > [特別なアプリアクセス] > [Wi-Fi 制御] > App name)に移動して、この承認を許可できます。