The Android Developer Challenge is back! Submit your idea before December 2.

Wi-Fi Network Request API for peer-to-peer connectivity

On Android 10 (API level 29) and higher devices, you can use a new peer to peer API to bootstrap configuration for secondary devices like Chromecast and Google Home hardware. This feature enables your app to prompt the user to change the access point that the device is connected to by using WifiNetworkSpecifier to describe properties of a requested network.

To use this API, do the following:

  1. Create a Wi-Fi network specifier using WifiNetworkSpecifier.Builder.

  2. Set a network filter to match networks to connect to, along with required credentials.

  3. Decide on a combination of SSID, SSID pattern, BSSID, and BSSID pattern to set the network filter in each request, subject to the following requirements:

    • Each request should provide at least one of SSID, SSID pattern, BSSID, or BSSID pattern
    • Each request can set only one of SSID or SSID pattern
    • Each request can set only one of BSSID or BSSID pattern
  4. Add the specifiers to the network request along with a NetworkCallback instance to track the status of the request.

    If the user accepts the request and the connection to the network is successful, NetworkCallback.onAvailable() is invoked on the callback object. If the user denies the request or if the connection to the network is unsuccessful, NetworkCallback.onUnavailable() is invoked on the callback object.

Initiating the request to connect to a peer device launches a dialog box on the same device, from which that device's user can accept the connection request.

Bypassing user approval

Once the user approves a network to connect to in response to a request from a specific app, the device stores the approval for the particular access point. If the app makes a specific request to connect to that access point again, the device skips the user approval phase and automatically connects to the network. If the user chooses to forget the network while connected to a network requested by the API, then this stored approval for that combination of app and network is removed, and any future request from the app must be approved by the user again. If the app makes a non-specific request, such as with an SSID or BSSID pattern, then the user must approve the request.

Code sample

The following code sample shows how to connect to an open network with an SSID prefix of "test" and a BSSID OUI of "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);