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

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

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);
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)で、通知の承認を行うことができます。