快速入门:使用点击或浏览连接应用 (HTML)

[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]

如果你使用邻近感应,你可以通过简单的点击手势,或浏览无线范围内的设备,即可在两台设备之间创建连接。你无需连接到网络。只需同时点击两台设备,或使用 Wi-Fi Direct 连接。

若要使用点击手势发起应用的两个实例之间的连接,大部分设备都必须具有 NFC。在电脑上,可以通过蓝牙、Wi-Fi Direct 或基础结构网络建立该连接通道。在 Windows Phone 上,可以通过蓝牙或基础结构网络建立连接。Wi-Fi Direct 在 Windows Phone 上不受支持。 这意味着可以在 Windows Phone 和电脑之间通过点击连接工作,但该通信限制为使用蓝牙或基础结构网络。

使用点击手势时,如果带有邻近感应的两台设备相互之间距离在 3-4 厘米范围内,邻近感应会通知双方的系统。你可以使用点击利用基础结构网络、Wifi-Direct 或蓝牙来建立长期的信道。点击手势仅在你的设备装有近距离通信 (NFC) 硬件时才可用。Wi-Fi Direct 浏览仅在你的无线适配器支持 Wi-Fi Direct 时才可用。

你也可以使用邻近感应在无线范围内建立与对等应用相连接的长期信道。

本主题介绍了如何使用邻近感应来在对等应用(如游戏、共享内容的应用等)之间创建连接。

本主题中的示例显示了如何使用邻近感应和 PeerFinder 类与另一台设备上的对等应用程序建立长期的套接字连接。

对于通过点击触发的连接,如果目标设备上的对等应用程序没有在前台运行,那么邻近感应将邀请用户激活目标计算机上的应用。如果对等应用没有安装在目标设备上,那么邻近感应将邀请目标设备上的用户从 Windows 应用商店安装应用。有关使用点击手势激活应用的详细信息,请参阅支持邻近感应和点击中的“使用邻近感应激活应用”。

目标: 通过使用邻近点击或无线浏览功能在两台设备之间建立连接。

先决条件

Microsoft Visual Studio Express 2012 for Windows 8

说明

1. 创建新项目并启用邻近感应

  1. 打开 Visual Studio Express 2012 for Windows 8,然后从“文件”菜单中选择“新建项目”。在“JavaScript”部分,选择“空白应用程序”。将该应用程序命名为 ProximityConnect,然后单击“确定”。
  2. 打开 Package.appxmanifest 文件并选择“功能”****选项卡。选择“邻近”功能以启用邻近感应。关闭并保存清单文件。

2. 添加 HTML UI

打开 Default.html 文件并将下面的 HTML 添加到 <body> 部分中。

<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. 添加初始化代码

本步骤中的代码将函数与 HTML 按钮的单击事件关联。在后面的步骤中,这些函数将作为事件处理程序添加。包括快捷方式函数,id,以便于访问 getElementById 函数。

打开 js 文件夹。打开 Default.js 文件并将默认的 activated 函数替换为下面的代码。

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. 添加代码以连接对等应用

在此步骤中,为按钮的单击事件添加代码。你还添加方法以写入 UI 线程。advertiseForPeersButton 按钮的事件处理程序中的代码为本地设备设置对等名称并启动 PeerFinder。如果支持触发的连接(点击),代码将识别 triggeredConnectionStateChanged 事件的事件处理程序。在 triggeredConnectionStateChanged 事件处理程序中,代码打开一个流套接字,从而在对等应用之间发送文本消息。

findPeersButton 按钮的事件处理程序的代码调用 findAllPeersAsync 方法,以在无线范围内浏览设备。找到一个或多个对等方后,示例调用 connectAsync 方法以连接找到的第一个对等方。仅作为示例。你应当向用户显示可选择的对等方列表,然后连接到用户所选的对等方。

代码中包括对等方通过调用 connectAsync 方法打开与你的连接后发生的 connectionRequested 事件的事件处理程序。你可以单击“接受连接”按钮以接受连接。

stopFindingPeersButton 按钮的事件处理程序中的代码调用停止方法。此方法通过无线连接或点击手势,阻止事件处理程序公布和浏览对等方。

在 Default.js 文件中,将以下代码添加到 id 函数后。

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. 添加使用 ProximityStreamSocket 发送和接收消息的代码

成功建立连接后,代码将由连接创建的 ProximityStreamSocket 对象传递到 sendMessage 函数。sendMessage 函数打开与邻近设备的网络连接。它支持来回发送消息。完成后,请确保总是调用 ProximityStreamSocket 对象的 close 方法。

在 Default.js 文件中,将以下代码添加到 connectToPeer 函数后。

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. 运行该应用

若要查看该应用的操作情况,请在两台启用了邻近感应的设备上运行该应用。然后在两个应用上都单击“公开以进行连接”按钮,再一起点击两台设备。如果你在两台设备上都有 Wi-Fi Direct,则不需要点击,在一台设备上单击“浏览对等方”****按钮即可建立连接。

要点  

本快速入门必须在两台设备上运行。对于使用点击手势的方案,每台设备都必须安装一个邻近感应设备,如近场通信 (NFC) 射频硬件。对于使用无线浏览的方案,你需要两台启用了 Wi-Fi Direct 的电脑,或者两台启用了蓝牙的 Windows Phone。如果没有支持邻近感应点击的硬件(例如 NFC 射频硬件),可以使用 Windows 驱动程序工具包 (WDK) 示例中包含的邻近感应驱动程序示例。可以使用示例驱动程序模拟两台设备之间网络连接上的点击手势。有关如何下载 WDK 的信息,请参阅 Windows 驱动程序工具包 (WDK)。安装 WDK 和示例后,可以在安装 WDK 示例的位置中的 src\nfp 目录下找到邻近驱动程序示例。请查阅 src\nfp\net 目录中的 NetNfpProvider.html 文件,了解构建和运行模拟器的说明。启动模拟器后,它在后台运行,而邻近应用在前台运行。应用必须在前台运行,这样点击模拟才能生效。

 

摘要和后续步骤

在本教程中,你创建了一个使用点击手势或无线浏览功能连接设备的应用。

还可以使用点击手势发布和订阅消息。若要查看示例,请参阅使用点击发布和订阅消息

相关主题

使用邻近进行开发的指南

支持邻近感应和点击

对应用中的邻近感应进行测试和疑难解答

Windows.Networking.Proximity namespace

示例

邻近示例