Windows Phone 8 的邻近感应
2012/11/14
适用于:仅限于 Windows Phone 8。
邻近感应指 Windows 运行时(支持近距离内设备之间的连接)中的类的集合。通过使用此 API,您的应用可以通过点击或通过浏览查找无线范围内运行您的应用(对等方应用)的其他设备来建立连接。例如,这其中的一个应用可能是多人游戏,其中的两个用户点击其手机共同建立一个共享游戏会话。或者,某个应用可能让用户能够点击计算机,并收到位置链接,用户可以在该位置获得更多信息或进行购买。Windows Phone 8 支持使用近场通信 (NFC) 的 邻近 通信。本主题概述 Windows Phone 邻近感应 API。
我们有意在本主题中使用术语 设备来表明:既可以在运行 Windows Phone 8 的手机之间进行临近感应通信,也可以在 Windows Phone 8 手机和不同种类的设备(如运行 Windows 的计算机)之间进行通信。 |
本主题包含以下各节。
临近感应和 NFC 使您能够通过点击或将两个设备放在几毫米的距离内来连接它们。该方案适用于 Windows Phone 8 和 Windows 8 设备。点击成功时,您会获得一个套接字,通过它即可与另一个设备通信。在 Windows Phone 8 上,在 TCP/IP (Wi-Fi) 连接或蓝牙连接时建立该套接字。临近感应 API 根据PeerFinder.AllowBluetooth 和 PeerFinder.AllowInfrastructure 的属性值(默认为 true)确定建立何种连接。当希望进行连接的设备已启用蓝牙时,可获得最一致的用户体验(就能够随处点击和连接而言)。如果两个设备处于相同的基础结构网络(相同的网络或路由器、无 IP 冲突、无防火墙、设备之间可执行 ping 操作),则有可能建立 Wi-Fi 连接。因此,建议应用在进行点击尝试之前通知用户,以确保两个设备都已启用蓝牙。这可以通过在页面上显示消息或显示 MessageBox 完成。这是告诉用户如何利用其设备获得最佳点击体验的透明方式。
发送和接收 NFC 消息
本例演示运行在两个启用 NFC 的设备上的应用如何交换数据。使用 ProximityDevice 类在应用之间传递简单的字符串。API 提供默认格式化,因此该方案非常容易实现。
发送消息 |
ProximityDevice device = ProximityDevice.GetDefault(); // Make sure NFC is supported if (device!= null) { long Id = device.PublishMessage("Windows.SampleMessageType", "Hello World!"); Debug.WriteLine("Published Message. ID is {0}", Id); // Store the unique message Id so that it // can be used to stop publishing this message } |
|
|
|
|
接收消息 |
ProximityDevice device = ProximityDevice.GetDefault(); // Make sure NFC is supported if (device!= null) { long Id = device.SubscribeForMessage ("Windows.SampleMessageType", messageReceived); Debug.WriteLine("Published Message. ID is {0}", Id); // Store the unique message Id so that it // can be used to stop subscribing for this message type } private void messageReceived(ProximityDevice sender, ProximityMessage message) { Debug.WriteLine("Received from {0}:'{1}'", sender.DeviceId, message.DataAsString); } |
|
查找 Windows Phone 对等方应用
本例演示如何使用 PeerFinder 类查找 对等方应用。
开始查找对等方 |
ProximityDevice device = ProximityDevice.GetDefault(); // Make sure NFC is supported if (device!= null) { PeerFinder.TriggeredConnectionStateChanged += OnTriggeredConnectionStateChanged; // Start finding peer apps, while making this app discoverable by peers PeerFinder.Start(); } |
|
|
|
|
处理连接状态变化 |
StreamSocket _streamSocket; void OnTriggeredConnectionStateChanged(object sender, TriggeredConnectionStateChangedEventArgs args) { switch (args.State) { case TriggeredConnectState.Listening: // Connecting as host break; case TriggeredConnectState.PeerFound: // Proximity gesture is complete and user can pull their devices away. Remaining work is to // establish the connection using a different transport, like TCP/IP or Bluetooth break; case TriggeredConnectState.Connecting: // Connecting as a client break; case TriggeredConnectState.Completed: // Connection completed, retrieve the socket over which to communicate _streamSocket = args.Socket; break; case TriggeredConnectState.Canceled: break; case TriggeredConnectState.Failed: // Connection was unsuccessful break; } } |
|
查找 Windows 8 对等方应用
若要查找其他平台(如 Windows 8)上的对等方应用,则必须首先定义您的应用在该平台上的备用应用 ID。
ProximityDevice device = ProximityDevice.GetDefault(); if (device != null) { PeerFinder.AlternateIdentities.Add("Windows", "my Win8 appID"); PeerFinder.TriggeredConnectionStateChanged += OnTriggeredConnectionStateChanged; // Start finding peer apps, while making this app discoverable to peers PeerFinder.Start(); }
为 NFC 建立的基础套接字不受保护。默认不加密数据信道。若要加密通过该套接字传递的数据,以便降低篡改风险,则可使用 StreamSocket 上的 SessionKey 属性值作为对称密钥。这可以在加密库中使用,如System.Security.Cryptography.AesManaged。只有彼此处于近距离的设备知道此密钥。
由于手机的资源限制,您的应用有时可能会被逻辑删除。这是正常情况,因为要帮助维持流畅平滑的手机体验。可能会因多种原因而将您的应用推送至后台:来电、用户切换应用、新短信等。当您的应用被逻辑删除时,它会丢失资源,而且任何套接字连接都断开。当用户移动时,应用也可能失去套接字连接,视无线连接的可用情况而定。这是预期之中的事,而且因为我们希望确保用户拥有良好的用户体验,所以在 Windows Phone 8 中引入了重新连接。通过重新连接,在短暂失去套接字连接之后,会自动重新建立连接。
Windows Phone 8 上的重新连接仅支持蓝牙和 TCP/IP (Wi-Fi) 连接。 |
套接字连接失败后重新连接的步骤
-
建立连接时,保存 RemoteHostName 和 RemoteServiceName 属性值。
-
在应用的 Application_DeActivated 事件中,如果有活动套接字连接,则保存RemoteHostName.RawName 和 RemoteServiceName 值,因为这表示应用希望在继续时重新连接。
string storedRemoteHostRawName = socket.Information.RemoteHostName.RawName; string storeRemoteServiceName = socket.Information.RemoteServiceName; // Persist these two values
-
当应用重新激活并继续时,照常调用 PeerFinder.Start 方法。
-
使用在步骤 2 中保存的 storedRemoteHostRawName 值创建新的 RemoteHostName 对象。
HostName newRemoteHostName = new HostName(storedRemoteHostRawName);
-
创建新的套接字,调用 ConnectAsync,并传入 storedRemoteServiceName 和新创建的newRemoteHostName。
await socket.ConnectAsync(newRemoteHostName, storedRemoteServiceName);
如果您和您的对等方都按此过程执行操作,则会顺利完成 ConnectAsync 调用,无需再次在一起点击手机,你们的应用即会重新连接。
调用取消挂起的 ConnectAsync 调用无效。在尝试重新连接之前,重新连接操作仍将等待全时暂停。 |
如果 Windows Phone 8 设备尝试重新连接 Windows 8 设备,它会失败,因为 Windows 8 不支持该重新连接操作。 |
无法使用 Windows Phone 模拟器 测试临近感应。应使用 Windows Phone 8 设备测试临近感应。
ProximityDevice.GetDefault() 创建 Windows.Networking.Proximity.ProximityDevice 类的实例并激活默认临近感应提供程序。但是,因为这不是系统内总是可用的资源,请确保把该对象存储为类成员变量或静态变量,使之不会无意中超出范围。