インターネット接続のための 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 ベースの Enterprise 提案(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 プロファイルを記述します。

次のコードサンプルは、オープン ネットワーク、WPA2 ネットワーク、WPA3 ネットワーク、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])でこの承認を許可できます。