在應用到應用的通信中,應用使用藍牙發現另一播發該應用想要通路的服務的應用。如果應用找到範圍内的提供此服務的另一應用,則發起連接配接請求。當兩個應用均接受連接配接時,将在兩者之間打開流套接字,應用通過它進行通訊。(應用應該是相同)
藍牙API,windows phone 8擴充: PeerFinder 提供發現附近裝置上的另一應用執行個體的能力,并在這些對等方應用之間建立套接字連接配接。對等方應用是運作在另一裝置上的另一應用執行個體。
PeerInformation
包含辨別對等應用或裝置的資訊。
StreamSocket
支援使用 TCP 流套接字的網絡通信。
ConnectionRequestedEventArgs 包含通過 ConnectionRequested 事件傳遞給應用的屬性。
在WMAppManifest.xml 中指定: 應用到應用 ID_CAP_PROXIMITY
應用到裝置
ID_CAP_PROXIMITY、ID_CAP_NETWORKING
一下代碼是綜合這兩個資料自己寫的,林政的代碼有點問題,msdn上有個地方有不同意見。
定義全局變量 StreamSocket _socket; //socket資料流對象 DataWriter _dataWriter; //資料寫入對象,将資料寫入到輸出流 DataReader _dataReader; //資料讀取對象,從輸入流中讀取資料
protected override void OnNavigatedTo( NavigationEventArgs e) { base .OnNavigatedTo(e);
//一定要在FindAllPeersAsync之前調用,顯示自己的藍牙,讓别人能發現 PeerFinder .Start(); //遠端對等類使用ConnectAsync時發生 PeerFinder .ConnectionRequested+=PeerFinder_ConnectionRequested; }
protected override void OnNavigatedFrom( NavigationEventArgs e) { base .OnNavigatedFrom(e);
PeerFinder .ConnectionRequested -= PeerFinder_ConnectionRequested; //stop:節約電量,避免像在程式中打開藍牙,傳回鍵回來目前頁面時能正确提示,而不會一直顯示打開藍牙 CloseConnection( false ); }
點選搜尋的時候調用 private async void Search_Click( object sender, RoutedEventArgs e) { try { //找到所有的 var peers = await PeerFinder .FindAllPeersAsync(); if (peers.Count == 0) { MessageBox .Show( "沒有可以對接的應用" ); } else { listbox.ItemsSource = peers;
if (listbox.Items.Count == 1) listbox.SelectedIndex = 0; } } catch ( Exception ex) { if (( uint )ex.HResult == 0x8007048F) { var result = MessageBox .Show( "是否打開藍牙開關" , "藍牙" , MessageBoxButton .OKCancel); if (result == MessageBoxResult .OK) { //打開藍牙設定 ConnectionSettingsTask connectionSettingsTask = new ConnectionSettingsTask (); connectionSettingsTask.ConnectionSettingsType = ConnectionSettingsType .Bluetooth; connectionSettingsTask.Show(); } } else { MessageBox .Show(ex.Message); } } }
點選連接配接的時候調用 private void OnLink( object sender, RoutedEventArgs e) { Button btn = sender as Button ; PeerInformation peerInfo = btn.DataContext as PeerInformation ;
ConnectToPeer(peerInfo); }
建立連接配接套接字
private async void ConnectToPeer( PeerInformation peer) { try { //連接配接到一個對等類 _socket = await PeerFinder .ConnectAsync(peer);
// We can preserve battery by not advertising our presence. PeerFinder .Stop(); //讀取資訊 PeerFinder_StartReader(); } catch { MessageBox .Show( "目标主機未開啟" ); //msdn上是false,個人覺得應該為true CloseConnection( true ); } }
在調用 ConnectAsync時會觸發事件,調用該事件委托
private void PeerFinder_ConnectionRequested( object sender, ConnectionRequestedEventArgs args) { this .Dispatcher.BeginInvoke(() => { try { var result = MessageBox .Show( string .Format( "是否接受{0}的連結請求" , args.PeerInformation.DisplayName), "對接" , MessageBoxButton .OKCancel); if (result == MessageBoxResult .OK) { txtshow.Text += "開始chat\n" ; ConnectToPeer(args.PeerInformation); } else { } } catch ( Exception ex) { MessageBox .Show(ex.Message); CloseConnection( true ); //重置 } }); }
讀取資訊,時刻等待,異步 async void PeerFinder_StartReader() { try { var message = await GetMessage(); txtshow.Text += message; PeerFinder_StartReader(); } catch { MessageBox .Show( "讀出資料不正确" ); CloseConnection( true ); txtshow.Text += "\nchat End!" ; } }
private async Task < string > GetMessage() { if (_dataReader == null ) _dataReader = new DataReader (_socket.InputStream);
await _dataReader.LoadAsync( sizeof ( uint )); uint strLength = ( uint )_dataReader.ReadInt32(); //讀出消息的長度 await _dataReader.LoadAsync(strLength); return _dataReader.ReadString(strLength); //讀出的字元串 }
發送資訊。 private void SendMessage_Tap_1( object sender, System.Windows.Input. GestureEventArgs e) { SendMessage(txtMessage.Text); }
private async void SendMessage( string message) { if (message.Trim().Length == 0) { MessageBox .Show( "輸入為空" ); return ; }
if (_socket == null ) { MessageBox .Show( "Socket Error" ); return ; } if (_dataWriter == null ) _dataWriter = new DataWriter (_socket.OutputStream); //寫入資訊的長度 _dataWriter.WriteInt32(message.Length); await _dataWriter.StoreAsync(); //寫入的字元串 _dataWriter.WriteString(message); await _dataWriter.StoreAsync(); }
主界面: < Grid x : Name ="ContentPanel" Grid.Row ="1" Margin ="12,0,12,0"> < StackPanel > < Button Content ="通過藍牙查找應用裝置" HorizontalAlignment ="Center" VerticalAlignment ="Top" Click ="Search_Click"/> < ListBox Name ="listbox"> < ListBox.ItemTemplate > < DataTemplate > < StackPanel Orientation ="Horizontal"> < TextBlock Text ="{ Binding DisplayName }"/> < TextBlock Text ="{ Binding ServiceName }"/> < Button Content ="連結" Width ="308" Height ="91" VerticalAlignment ="Top" Click ="OnLink"/> </ StackPanel > </ DataTemplate > </ ListBox.ItemTemplate > </ ListBox > < StackPanel Orientation ="Horizontal"> < TextBox x : Name ="txtMessage" Width ="350"/> < Button x : Name ="btnSendMessage" Content ="Send" Tap ="SendMessage_Tap_1"/> </ StackPanel > < TextBlock Name ="txtshow"/> </ StackPanel > </ Grid >
參考資料: http://www.cnblogs.com/linzheng/archive/2013/01/12/2857468.html http://msdn.microsoft.com/zh-cn/library/windowsphone/develop/jj207007(v=vs.105).aspx