在应用到应用的通信中,应用使用蓝牙发现另一播发该应用想要访问的服务的应用。如果应用找到范围内的提供此服务的另一应用,则发起连接请求。当两个应用均接受连接时,将在两者之间打开流套接字,应用通过它进行通讯。(应用应该是相同)
蓝牙API,windows phone 8扩展:
PeerFinder
提供发现附近设备上的另一应用实例的能力,并在这些对等方应用之间建立套接字连接。对等方应用是运行在另一设备上的另一应用实例。
PeerInformation
包含标识对等应用或设备的信息。
StreamSocket
支持使用 TCP 流套接字的网络通信。
支持使用 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;
-= PeerFinder_ConnectionRequested;
//stop:节约电量,避免像在程序中打开蓝牙,返回键回来当前页面时能正确提示,而不会一直显示打开蓝牙
CloseConnection( false );
}
点击搜索的时候调用
private async void Search_Click( object sender, RoutedEventArgs e)
{
try
{
//找到所有的
var peers
= await PeerFinder.FindAllPeersAsync();
= await PeerFinder.FindAllPeersAsync();
if (peers.Count
== 0)
== 0)
{
MessageBox .Show("没有可以对接的应用" );
}
else
{
listbox.ItemsSource = peers;
if (listbox.Items.Count
== 1)
== 1)
listbox.SelectedIndex = 0;
}
}
catch (Exception ex)
{
if ((uint )ex.HResult
== 0x8007048F)
== 0x8007048F)
{
var result
= MessageBox .Show( "是否打开蓝牙开关" , "蓝牙" , MessageBoxButton .OKCancel);
= MessageBox .Show( "是否打开蓝牙开关" , "蓝牙" , MessageBoxButton .OKCancel);
if (result
== MessageBoxResult .OK)
== MessageBoxResult .OK)
{
//打开蓝牙设置
ConnectionSettingsTask connectionSettingsTask
= new 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;
= sender as Button;
PeerInformation peerInfo
= btn.DataContext as PeerInformation;
= 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.
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);
= MessageBox .Show( string.Format( "是否接受{0}的链接请求" ,
args.PeerInformation.DisplayName), "对接" , MessageBoxButton.OKCancel);
if (result
== MessageBoxResult .OK)
== 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();
= await GetMessage();
txtshow.Text += message;
PeerFinder_StartReader();
}
catch
{
MessageBox .Show("读出数据不正确" );
CloseConnection( true );
txtshow.Text += "\nchat
End!" ;
End!" ;
}
}
private async Task< string >
GetMessage()
GetMessage()
{
if (_dataReader
== null )
== null )
_dataReader = new DataReader (_socket.InputStream);
await _dataReader.LoadAsync(sizeof ( uint));
uint strLength
= (uint )_dataReader.ReadInt32(); //读出消息的长度
= (uint )_dataReader.ReadInt32(); //读出消息的长度
await _dataReader.LoadAsync(strLength);
return _dataReader.ReadString(strLength); //读出的字符串
}
发送信息。
private void SendMessage_Tap_1( object sender,
System.Windows.Input. GestureEventArgs e)
System.Windows.Input. GestureEventArgs e)
{
SendMessage(txtMessage.Text);
}
private async void SendMessage( string message)
{
if (message.Trim().Length
== 0)
== 0)
{
MessageBox .Show("输入为空" );
return ;
}
if (_socket
== null )
== null )
{
MessageBox .Show("Socket
Error" );
Error" );
return ;
}
if (_dataWriter
== null )
== 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>
参考资料: