Create P2P connections with Wi-Fi

Wi-Fi P2P allows your application to quickly find and interact with nearby
devices, at a range beyond the capabilities of Bluetooth.

The Wi-Fi peer-to-peer (P2P) APIs allow applications to connect to nearby devices without
needing to connect to a network or hotspot (Android's Wi-Fi P2P framework complies with the
Wi-Fi Direct™ certification program).
If your app is designed to be a part of a secure, near-range network, Wi-Fi
Direct is a more suitable option than traditional Wi-Fi ad-hoc
networking for the following reasons:

Devices can broadcast the services that they provide, which helps other
devices discover suitable peers more easily.

When determining which device should be the group owner for the network,
Wi-Fi Direct examines each device's power management, UI, and service
capabilities and uses this information to choose the device that can handle
server responsibilities most effectively.

Android doesn't support Wi-Fi ad-hoc mode.

This lesson shows you how to find and connect to nearby devices using Wi-Fi P2P.

Set up a broadcast receiver and peer-to-peer manager

To use Wi-Fi P2P, you need to listen for broadcast intents that tell your
application when certain events have occurred. In your application, instantiate
an IntentFilter and set it to listen for the following:

Finally, add code to register the intent filter and broadcast receiver when
your main activity is active, and unregister them when the activity is paused.
The best place to do this is the onResume() and
onPause() methods.

Java

manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// Code for when the discovery initiation is successful goes here.
// No services have actually been discovered yet, so this method
// can often be left blank. Code for peer discovery goes in the
// onReceive method, detailed below.
}
@Override
public void onFailure(int reasonCode) {
// Code for when the discovery initiation fails goes here.
// Alert the user that something went wrong.
}
});

Keep in mind that this only initiates peer discovery. The
discoverPeers() method starts the discovery process and then
immediately returns. The system notifies you if the peer discovery process is
successfully initiated by calling methods in the provided action listener.
Also, discovery remains active until a connection is initiated or a P2P group is
formed.

Fetch the list of peers

Now write the code that fetches and processes the list of peers. First
implement the WifiP2pManager.PeerListListener
interface, which provides information about the peers that Wi-Fi P2P has
detected. This information also allows your app to determine when peers join or
leave the network. The following code snippet illustrates these operations
related to peers:

Kotlin

private val peers = mutableListOf<WifiP2pDevice>()
...
private val peerListListener = WifiP2pManager.PeerListListener { peerList ->
val refreshedPeers = peerList.deviceList
if (refreshedPeers != peers) {
peers.clear()
peers.addAll(refreshedPeers)
// If an AdapterView is backed by this data, notify it
// of the change. For instance, if you have a ListView of
// available peers, trigger an update.
(listAdapter as WiFiPeerListAdapter).notifyDataSetChanged()
// Perform any other updates needed based on the new list of
// peers connected to the Wi-Fi P2P network.
}
if (peers.isEmpty()) {
Log.d(TAG, "No devices found")
return@PeerListListener
}
}

Java

private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
...
private PeerListListener peerListListener = new PeerListListener() {
@Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
List<WifiP2pDevice> refreshedPeers = peerList.getDeviceList();
if (!refreshedPeers.equals(peers)) {
peers.clear();
peers.addAll(refreshedPeers);
// If an AdapterView is backed by this data, notify it
// of the change. For instance, if you have a ListView of
// available peers, trigger an update.
((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
// Perform any other updates needed based on the new list of
// peers connected to the Wi-Fi P2P network.
}
if (peers.size() == 0) {
Log.d(WiFiDirectActivity.TAG, "No devices found");
return;
}
}
}

Now modify your broadcast receiver's onReceive()
method to call requestPeers() when an intent with the action WIFI_P2P_PEERS_CHANGED_ACTION is received. You
need to pass this listener into the receiver somehow. One way is to send it
as an argument to the broadcast receiver's constructor.

If each of the devices in your group supports Wi-Fi direct, you don't need
to explicitly ask for the group's password when connecting. To allow a device
that doesn't support Wi-Fi Direct to join a group, however, you need to
retrieve this password by calling
requestGroupInfo(), as
shown in the following code snippet:

Java

Note that the WifiP2pManager.ActionListener implemented in
the connect() method only notifies you when the initiation
succeeds or fails. To listen for changes in connection state, implement the
WifiP2pManager.ConnectionInfoListener interface.
Its onConnectionInfoAvailable() callback notifies you when the state of the
connection changes. In cases where multiple devices are going to be connected to
a single device (like a game with three or more players, or a chat app), one device
is designated the "group owner". You can designate a particular device as
the network's group owner by following the steps in the
Create a Group section.

Kotlin

private val connectionListener = WifiP2pManager.ConnectionInfoListener { info ->
// InetAddress from WifiP2pInfo struct.
val groupOwnerAddress: String = info.groupOwnerAddress.hostAddress
// After the group negotiation, we can determine the group owner
// (server).
if (info.groupFormed && info.isGroupOwner) {
// Do whatever tasks are specific to the group owner.
// One common case is creating a group owner thread and accepting
// incoming connections.
} else if (info.groupFormed) {
// The other device acts as the peer (client). In this case,
// you'll want to create a peer thread that connects
// to the group owner.
}
}

Java

@Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
// InetAddress from WifiP2pInfo struct.
InetAddress groupOwnerAddress = info.groupOwnerAddress.getHostAddress();
// After the group negotiation, we can determine the group owner
// (server).
if (info.groupFormed && info.isGroupOwner) {
// Do whatever tasks are specific to the group owner.
// One common case is creating a group owner thread and accepting
// incoming connections.
} else if (info.groupFormed) {
// The other device acts as the peer (client). In this case,
// you'll want to create a peer thread that connects
// to the group owner.
}
}