Quickstart: Connecting apps using tapping or browsing (HTML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

When you use Proximity, you can create a connection between two devices with a simple tap gesture, or by browsing for devices within wireless range. You do not need to be connected to a network. You can simply tap two devices together, or connect using Wi-Fi Direct.

To initiate a connection between two instances of the app using a tap gesture, most devices must have NFC. On a PC, this connection channel can be made over Bluetooth, Wi-Fi Direct, or an infrastructure network. On Windows Phone, the connection can be established over Bluetooth or an infrastructure network. Wi-Fi Direct is not supported on Windows Phone. This means that tapping to connect works between a Windows Phone and a PC, but that communication is restricted to using either Bluetooth or an infrastructure network.

For a tap gesture, if two devices with Proximity come within 3-4 centimeters of each other, Proximity notifies both systems. You can use the tap to set up a long-term communication channel, by using Infrastructure network, Wi-Fi Direct, or Bluetooth. Tap gestures are only available if your device has Near-Field Communications (NFC) hardware installed. Wi-Fi Direct browsing is only available if your wireless adapter supports Wi-Fi Direct.

You can also use Proximity to set up a long-term communication channel to a peer app within wireless range.

This topic shows you how to use Proximity to create a connection between peer apps, such as games, between apps that share content, and so on.

The sample in this topic shows how to use Proximity and the PeerFinder class to create a long-term socket connection with a peer application on another device.

For connections triggered by a tap, if the peer application is not running in the foreground on the target device, then Proximity invites the user to activate the app on the target machine. If the peer app is not installed on the target device, then Proximity invites the user on the target device to install the app from the Windows Store. For more details on activating apps with a tap gesture, see "Activating apps using Proximity" in Supporting Proximity and tapping.

Objective: Create a connection between two devices by using Proximity tapping or wireless browsing.

Prerequisites

Microsoft Visual Studio Express 2012 for Windows 8

Instructions

1. Create a new project and enable Proximity

  1. Open Visual Studio Express 2012 for Windows 8 and select New Project from the File menu. In the Javascript section, select Blank Application. Name the application ProximityConnect and click OK.
  2. Open the Package.appxmanifest file and select the Capabilities tab. Select the Proximity capability to enable Proximity. Close and save the manifest file.

2. Add HTML UI

Open the Default.html file and add the following HTML to the <body> section.

<div style="position:absolute;margin:0">
    Display Name: <input type="text" id="displayNameTextBox" style="width:300px" />
    <button id="advertiseForPeersButton">Advertise for a Connection</button>
    <button id="acceptButton">Accept Connection</button>
    <button id="findPeersButton">Browse for Peers</button>
    <button id="stopFindingPeersButton">Stop Browsing for Peers</button><br />
    <input id="sendMessageText" type="text" style="width:200px" />
    <button id="sendMessageButton">Send Message</button><br />
    <div id="messageDiv" style="position:relative;width:600px"></div>
   </div>

3. Add initialization code

The code in this step associates functions with the click events of the HTML buttons. These functions will be added in later steps as event handlers. A shortcut function, id, is included for convenient access to the getElementById function.

Open the js folder. Open the Default.js file and replace the default activated function with the following code.

app.onactivated = function (args) {
    if (args.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {

        id("advertiseForPeersButton").addEventListener("click", advertiseForPeers);
        id("acceptButton").addEventListener("click", acceptConnection);
        id("findPeersButton").addEventListener("click", findPeers);
        id("stopFindingPeersButton").addEventListener("click", stopFindingPeers);
        displayNameTextBox.value = Windows.Networking.Proximity.PeerFinder.displayName;
        Windows.Networking.Proximity.PeerFinder.addEventListener("connectionrequested", connectionRequested);

        // Detect if app launched from a tap.
        if ((args.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) &&
            (args.detail.arguments === "Windows.Networking.Proximity.PeerFinder:StreamSocket")) {

            advertiseForPeers(true);
        }

        args.setPromise(WinJS.UI.processAll());
    }
};

function id(elementId) {
    return document.getElementById(elementId);
}

4. Add the code to connect to a peer app

In this step, you add the code for the click events of the buttons. You also add a method for writing to the UI thread. The code in the event handler for the advertiseForPeersButton button sets the peer name for the local device and starts the PeerFinder. If triggered connections are supported (tapping), the code identifies the event handler for the triggeredConnectionStateChanged event. In the triggeredConnectionStateChanged event handler, the code opens a stream socket to send text messages between the peer apps.

The code in the event handler for the findPeersButton button calls the findAllPeersAsync method to browse for devices within wireless range. When one or more peers is found, the sample calls the connectAsync method to connect to the first peer that is found. This is for sample purposes only. You should present the user with a list of possible peers to choose from, and then connect to the peer that the user chooses.

The code includes an event handler for the connectionRequested event that occurs when a peer opens a connection with you by calling the connectAsync method. You can click the Accept Connection button to accept the connection.

The code in the event handler for the stopFindingPeersButton button calls the stop method. This method stops the event handler from advertising and browsing for peers, whether by a wireless connection or from a tap gesture.

In the Default.js file, add the following code after the id function.

var started = false;

// Click event for "Advertise" button.
function advertiseForPeers(launchedFromTap) {
    Windows.Networking.Proximity.PeerFinder.displayName = displayNameTextBox.Text;

    if (Windows.Networking.Proximity.PeerFinder.supportedDiscoveryTypes &
        Windows.Networking.Proximity.PeerDiscoveryTypes.triggered) {

        Windows.Networking.Proximity.PeerFinder.addEventListener(
            "triggeredconnectionstatechanged", triggeredConnectionStateChanged);

        id("messageDiv").innerHTML +=
            "You can tap to connect a peer device that is " +
            "also advertising for a connection.<br />";
    } else {
        id("messageDiv").innerHTML +=
            "Tap to connect is not supported.<br />";
    }

    if (!launchedFromTap) {
        if (!(Windows.Networking.Proximity.PeerFinder.SupportedDiscoveryTypes &
              Windows.Networking.Proximity.PeerDiscoveryTypes.Browse)) {
            id("messageDiv").innerHTML +=
                "Peer discovery using Wi-Fi Direct is not supported.<br />";
        }
    }

    if (!started) {
        Windows.Networking.Proximity.PeerFinder.start();
        started = true;
    }
}

function triggeredConnectionStateChanged(e) {
    if (e.state === Windows.Networking.Proximity.TriggeredConnectState.peerFound) {
        id("messageDiv").innerHTML +=
            "Peer found. You may now pull your devices out of proximity.<br />";
    }
    if (e.state === Windows.Networking.Proximity.TriggeredConnectState.completed) {
        id("messageDiv").innerHTML += "Connected. You may now send a message.<br />";
        sendMessage(e.socket);
    }
}


// Click event for "Browse" button.
function findPeers() {
    if (Windows.Networking.Proximity.PeerFinder.supportedDiscoveryTypes &
        Windows.Networking.Proximity.PeerDiscoveryTypes.browse) {

        Windows.Networking.Proximity.PeerFinder.findAllPeersAsync().done(
    function (peerInfoCollection) {
        if (peerInfoCollection.length > 0) {
            // Connect to first peer found - example only.
            // In your app, provide the user with a list of available peers.
            connectToPeer(peerInfoCollection[0]);
        }
    },
    function (err) {
        id("messageDiv").innerHTML += "Error finding peers: " + err + "<br />";
    });
    } else {
        id("messageDiv").innerHTML +=
        "Peer discovery using Wi-Fi Direct is not supported.<br />";
    }
}

function connectToPeer(peerInfo) {
    id("messageDiv").innerHTML += ("Peer found. Connecting to " + peerInfo.displayName + "<br />");
    Windows.Networking.Proximity.PeerFinder.connectAsync(peerInfo).done(
        function (socket) {
            id("messageDiv").innerHTML += "Connection successful. You may now send messages.<br />";
            sendMessage(socket);
        },
        function (err) {
            id("messageDiv").innerHTML += "Connection failed: " + err + "<br />";
        });

    requestingPeer = null;
}

function stopFindingPeers() {
    Windows.Networking.Proximity.PeerFinder.stop();
    started = false;
    if (proximitySocket != null) { closeSocket(); }
}

// Handle external connection requests.
var requestingPeer;

function connectionRequested(e) {
    id("messageDiv").innerHTML +=
        "Connection requested by " + e.peerInformation.DisplayName + ". " +
        "Click 'Accept Connection' to connect.";
    requestingPeer = e.PeerInformation;
}

function acceptConnection() {
    if (requestingPeer == null) {
        id("messageDiv").innerHTML += "No peer connection has been requested.";
        return;
    }

    connectToPeer(requestingPeer);
}

5. Add the code to send and receive messages using the ProximityStreamSocket

When a successful connection is made, the code passes the ProximityStreamSocket object created by the connection to the sendMessage function. The sendMessage function opens a network connection with the proximate device. This enables you to send messages back and forth. Be sure to always call the close method of the ProximityStreamSocket object when you are finished with it.

In the Default.js file, add the following code after the connectToPeer function.

var proximitySocket;
var dataWriter;

// Reference socket streams for writing and reading messages.
function sendMessage(socket) {
    id("sendMessageButton").addEventListener("click", sendMessageText);

    // Get the network socket from the proximity connection.
    proximitySocket = socket;

    // Create DataWriter for writing messages to peers.
    dataWriter = new Windows.Storage.Streams.DataWriter(proximitySocket.outputStream);

    // Listen for messages from peers.
    var dataReader = new Windows.Storage.Streams.DataReader(proximitySocket.inputStream);
    startReader(proximitySocket, dataReader);
}

// Send a message to the socket.
function sendMessageText() {
    var msg = id("sendMessageText").value;

    if (msg.length > 0) {
        var msgLength = dataWriter.measureString(msg);
        dataWriter.writeInt32(msgLength);
        dataWriter.writeString(msg);
        dataWriter.storeAsync().done(
            function (byteCount) {
                if (byteCount > 0) {
                    id("messageDiv").innerHTML += "Message sent: " + msg + "<br />";
                } else {
                    id("messageDiv").innerHTML += "The remote peer closed the socket.";
                    closeSocket();
                }
            },
            function (err) {
                id("messageDiv").innerHTML += "Send error: " + err.message + "<br />";
                closeSocket();
            });
    }
}

// Read out and print the message received from the socket.
function startReader(socket, reader) {
    var initialLength = 4;
    reader.loadAsync(initialLength).done(
    function (byteCount) {
        if (byteCount > 0) {
            var msgLength = reader.readInt32();
            reader.loadAsync(msgLength).done(
                function (byteCount) {
                    if (byteCount > 0) {
                        var message = reader.readString(msgLength);
                        id("messageDiv").innerHTML += "Received message: " + message + "<br />";

                        // After receiving a message, listen for the next message.
                        startReader(socket, reader);
                    }
                    else {
                        id("messageDiv").innerHTML += "The remote peer closed the socket.";
                        closeSocket();
                    }
                },
                function (err) {
                    id("messageDiv").innerHTML += "Receive error: " + err.message + "<br />";
                    reader.close();
                });
        }
        else {
            id("messageDiv").innerHTML += "The remote peer closed the socket.";
            reader.close();
        }
    },
    function (err) {
        id("messageDiv").innerHTML += "Receive error: " + err.message + "<br />";
        reader.close();
    });
}

function closeSocket() {
    if (proximitySocket) {
        proximitySocket.close();
        proximitySocket = null;
    }

    if (dataWriter) {
        dataWriter.close();
        dataWriter = null;
    }
}

6. Run the app

To see the app in action, run it on two devices that have Proximity enabled. Then click the Advertise for a Connection button in both apps, and then tap the devices together. If you have Wi-Fi Direct on both devices, instead of a tap, you can click the or Browse for Peers button on one device to create the connection.

Important  

This quickstart must be run on two devices. For scenarios that use a tap gesture, each device must have a Proximity device, such as a Near-Field Communication (NFC) radio, installed. For scenarios that use wireless browsing, you need two PCs with Wi-Fi Direct enabled, or two Windows Phones with Bluetooth enabled. If you don't have hardware that supports Proximity tapping, such as an NFC radio, you can use the Proximity driver sample that is part of the Windows Driver Kit (WDK) samples. You can use the sample driver to simulate a tap gesture over a network connection between two devices. For information on how to download the WDK, see Windows Driver Kit (WDK). After you have installed the WDK and samples, you can find the Proximity driver sample in the src\nfp directory in the location where you installed the WDK samples. See the NetNfpProvider.html file in the src\nfp\net directory for instructions on building and running the simulator. After you start the simulator, it runs in the background while your Proximity app is running in the foreground. Your app must be in the foreground for the tap simulation to work.

 

Summary and next steps

In this tutorial, you created an app that uses a tap gesture or wireless browsing to connect devices.

You can also use tap gestures to publish and subscribe to messages. For an example, see Publishing and subscribing to messages using Tapping.

Guidelines for developing using Proximity

Supporting Proximity and tapping

Testing and troubleshooting Proximity in apps

Windows.Networking.Proximity namespace

Samples

Proximity sample