Windows Phone 8 蓝牙编程
蓝牙是手机的近距离无限传输的技术,在之前的Windows Phone 7系统手机里面仅支持蓝牙耳机功能,并不支持蓝牙文件信息传输,那么在Windows Phone 8手机里面将全面支持蓝牙技术,并且提供了相关的API来给开发者使用。开发者可以利用蓝牙的相关API来创建应用程序,在应用程序里面使用手机的蓝牙技术来进行近距离的文件传输和发送接收消息,创造出更加有趣和方便的应用软件。
在Windows Phone 8里面可以在应用程序里面利用蓝牙进行通信,使用蓝牙相关的API,可以让应用程序连接到另外的一个应用程序,也可以让应用程序连接到一个设备上。Windows Phone 8的蓝牙技术支持两个蓝牙方案:一个是应用程序到应用程序的通信,另外一个是应用程序到设备的通信。
1.应用程序到应用程序的通信
应用程序到应用程序的通信的过程是,应用程序使用蓝牙去查找正在广播蓝牙服务的对等的应用程序,如果在应用程序提供服务的范围内发现一个应用程序,那么该应用程序可以发起连接请求。当这两个应用程序接受连接,它们之间就可以进行通信了,通信的过程是使用socket的消息发送接收机制。在Windows Phone 8中使用到应用程序到应用程序的蓝牙通讯技术,需要在项目的WMAppManifest.xml文件中添加ID_CAP_PROXIMITY的功能选项,表示支持临近的设备通信能力,否则程序会出现异常。
2.应用程序到设备的通信
在应用程序到设备的通信过程时,应用程序使用蓝牙去查找提供服务的设备,如果提供的服务范围之内发现一个可以连接的蓝牙设备,那么该应用程序可以发起连接请求。当应用程序和设备同时接受该连接,它们之间就可以进行通信了,通信的过程也是使用socket的消息发送接收机制,类似于应用程序到应用程序的通信。在Windows Phone 8中使用到应用程序到设备的蓝牙通讯技术,需要在项目的WMAppManifest.xml文件中添加ID_CAP_PROXIMITY和ID_CAP_NETWORKING的功能选项,表示支持临近的设备通信能力和网络通信能力,否则程序会出现异常。
蓝牙编程类
在Windows Phone 8里面使用到蓝牙编程主要会用到PeerFinder类,PeerInformation类,StreamSocket类和ConnectionRequestedEventArgs类,这些类的说明如表19.1所示。因为蓝牙也是基于TCP协议进行消息传递了,所以需要用到Socket的相关的编程知识,以及StreamSocket类。PeerFinder类是蓝牙查找类,它的主要成员如表19.2所示。
表19.1 蓝牙编程类的说明
类名 |
说明 |
PeerFinder |
用于去查找附近的设备是否有运行和当前应用程序相同的应用程序,并且可以在两个应用程序之间建立起socket连接,从而可以进行通信。对等应用程序是在其他设备上运行的应用程序的另一个实例。 |
PeerInformation |
包含对等应用程序或设备的识别信息。 |
StreamSocket |
支持使用一个TCP的Socket流的网络通信。 |
ConnectionRequestedEventArgs |
表示传递到一个应用程序的ConnectionRequested事件的属性 |
表 19.2 PeerFinder类的成员
成员 |
说明 |
bool AllowBluetooth |
指定 PeerFinder 类的此实例是否可以通过使用 Bluetooth 来连接 ProximityStreamSocket 对象。如果PeerFinder 的此实例可以通过使用 Bluetooth 来连接 ProximityStreamSocket 对象,则为 true;否则为false。默认为 true。 |
bool AllowInfrastructure |
是否使用TCP/IP协议连接到StreamSocket |
bool AllowWiFiDirect |
指定 PeerFinder 类的此实例是否可以通过使用 Wi-Fi Direct 来连接 ProximityStreamSocket 对象。如果 PeerFinder 的此实例可以通过使用 Wi-Fi Direct 来连接 ProximityStreamSocket 对象,则为 true;否则为false。默认为 true。 |
IDictionary<string, string> AlternateIdentities |
获取要与其他平台上的对等应用程序匹配的备用 AppId 值列表。返回要与其他平台的对等类应用程序匹配的备用 AppId 值列表。 |
string DisplayName |
获取或设置标识计算机到远程对等类的名称。 |
PeerDiscoveryTypes SupportedDiscoveryTypes |
获取一个值,该值指示哪些发现选项可与 PeerFinder 类一同使用 |
event TypedEventHandler<object, ConnectionRequestedEventArgs> ConnectionRequested |
远程对等类使用 ConnectAsync 方法请求连接时发生。 |
event TypedEventHandler<object, TriggeredConnectionStateChangedEventArgs> TriggeredConnectionStateChanged |
在远程对等类的轻击笔势期间发生。 |
IAsyncOperation< StreamSocket> ConnectAsync(PeerInformation peerInformation) |
连接已发现了对 FindAllPeersAsync 方法的调用的对等类。peerInformation:表示连接到的对等类的对等类信息对象。返回通过使用所提供的临近StreamSocket 对象连接远程对等类的异步操作。 |
IAsyncOperation<IReadOnlyList<PeerInformation>> FindAllPeersAsync() |
适用于无线范围内运行相同应用程序的对等计算机的异步浏览。返回通过使用 Wi-Fi直连技术浏览对等类的异步操作。 |
void Start(string peerMessage) |
向临近设备上的对等类应用程序传递消息。 |
void Stop() |
停止查找对等类应用程序或广播对等类连接的过程 |
查找蓝牙设备和对等项
查找在服务范围内的蓝牙设备和对等项是蓝牙编程的第一步,查找蓝牙设备和对等项中会使用到PeerFinder类的FindAllPeersAsync方法去进行查找,然后以异步的方式返回查找到的对等项列表的信息IReadOnlyList<PeerInformation>,注意要使查找对等的应用程序时,在调用FindAllPeersAsync方法前必须先调用PeerFinder类的Start方法,主要的目的是启动广播服务,让对方的应用程序也能查找到自己。PeerInformation包含三个属性:一个是DisplayName表示对等项的名字,这个名字一般都是由对方的设备的名称或者查找到的应用程序自身设置的现实名字,一个是HostName表示主机名字或者IP地址,还有一个属性是ServiceName表示服务名称或者TCP协议的端口号。然后可以利用查找到的PeerInformation信息进行连接和通信。
查找对等的应用程序的代码示例:
async void AppToApp(){ // 启动查找服务 PeerFinder.Start(); //开始查找 ObservableCollection<PeerInformation> peers = await PeerFinder.FindAllPeersAsync(); if (peers.Count == 0) { //未找到任何的对等项 } else { //处理查找到的对等项,可以使用PeerFinder类的ConnectAsync方法来连接选择的要进行通信的对等项 }}
查找蓝牙设备的代码示例:
private async void AppToDevice(){ // 设置查找所匹配的蓝牙设备 PeerFinder.AlternateIdentities["Bluetooth:Paired"] = ""; // 开始查找 ObservableCollection<PeerInformation> pairedDevices = await PeerFinder.FindAllPeersAsync(); if (pairedDevices.Count == 0) { // 没有找到可用的蓝牙设备 } else { //处理查找到的蓝牙设备,可以新建一个StreamSocket对象,然后使用StreamSocket类的ConnectAsync方法通过HostName和ServiceName来连接蓝牙设备 }}
蓝牙发送消息
蓝牙编程的发送消息机制使用的是TCP的StreamSocket的方式,原理与Socket的一致。在蓝牙连接成功后,可以获取到一个StreamSocket类的对象,然后我们使用该对象的OutputStream属性来初始化一个DataWriter对象,通过DataWriter对象来进行发送消息。OutputStream属性表示的是Socket的输出流,用于发送消息给对方。下面来看一下发送消息的示例:
async void SendMessage(string message){ // 连接选中的对等项,selectedPeer为查找到的PeerInformation对象 StreamSocket _socket= = await PeerFinder.ConnectAsync(selectedPeer); // 创建DataWriter DataWriter _dataWriter = new DataWriter(_socket.OutputStream); // 先写入发送消息的长度 _dataWriter.WriteInt32(message.Length); await _dataWriter.StoreAsync(); // 最后写入发送消息的内容 _dataWriter.WriteString(message); await _dataWriter.StoreAsync();}
蓝牙接收消息
蓝牙编程的接收消息机制同样也是使用的是TCP的StreamSocket的方式,原理与Socket的一致。在蓝牙连接成功后,可以获取到一个StreamSocket类的对象,然后我们使用该对象的InputStream属性来初始化一个DataReader对象,通过DataReader对象来进行接收消息。InputStream属性表示的是Socket的输入流,用于接收对方的消息。下面来看一下接收消息的示例:
async Task<string> GetMessage(){ // 连接选中的对等项,selectedPeer为查找到的PeerInformation对象 StreamSocket _socket= = await PeerFinder.ConnectAsync(selectedPeer); // 创建DataReader DataReader _dataReader = new DataReader(_socket.InputStream); // 先读取消息的长度 await _dataReader.LoadAsync(4); uint messageLen = (uint)_dataReader.ReadInt32(); // 最后读取消息的内容 await _dataReader.LoadAsync(messageLen); return _dataReader.ReadString(messageLen); }
实例:实现蓝牙程序对程序的传输
下面给出蓝牙程序对程序传输的示例:通过使用蓝牙功能查找周边也要使用改应用的手机,互相建立起连接和发送测试消息。
代码清单19-1:蓝牙程序对程序传输(源代码:第19章/Examples_19_1)
MainPage.xaml文件主要代码
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel> <Button x:Name="btFindBluetooth" Content="通过蓝牙查找该应用设备" Click="btFindBluetooth_Click"/> <ListBox x:Name="lbBluetoothApp" ItemsSource="{Binding}" >
<ListBox.ItemTemplate
> <DataTemplate> <StackPanel> <TextBlock Text="{Binding DisplayName}"
/> <TextBlock Text="{Binding ServiceName}"
/> <Button Content="连接" HorizontalAlignment="Left"
Width="308"
Height="91"
Click="btConnect_Click"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Grid>
MainPage.xaml.cs文件主要代码
using System;using System.Windows;using System.Windows.Controls;using Microsoft.Phone.Controls;using Windows.Networking.Proximity;using Windows.Networking.Sockets;using Windows.Storage.Streams;namespace BluetoothDemo{ public
partial class MainPage : PhoneApplicationPage {
private StreamSocket _socket = null; // Socket数据流对象
private DataWriter _dataWriter; // 数据写入对象
private DataReader _dataReader; // 数据读取对象 public
MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;//页面加载事件 }
// 查找蓝牙对等项按钮事件处理 private async void btFindBluetooth_Click(object
sender, RoutedEventArgs e) { try
{ //开始查找对等项 PeerFinder.Start(); // 等待找到的对等项 var peers = await PeerFinder.FindAllPeersAsync(); if
(peers.Count == 0) { MessageBox.Show("没有发现对等的蓝牙应用"); } else { // 把对等项目绑定到列表中 lbBluetoothApp.ItemsSource
= peers; } } catch(Exception ex)
{ if ((uint)ex.HResult
== 0x8007048F) { MessageBox.Show("Bluetooth已关闭请打开手机的蓝牙开关"); } else {
MessageBox.Show(ex.Message); } } }
// 连接蓝牙对等项的按钮事件处理 private
async void
btConnect_Click(object sender,
RoutedEventArgs e) { Button deleteButton = sender
as Button; PeerInformation selectedPeer =
deleteButton.DataContext as PeerInformation;
// 连接到选择的对等项 _socket = await
PeerFinder.ConnectAsync(selectedPeer); //
使用输出输入流建立数据读写对象 _dataReader = new
DataReader(_socket.InputStream); _dataWriter = new DataWriter(_socket.OutputStream); //
开始读取消息 PeerFinder_StartReader(); }
// 读取消息 async void PeerFinder_StartReader() {
try { uint
bytesRead = await _dataReader.LoadAsync(sizeof(uint)); if (bytesRead > 0)
{ // 获取消息内容的大小 uint strLength = (uint)_dataReader.ReadUInt32(); bytesRead = await _dataReader.LoadAsync(strLength); if (bytesRead > 0)
{ String
message = _dataReader.ReadString(strLength); MessageBox.Show("获取到消息:" + message); // 开始下一条消息读取
PeerFinder_StartReader(); } else { MessageBox.Show("对方已关闭连接"); } } else { MessageBox.Show("对方已关闭连接"); } } catch (Exception
e) { MessageBox.Show("读取失败: " + e.Message); } }
// 页面加载事件处理 void
MainPage_Loaded(object sender,
RoutedEventArgs e) { //
订阅连接请求事件 PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested; }
// 连接请求事件处理 void
PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args) { //
连接并且发送消息 ConnectToPeer(args.PeerInformation); }
// 连接并发送消息给对方 async void ConnectToPeer(PeerInformation
peer) { _socket = await PeerFinder.ConnectAsync(peer); _dataReader = new DataReader(_socket.InputStream); _dataWriter = new DataWriter(_socket.OutputStream); string
message = "测试消息"; uint strLength = _dataWriter.MeasureString(message); _dataWriter.WriteUInt32(strLength);//写入消息的长度
_dataWriter.WriteString(message);//写入消息的内容 uint
numBytesWritten = await _dataWriter.StoreAsync();
} }}
程序的运行效果如图19.2所示。
实例:实现蓝牙程序对设备的连接
下面给出蓝牙程序对设备连接的示例:查找蓝牙设备,并对找到的第一个蓝牙设备进行连接。
代码清单19-2:蓝牙程序对设备连接(源代码:第19章/Examples_19_2)
MainPage.xaml文件主要代码
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel> <Button x:Name="btFindBluetooth" Content="连接周围的蓝牙设备" Click="btFindBluetooth_Click"/> </StackPanel> </Grid>
MainPage.xaml.cs文件主要代码
// 查找蓝牙设备事件处理
private async
void btFindBluetooth_Click(object sender,
RoutedEventArgs e) { try
{ //
配置PeerFinder蓝牙服务的GUID去搜索设备 PeerFinder.AlternateIdentities["Bluetooth:SDP"] = "5bec6b8f-7eba-4452-bf59-1a510745e99d"; var peers = await PeerFinder.FindAllPeersAsync(); if
(peers.Count == 0) { Debug.WriteLine("没发现蓝牙设备"); } else { // 连接找到的第一个蓝牙设备 PeerInformation
selectedPeer = peers[0]; StreamSocket
socket = new StreamSocket(); await socket.ConnectAsync(selectedPeer.HostName,
selectedPeer.ServiceName);
MessageBox.Show("连接上了HostName:" + selectedPeer.HostName + "ServiceName:"
+ selectedPeer.ServiceName); } } catch
(Exception ex) { if
((uint)ex.HResult == 0x8007048F)
{
MessageBox.Show("Bluetooth is
turned off"); } } }
基本就是这些了。文章里的一些代码取自一个叫麦子学院的IT在线教育平台,这里注明一下。
Windows Phone 8 蓝牙编程的更多相关文章
- C# 蓝牙编程
C#进行蓝牙编程 本节我们给大家用源码的形式给大家介绍如何用C#调用蓝牙.下面的源码是基于destop的C#调用蓝牙的程序,也就是使用普通版本的.NET Framework来调用编程,一般是有蓝牙的笔 ...
- 用C#调用蓝牙编程
2013-04-22 09:41:06 什么是蓝牙? 现在只能手机这么发达,蓝牙对我们来说肯定不陌生.我来介绍一下官方概念: 蓝牙,是一种支持设备短距离通信(一般10m内)的无线电技术.能在包括移动电 ...
- Linux下TCP网络编程与基于Windows下C#socket编程间通信
一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...
- winsock教程- windows下的socket编程(c语言实现)
winsock教程- windows下的socket编程(c语言实现) 使用winsock进行socket 编程 这是一个学习windows下socket编程(c语言)的快速指南.这是因为一下 ...
- 在windows下的QT编程中的_TCHAR与QString之间的转换
由于在windows下的QT编程中,如果涉及到使用微软的API,那么不可避免使用_TCHAR这些类型,因此在网上查了一下,其中一个老外的论坛有人给出了这个转换,因此在这里做一下笔记 : )#ifdef ...
- Windows环境下多线程编程原理与应用读书笔记(1)————基本概念
自从学了操作系统知识后,我就对多线程比较感兴趣,总想让自己写一些有关多线程的程序代码,但一直以来,发现自己都没怎么好好的去全面学习这方面的知识,仅仅是完成了操作系统课程上的小程序,对多线程的理解也不是 ...
- Windows应用程序组成及编程步骤
Windows应用程序组成及编程步骤: 1.应用程序的组成:一个完整的Windows应用程序通常由五种类型的文件组成 1.C语言源程序文件 2.头文件 3.模块定义文件 4.资源描述文件 5.项目文件 ...
- 使用Windows API进行串口编程
使用Windows API进行串口编程 串口通信一般分为四大步:打开串口->配置串口->读写串口->关闭串口,还可以在串口上监听读写等事件.1.打开和关闭串口Windows中串口 ...
- android 蓝牙编程重点---如何发送和接收16进制数据
最近的android蓝牙开发项目也逐渐接近尾声,基本的功能都已经完成,只剩下界面的设计.现在真的是舒了一口气! 作为编程学习经验只有1年的菜鸟,这是我独自完成的商业性产品,而且还是涉及到与单片机蓝牙模 ...
随机推荐
- MySQL 5.7 深度解析: JSON数据类型使用
http://www.actionsky.com/docs/archives/156 2015年12月25日 杨涛涛 JSON (JavaScriptObject Notation) 是一种轻量级 ...
- springMVC与struts2的区别
1. 机制:spring mvc的入口是servlet,而struts2是filter,这样就导致了二者的机制不同. 2. 性能:spring会稍微比struts快.spring mvc是基于方法的设 ...
- jq实现地址级联效果
(function ($) { $.fn.Address = function (options) { var defaults = { divid: "Address", cal ...
- Ubuntu下安装FTP服务及使用(VSFTPD详细设置)(二)
vsftpd 作为一个主打安全的FTP服务器,有很多的选项设置.下面介绍了vsftpd的配置文件列表,而所有的配置都是基于vsftpd.conf这个配置文件 的.本文将提供完整的vsftpd.conf ...
- VC6.0常见编译错误提示
原文:http://c.biancheng.net/cpp/html/746.html 1) error C2001: newline in constant 编号:C2001 直译:在常量中出现了换 ...
- 通过layer的contents属性来实现uiimageview的淡入切换
#import "ViewController.h" @interface ViewController () @property(nonatomic,strong)CALayer ...
- #技塑人生# windows2008无法远程— 注册表缺失键值导致高级防火墙服务异常
windows2008无法远程— 注册表缺失键值导致高级防火墙服务异常 阿里云技术支持中心:章阿贵 一.远程无法访问(windows server 2008) 症状:无法远程但是系统内网络正常,防火墙 ...
- 【Shell脚本学习20】Shell until循环
until 循环执行一系列命令直至条件为 true 时停止.until 循环与 while 循环在处理方式上刚好相反.一般while循环优于until循环,但在某些时候,也只是极少数情况下,until ...
- 监控服务器JVM内存运行
使用jdk的jconsole进行监控jmx 首先,设置监控对象的端口 配置 catalina.sh #vi /usr/tomcat/bin/catalina.sh 注: /usr/tomcat/b ...
- find中的 time 参数
find手册中对time的解释:以 atime 为例: -atime n File was last accessed n*24 hours ago. When find figures out ho ...