Windows Proximity API Part 6: FindAllPeersAsync

Now that we have the basics in for PeerFinder, we’ll start looking for local peers without using NFC.

Proximity API series overview

Part Six: FindAllPeersAsync

Step One: Look for peers

So far, we can only connect via tapping. Let’s implement the Find button!

Once again in MainPage.xaml.cs at the bottom of our MainPage class add the following:

async private void FindButtonPressed(object sender, RoutedEventArgs e)
{
    if ((PeerFinder.SupportedDiscoveryTypes & PeerDiscoveryTypes.Browse) != PeerDiscoveryTypes.Browse)
    {
        WriteMessageText("Peer discovery using Wi-Fi is not supported.");
        return;
    }

    try
    {
        WriteMessageText("Attempting to find connection.");
        var peerInfoCollection = await PeerFinder.FindAllPeersAsync();
        if (peerInfoCollection.Count > 0)
        {
            // Connect to the first peer
            // NOTE: In production, would provide a list
            ConnectToPeer(peerInfoCollection[0]);
        }
    }
    catch (Exception err)
    {
        WriteMessageText("Error finding peers: " + err.Message);
    }
}

Breakdown:

    if ((PeerFinder.SupportedDiscoveryTypes & PeerDiscoveryTypes.Browse) != PeerDiscoveryTypes.Browse)
    {
        WriteMessageText("Peer discovery using Wi-Fi is not supported.");
        return;
    }

If browse discovery (finding peers through WiFi) is not supported, display a message to the user and return out of the function.

    try
    {
        WriteMessageText("Attempting to find connection.");
        
        //...

    }
    catch (Exception err)
    {
        WriteMessageText("Error finding peers: " + err.Message);
    }

Try to connect, but handle failures.

        var peerInfoCollection = await PeerFinder.FindAllPeersAsync();

Using FindAllPeersAsync(), we get a list of peers in the area and put it into an array.

        if (peerInfoCollection.Count > 0)
        {
            //..
        }

If the count is more than 0, that means there is a peer!

            // Connect to the first peer
            // NOTE: In production, would provide a list
            ConnectToPeer(peerInfoCollection[0]);

For this application, we’re just going to connect to the first peer. In a real app, we would let the user have a little more choice in the matter. Most likely let them chose from some sort of list of potential connections.

But this is just a demo/example, so we don’t need any of that!

Let’s ask to connect to them via the ConnectToPeer() function we’ll make in Step Three.

Step Two: Found a peer!

Somebody is asking to connect to us, let’s accept the connection!

Another new function for our MainPage class:

private void AcceptButtonPressed(object sender, RoutedEventArgs e)
{
    if (requestingPeer == null)
    {
        WriteMessageText("No peer connection has been requested.");
        return;
    }

    ConnectToPeer(requestingPeer);
}

This one is pretty simple. If there is no requestingPeer (a variable we made in Part 5), give an error message and return out of the function. Otherwise, connect to the peer.

Step Three: ConnectToPeer

Once we find a peer through FindAllPeersAsync, we need to connect to it.

async private void ConnectToPeer(PeerInformation peerInfo)
{
    WriteMessageText("Peer found. Connecting to " + peerInfo.DisplayName);
    try
    {
        Windows.Networking.Sockets.StreamSocket socket =
            await PeerFinder.ConnectAsync(peerInfo);

        WriteMessageText("Connection successful. You may now send messages.");
        EnableMessaging(socket);
    }
    catch (Exception err)
    {
         WriteMessageText("Connection failed: " + err.Message);
    }

    requestingPeer = null;
}

Breakdown:

    try
    {
        //...
    }
    catch (Exception err)
    {
         WriteMessageText("Connection failed: " + err.Message);
    }

    requestingPeer = null;

Try to connect, if failed write a nice message to the user. Either way, since there is no longer a requesting peer, null that out.

        Windows.Networking.Sockets.StreamSocket socket =
            await PeerFinder.ConnectAsync(peerInfo);

Make a socket variable, and then attempt to connect using PeerFinder and ConnectAsync.

        WriteMessageText("Connection successful. You may now send messages.");
        EnableMessaging(socket);

If we didn’t enter the catch, it was successful! Now we just need to enable messaging like we did in Part 5.

Step Four: Don’t be shy, say something!

We went to all this trouble to connect, now what do we do?

I guess it’s time to say something!

private void SendButtonPressed(object sender, RoutedEventArgs e)
{
    if (proximitySocket != null)
    {
        SendMessageText();
    }
    else
    {
        WriteMessageText("You must enter proximity to send a message.");
    }
}

When we hit send, check if proximitySocket has a value. If it doesn’t, let the user know they need to connect.

Otherwise, we’ll send the current text in the message box from the function in Step Five.

Step Five: SendMessageText

private async void SendMessageText()
{
    string msg = MessageTextBox.Text;

    if (msg.Length > 0)
    {
        var msgLength = dataWriter.MeasureString(msg);
        dataWriter.WriteInt32(msg.Length);
        dataWriter.WriteString(msg);
        try
        {
            await dataWriter.StoreAsync();
            WriteMessageText("Message sent: " + msg);
        }
        catch (Exception e)
        {
            WriteMessageText("Send error: " + e.Message);
            CloseSocket();
        }
    }
    else
    {
        WriteMessageText("Error: Write something first, silly!");
    }
}

Breakdown:

    string msg = MessageTextBox.Text;

Grab the current value of the MessageTextBox

    if (msg.Length > 0)
    {
        //...
    }
    else
    {
        WriteMessageText("Error: Write something first, silly!");
    }

If the length of that message less than or equal to 0, give an error message.

        var msgLength = dataWriter.MeasureString(msg);
        dataWriter.WriteInt32(msg.Length);
        dataWriter.WriteString(msg);

Read the string into the dataWriter

        try
        {
            await dataWriter.StoreAsync();
            WriteMessageText("Message sent: " + msg);
        }
        catch (Exception e)
        {
            WriteMessageText("Send error: " + e.Message);
            CloseSocket();
        }

Attempt to StoreAsync the string. If there are any errors, give a message and close the socket.

With that, we’re able to chat!

Step Six: Stop button

What happens when we’re done?

private void StopButtonPressed(object sender, RoutedEventArgs e)
{
    _advertising = false;
    PeerFinder.Stop();
    CloseSocket();
    WriteMessageText("Stopped PeerFinder and closed socket");
}

Stop the PeerFinder, which of course means we need to set the _advertising to false, and close the socket.

Up next:

We have a (mostly) working application! Now we just need to add some finishing touches in part seven.

-Tobiah

6 thoughts on “Windows Proximity API Part 6: FindAllPeersAsync”

Leave a Reply

Your email address will not be published. Required fields are marked *