P2P 연결을 위한 Wi-Fi 네트워크 요청 API

Android 10 (API 수준 29) 이상 기기에서는 새로운 P2P API를 사용하여 Chromecast, Google Home 하드웨어와 같은 보조 기기의 구성을 부트스트랩할 수 있습니다. 이 기능을 사용하면 앱에서 요청된 네트워크의 속성을 설명할 수 있는 WifiNetworkSpecifier를 사용해 기기가 연결되는 액세스 포인트를 변경하라는 메시지를 사용자에게 표시할 수 있습니다.

이 API를 사용하는 방법은 다음과 같습니다.

  1. WifiNetworkSpecifier.Builder를 사용하여 Wi-Fi 네트워크 지정자를 생성합니다.

  2. 필요한 사용자 인증 정보와 함께 연결할 네트워크와 일치하도록 네트워크 필터를 설정합니다.

  3. SSID, SSID pattern, BSSID, BSSID pattern을 어떻게 조합할지 결정하여 각 요청에서 네트워크 필터를 설정합니다. 여기에는 다음과 같은 요구 사항이 적용됩니다.

    • 각 요청은 SSID, SSID pattern, BSSID, BSSID pattern 중 하나 이상을 제공해야 합니다.
    • 각 요청은 SSID 또는 SSID pattern 중 하나만 설정할 수 있습니다.
    • 각 요청은 BSSID 또는 BSSID pattern 중 하나만 설정할 수 있습니다.
  4. NetworkCallback 인스턴스와 함께 네트워크 요청에 지정자를 추가하여 요청 상태를 추적합니다.

    사용자가 요청을 수락하고 네트워크에 연결되면 콜백 객체에서 NetworkCallback.onAvailable()이 호출됩니다. 사용자가 요청을 거부하거나 네트워크 연결에 실패하면 콜백 객체에서 NetworkCallback.onUnavailable()이 호출됩니다.

피어 기기 연결 요청을 시작하면 동일한 기기에 대화상자가 표시됩니다. 이 대화상자에서 기기 사용자가 연결 요청을 수락할 수 있습니다.

사용자 승인 우회

사용자가 특정 앱의 요청에 응답하여 네트워크 연결을 승인하면 기기에서 특정 액세스 포인트에 관한 승인을 저장합니다. 앱이 다시 해당 액세스 포인트에 연결하기 위한 요청을 보내면 기기는 사용자 승인 단계를 건너뛰고 네트워크에 자동으로 연결합니다. 사용자가 API에서 요청한 네트워크에 연결되어 있는 동안 네트워크를 잊기를 원할 경우, 해당 앱과 네트워크에 대해 저장된 승인이 삭제되고 그 이후에 앱에서 보내는 모든 요청은 다시 사용자의 승인을 받아야 합니다. 앱이 불특정 요청(예: SSID 또는 BSSID 패턴)을 보낼 경우, 사용자는 반드시 이 요청을 승인해야 합니다.

코드 샘플

다음 코드 샘플은 SSID 접두사가 "test"이고 BSSID OUI가 "10:03:23"인 개방형 네트워크에 연결하는 방법을 보여줍니다.

Kotlin

val specifier = WifiNetworkSpecifier.Builder()
    .setSsidPattern(PatternMatcher("test", PatternMatcher.PATTERN_PREFIX))
    .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), MacAddress.fromString("ff:ff:ff:00:00:00"))
    .build()

val request = NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
    .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .setNetworkSpecifier(specifier)
    .build()

val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

val networkCallback = object : ConnectivityManager.NetworkCallback() {
    ...
    override fun onAvailable(network: Network?) {
        // do success processing here..
    }

    override fun onUnavailable() {
        // do failure processing here..
    }
    ...
}
connectivityManager.requestNetwork(request, networkCallback)
...
// Release the request when done.
connectivityManager.unregisterNetworkCallback(networkCallback)

Java

final NetworkSpecifier specifier =
  new WifiNetworkSpecifier.Builder()
  .setSsidPattern(new PatternMatcher("test", PatternMatcher.PATTERN_PREFIX))
  .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), MacAddress.fromString("ff:ff:ff:00:00:00"))
  .build();

final NetworkRequest request =
  new NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
  .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
  .setNetworkSpecifier(specifier)
  .build();

final ConnectivityManager connectivityManager = (ConnectivityManager)
  context.getSystemService(Context.CONNECTIVITY_SERVICE);

final NetworkCallback networkCallback = new NetworkCallback() {
  ...
  @Override
  void onAvailable(...) {
      // do success processing here..
  }

  @Override
  void onUnavailable(...) {
      // do failure processing here..
  }
  ...
};
connectivityManager.requestNetwork(request, networkCallback);
...
// Release the request when done.
connectivityManager.unregisterNetworkCallback(networkCallback);