隨著NFC的發展,相關的應用也日趨廣泛,讓原本用”應用不廣泛,不普及”為由不添加NFC晶片至手機中的諸家廠商也開始轉向,不管是Android還是Windows Phone,中高階手機都已經內建了NFC晶片
文/黃忠成
NFC(Near Field Communication)
隨著NFC的發展,相關的應用也日趨廣泛,讓原本用”應用不廣泛,不普及”為由不添加NFC晶片至手機中的諸家廠商也開始轉向,不管是Android還是Windows Phone,中高階手機都已經內建了NFC晶片,可以預想的未來的iOS裝置也會跟上。
在這領域中,最積極的莫過於Sony所推出的Andorid手機及Nokia所推出的Windows Phone手機,這兩家廠商只要不是低階的手機,NFC都一定是標準配備。
Proximity Tapper
在Windows Phone 8上市初期,NFC雖然出現在Nokia全系列的Windows 8手機中,但是開發者卻沒有一個方便的模擬工具可以進行NFC相關應用的測試,筆者為了測試NFC於Windows Phone 8的應用,先後購買了HTC的8X及Nokia 620來進行測試,
對開發者而言,這是一個非常傷本的投資。
很幸運的,Windows 8 NFC Emulator出現後不久,一套免費的NFC Emulator for Windows Phone 8 工具推出了,這就是本文介紹的: Proximity Tapper。
透過這個工具,開發者不需要再耗費金錢去購買兩支Windows Phone 8手機,就可以在一個以上的Windows Phone 8模擬器上測試NFC功能,最棒的是她是完全免費且Open Source的。
安裝及使用
Proximity Tapper的安裝非常簡單,只要到以下網址下載程式:
http://proximitytapper.codeplex.com/
切到Download頁面即可下載並安裝。
圖1
特別注意一點,在安裝過程中會出現Windows 防火牆的提示,請一律選擇”允許”,如果不小心沒選到,事後可以到控制台中的Windows防火牆去打開。
圖2
確定一切正常後,便可開啟ProximityTapper.exe,通常安裝後會直接執行,未來可透過桌面捷徑來啟動。
圖3
啟動後會看到以下畫面。
圖4
預設是會自動尋找已啟動的Windows Phone 8 Emulator,接著啟動一個Windows Phone 8 Emulator來試試。
圖5
如果你啟動了Windows Phone 8 Emulator,而ProximityTapper沒找到,那麼很有可能是防火牆的設定未打開,請先確定這點。
當找到後,可以選取該Emulator,然後點選Tap Selected Device and Remain Connected按鈕,然後就可以點選下方的Send Url來模擬以NFC傳送URL至模擬器。
圖6
圖7
Windows Phone 8 SDK中內建的NFC APIs
Windows Phone 8 SDK中提供了基礎的NFC APIs,開發者可以利用這些APIs來撰寫NFC相關的應用程式,例如在兩個Windwos Phone 8 裝置中交換訊息,或是先進行配對然後以藍芽了傳送較大的檔案,
本文先以一個簡單的交換訊息應用程式來展示ProximityTapper的模擬功能。
注意,要使用NFC功能的Windows Phone Project必須啟用ID_CAP_PROXIMITY權限。
圖8
接著請在畫面上放置一個Button,程式如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using PhoneApp15.Resources;
using Windows.Networking.Proximity;
namespace PhoneApp15
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ProximityDevice device = ProximityDevice.GetDefault();
if (device == null)
MessageBox.Show("nfc is not found.");
device.PublishUriMessage(new Uri("http://www.microsoft.com"));
}
………………………
完成後執行此程式,接著啟動另一個模擬器(Windows Phoen 8可以同時開啟不同解析度的模擬器,你可以開啟另一個Visual Studio 2012來啟動另一個模擬器,或是透過後面提供的連結來手動啟動),
然後在ProximityTapper以Ctrl+Mouse Click選取兩個模擬器。
圖9
圖10
完成配對後,就可以點選Button來送出訊息。
圖11
手動啟動Windows Phone 8 Emulator http://blogs.msdn.com/b/notime/archive/2013/04/21/shortcut-to-start-windows-phone-8-emulator.aspx
|
PeerFinder
透過PeerFinder,可以讓兩個裝置以NFC配對然後開啟藍芽或直接透過NFC傳送自訂義的資訊,下面是一個簡單的程式。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using PhoneApp15.Resources;
using Windows.Networking.Proximity;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Storage.Streams;
using Windows.Networking.Sockets;
using System.Threading.Tasks;
namespace PhoneApp15
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
PeerFinder.TriggeredConnectionStateChanged += PeerFinder_TriggeredConnectionStateChanged;
PeerFinder.Start();
Task.Factory.StartNew(async () =>
{
while (true)
{
if (_streamSocket != null)
{
DataReader dr = new DataReader(_streamSocket.InputStream);
try
{
try
{
await dr.LoadAsync(sizeof(uint));
}
catch (Exception)
{
continue;
}
uint strlen = dr.ReadUInt32();
await dr.LoadAsync(strlen);
string data = dr.ReadString(strlen);
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(data);
});
}
finally
{
dr.DetachStream();
dr.Dispose();
dr = null;
}
}
await Task.Delay(1000);
}
});
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
if (_streamSocket != null)
{
DataWriter dw = new DataWriter(_streamSocket.OutputStream);
string message = "i am code6421";
try
{
try
{
dw.WriteUInt32((uint)message.Length);
await dw.StoreAsync();
}
catch (Exception)
{
_streamSocket.Dispose();
return;
}
dw.WriteString(message);
await dw.StoreAsync();
}
finally
{
dw.DetachStream();
dw.Dispose();
dw = null;
}
}
}
private StreamSocket _streamSocket = null;
async void PeerFinder_TriggeredConnectionStateChanged(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;
}
}
// Sample code for building a localized ApplicationBar
//private void BuildLocalizedApplicationBar()
//{
// // Set the page's ApplicationBar to a new instance of ApplicationBar.
// ApplicationBar = new ApplicationBar();
// // Create a new button and set the text value to the localized string from AppResources.
// ApplicationBarIconButton appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/appbar.add.rest.png", UriKind.Relative));
// appBarButton.Text = AppResources.AppBarButtonText;
// ApplicationBar.Buttons.Add(appBarButton);
// // Create a new menu item with the localized string from AppResources.
// ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarMenuItemText);
// ApplicationBar.MenuItems.Add(appBarMenuItem);
//}
}
}
編譯後透過Visual Studio 2012分別部署到兩個模擬器,分別執行後測試。
圖12
圖13
PS: 在其中一個模擬器執行App後,你必須先透過ProximityTapper斷開兩個模擬器的連線,再重新連線來模擬進接裝態。 |