Windows phone 8 学习笔记(3) 通信




Windows phone 8 可利用的数据通信方式比较广泛,在硬件支持的前提下,我们可以利用WiFi、蓝牙、临近感应等多种方式。数据交互一般通过套接字来完成,我们将在本文详细的分析。
快速导航:
一、WP8套接字
二、蓝牙
三、NFC
四、获取网络状态
五、访问web的几种方式
一、WP8套接字
1)创建套接字客户端
Windows phone 8中的套接字并不支持发布服务端,我们只能利用它在手机上创建套接字客户端,我们在此例中要用套接字去访问web服务器。首先,我们定义一个SocketClient来表示套接字客户端。
[C#]
  1. public class SocketClient
  2. {

  3. //缓存套接字对象以便在整个生命周期重用
  4. Socket _socket = null;

  5. // 信号通知对象,用于异步操作完成通知
  6. static ManualResetEvent _clientDone = new ManualResetEvent(false);

  7. /// <summary>
  8. /// 为每个异步调用设置超时时间
  9. /// </summary>
  10. const int TIMEOUT_MILLISECONDS = 30000;

  11. /// <summary>
  12. /// 数据缓冲区大小
  13. /// </summary>
  14. const int MAX_BUFFER_SIZE = 2048 * 100;

  15. /// <summary>
  16. /// 关闭套接字连接和释放所有相关的资源
  17. /// </summary>
  18. public void Close()
  19. {
  20. if (_socket != null)
  21. {
  22. _socket.Close();
  23. }
  24. }
  25. }
复制代码
这个客户端包含连接服务器、发送信息和接受信息三个方法。我们将如下代码加入SocketClient类:
    连接:
[C#]
  1. /// <summary>
  2. /// 尝试用TCP套接字连接到指定主机端口
  3. /// </summary>
  4. /// <param name="hostName">主机名</param>
  5. /// <param name="portNumber">端口号</param>
  6. /// <returns>描述连接结果</returns>
  7. public string Connect(string hostName, int portNumber)
  8. {
  9. string result = string.Empty;

  10. //创建一个终结点,主机名、端口号
  11. DnsEndPoint hostEntry = new DnsEndPoint(hostName, portNumber);

  12. //创建一个基于流,TCP套接字。
  13. _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  14. //套接字上下文
  15. SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
  16. socketEventArg.RemoteEndPoint = hostEntry;

  17. socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
  18. {
  19. //执行的状态信息
  20. result = e.SocketError.ToString();
  21. //将当前线程设置为收到信息状态,这样被阻止的线程可以继续执行
  22. _clientDone.Set();
  23. });

  24. //标识当前进程为未收到信息状态
  25. _clientDone.Reset();

  26. // 发送一个异步连接请求
  27. _socket.ConnectAsync(socketEventArg);
  28. //将当前线程阻止,直到当前线程收到信息或者超时时间已到
  29. _clientDone.WaitOne(TIMEOUT_MILLISECONDS);

  30. return result;
  31. }
复制代码
发送消息:
[C#]
  1. /// <summary>
  2. /// 向连接的服务器发送信息
  3. /// </summary>
  4. /// <param name="data">数据正文</param>
  5. /// <returns>反馈</returns>
  6. public string Send(string data)
  7. {
  8. string response = "操作超时";

  9. //套接字是否准备好
  10. if (_socket != null)
  11. {
  12. //套接字上下文
  13. SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();

  14. socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
  15. socketEventArg.UserToken = null;

  16. socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
  17. {
  18. response = e.SocketError.ToString();
  19. _clientDone.Set();
  20. });
  21. byte[] payload = Encoding.UTF8.GetBytes(data);
  22. socketEventArg.SetBuffer(payload, 0, payload.Length);
  23. _clientDone.Reset();
  24. _socket.SendAsync(socketEventArg);
  25. _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
  26. }
  27. else
  28. {
  29. response = "套接字没有准备好";
  30. }

  31. return response;
  32. }
复制代码
接受消息:
[C#]
  1. /// <summary>
  2. /// 从连接服务器接收数据
  3. /// </summary>
  4. /// <returns>The data received from the server</returns>
  5. public string Receive()
  6. {
  7. string response = "操作超时";

  8. if (_socket != null)
  9. {
  10. SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
  11. socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;

  12. //设置接收数据的缓冲区
  13. socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE);

  14. socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
  15. {
  16. if (e.SocketError == SocketError.Success)
  17. {
  18. // Retrieve the data from the buffer
  19. response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
  20. response = response.Trim('\0');
  21. }
  22. else
  23. {
  24. response = "错误:" + e.SocketError.ToString();
  25. }

  26. _clientDone.Set();
  27. });

  28. _clientDone.Reset();
  29. _socket.ReceiveAsync(socketEventArg);
  30. _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
  31. }
  32. else
  33. {
  34. response = "套接字没有准备好";
  35. }

  36. return response;
  37. }
复制代码
2)通过套接字访问HTTP网站
现在我们有了套接字客户端,这个时候我们来做一个类似于浏览器的功能,我们模拟HTTP请求发送到web服务器,代码如下:
[XAML]
  1. <!--LayoutRoot 是包含所有页面内容的根网格-->
  2. <Grid x:Name="LayoutRoot" Background="Transparent">
  3. <Grid.RowDefinitions>
  4. <RowDefinition Height="Auto"/>
  5. <RowDefinition Height="*"/>
  6. </Grid.RowDefinitions>
  7. <!--TitlePanel 包含应用程序的名称和页标题-->
  8. <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
  9. <TextBlock x:Name="ApplicationTitle" Text="套接字访问web" Style="{StaticResource PhoneTextNormalStyle}"/>
  10. </StackPanel>
  11. <!--ContentPanel - 在此处放置其他内容-->
  12. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  13. <TextBox x:Name="textbox1" HorizontalAlignment="Left" Height="72" Margin="-10,-17,0,0" TextWrapping="Wrap" Text="www.hao123.com" VerticalAlignment="Top" Width="395"/>
  14. <Button Content="转到" HorizontalAlignment="Left" Margin="364,-17,-9,0" VerticalAlignment="Top" Click="Button_Click_1"/>
  15. </Grid>
  16. <ScrollViewer Height="649" Width="468" Margin="12,47,0,0" HorizontalAlignment="Left" Grid.Row="1" VerticalAlignment="Top" >
  17. <TextBlock ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible" x:Name="textblok1" Height="649" Width="468" MaxHeight="649" MaxWidth="468" />
  18. </ScrollViewer>
  19. </Grid>
复制代码
[C#]
  1. private void Button_Click_1(object sender, RoutedEventArgs e)
  2. {

  3. string hostName = textbox1.Text.Replace("http://", string.Empty);
  4. SocketClient client = new SocketClient();
  5. //主机,端口号
  6. textblok1.Text = client.Connect(hostName, 80);
  7. //模拟一个HTTP Get请求
  8. textblok1.Text = client.Send("GET http://" + hostName + " HTTP/1.0\r\nHost: " + hostName + "\r\n\r\n\r\n");
  9. //等待相应
  10. textblok1.Text = client.Receive();

  11. }
复制代码
二、蓝牙
WP8蓝牙支持对等方应用连接,也支持其他蓝牙设备,下面我们看看如何连接到对等方应用和设备。
1)连接到对等方
[C#]
  1. //已经搜索到的对等方列表
  2. IReadOnlyList<PeerInformation> peers;

  3. // 开始连接到对等应用
  4. async void AppToApp()
  5. {
  6. // 开始查找对等项,如果有这句话,即可使自己能够被其他蓝牙设备搜索到
  7. PeerFinder.Start();

  8. peers = await PeerFinder.FindAllPeersAsync();

  9. if (peers.Count == 0)
  10. {
  11. // 没有发现
  12. }
  13. else
  14. {
  15. // 选择第一个对等应用
  16. PeerInformation selectedPeer = peers[0];
  17. // 连接到第一个对等方应用
  18. var streamSocket = await PeerFinder.ConnectAsync(selectedPeer);
  19. }
  20. }
复制代码
2)连接到设备
PeerFinder.AlternateIdentities["Bluetooth:Paired"] = ""; 查找所有已配对的设备。这样连接找到的设备对应的PeerInformation.ServiceName将为空,所以我们不能通过PeerFinder.ConnectAsync(selectedPeer);的方式去连接,具体示例如下:
[C#]
  1. //搜寻全部蓝牙设备并连接第一个
  2. private async void AppToDevice()
  3. {
  4. // 搜索所有配对的设备
  5. PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
  6. var pairedDevices = await PeerFinder.FindAllPeersAsync();

  7. if (pairedDevices.Count == 0)
  8. {
  9. //没有发现设备
  10. }
  11. else
  12. {
  13. // 选择第一个连接的设备,此时selectedDevice.ServiceName为空
  14. PeerInformation selectedDevice = pairedDevices[0];

  15. // 主动创建一个StreamSocket
  16. StreamSocket socket = new StreamSocket();
  17. // 第二个参数是一个RFCOMM端口号,范围是1-30
  18. await socket.ConnectAsync(selectedDevice.HostName, "1");
  19. }
  20. }
复制代码
PeerFinder.AlternateIdentities["Bluetooth:SDP"] = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";查找使用服务发现协议 (SDP) 并通过既定 GUID 播发服务的设备
[C#]
  1. //搜寻特定GUID的设备
  2. private async void AppToDevice2()
  3. {
  4. PeerFinder.AlternateIdentities["Bluetooth:SDP"] = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
  5. var pairedDevices = await PeerFinder.FindAllPeersAsync();

  6. if (pairedDevices.Count == 0)
  7. {
  8. //没有发现设备
  9. }
  10. else
  11. {
  12. // 选择第一个连接的设备
  13. PeerInformation selectedDevice = pairedDevices[0];

  14. // 主动创建一个StreamSocket
  15. StreamSocket socket = new StreamSocket();
  16. // 这种情况下selectedDevice.ServiceName等于您指定的GUID
  17. await socket.ConnectAsync(selectedDevice.HostName, selectedDevice.ServiceName);
  18. }
  19. }
复制代码
3)侦听连接请求
[C#]
  1. public Page1()
  2. {
  3. InitializeComponent();
  4. //侦听连接请求需要先添加事件
  5. Loaded += MainPage_Loaded;
  6. }

  7. void MainPage_Loaded(object sender, RoutedEventArgs e)
  8. {
  9. //远程对等类异步连接时触发
  10. PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested;
  11. }
  12. async void PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args)
  13. {
  14. // 获取到请求连接的对等方
  15. var peer = args.PeerInformation;
  16. // 回应连接
  17. var streamSocket = await PeerFinder.ConnectAsync(peer);
  18. }
复制代码
4)发送消息
[C#]
  1. /// <summary>
  2. /// 在已连接的情况下发送消息
  3. /// </summary>
  4. /// <param name="socket"></param>
  5. public async void Send(StreamSocket socket, string msg)
  6. {
  7. var _dataWriter = new DataWriter(socket.OutputStream);

  8. //写入消息的长度
  9. uint strLength = _dataWriter.MeasureString(msg);
  10. _dataWriter.WriteUInt32(strLength);

  11. //写入消息的内容
  12. _dataWriter.WriteString(msg);
  13. uint numBytesWritten = await _dataWriter.StoreAsync();
  14. }
复制代码
5)接收消息
[C#]
  1. /// <summary>
  2. /// 在已连接的情况下读取消息
  3. /// </summary>
  4. /// <param name="socket"></param>
  5. public async Task<string> Read(StreamSocket socket)
  6. {
  7. var _dataReader = new DataReader(socket.InputStream);
  8. // 读取消息长度
  9. await _dataReader.LoadAsync(sizeof(uint));
  10. uint msgLength = (uint)_dataReader.ReadUInt32();
  11. // 读取消息的内容
  12. await _dataReader.LoadAsync(msgLength);
  13. return _dataReader.ReadString(msgLength);
  14. }
复制代码
三、NFC
当两个设备距离较近时,可以使用近场通信技术,本文演示一个使用近场通信制作聊天软件的例子。
[XAML]
  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2. <TextBlock x:Name="textblock1" Text="连接状态:未连接" HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" VerticalAlignment="Top">
  3. </TextBlock>
  4. <TextBox x:Name="textbox1" HorizontalAlignment="Left" Height="72" Margin="0,27,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="386"/>
  5. <Button Content="发送" HorizontalAlignment="Left" Margin="369,29,-9,0" VerticalAlignment="Top" Click="Button_Click_1"/>
  6. <ListBox x:Name="listbox1" Margin="0,100,0,0" Grid.Row="1"/>
  7. </Grid>
复制代码
[C#]
  1. public partial class MainPage : PhoneApplicationPage
  2. {
  3. ProximityDevice device;

  4. long typeId = -1;
  5. long msgId = -1;
  6. public MainPage()
  7. {
  8. InitializeComponent();

  9. device = ProximityDevice.GetDefault();
  10. if (device == null)
  11. {
  12. IsEnabled = false;
  13. textblock1.Text = "您的手机不支持NFC功能";
  14. }
  15. else
  16. {
  17. //设备进入NFC识别范围时触发
  18. device.DeviceArrived += device_DeviceArrived;
  19. //设备离开NFC识别范围时触发
  20. device.DeviceDeparted += device_DeviceDeparted;
  21. }
  22. }

  23. //设备进入NFC识别范围时触发
  24. void device_DeviceArrived(ProximityDevice sender)
  25. {
  26. //创建消息订阅,创建好后就可以直接发消息了
  27. typeId = sender.SubscribeForMessage("Windows.MyMsgType", MsgReceivedHandler);
  28. Dispatcher.BeginInvoke(() => textblock1.Text = "连接状态:已连接");
  29. }

  30. //设备离开NFC识别范围时触发
  31. void device_DeviceDeparted(ProximityDevice sender)
  32. {
  33. if (typeId != -1)
  34. {
  35. //取消消息订阅
  36. sender.StopSubscribingForMessage(typeId);
  37. typeId = -1;
  38. }

  39. Dispatcher.BeginInvoke(() => textblock1.Text = "连接状态:连接中断");
  40. }

  41. /// <summary>
  42. /// 接收到消息后的处理逻辑
  43. /// </summary>
  44. void MsgReceivedHandler(ProximityDevice sender, ProximityMessage message)
  45. {
  46. Dispatcher.BeginInvoke(() =>
  47. {
  48. listbox1.Items.Add(("对方:" + message.DataAsString));
  49. }); 
  50. }

  51. /// <summary>
  52. /// 发送消息按钮按下时
  53. /// </summary>
  54. private void Button_Click_1(object sender, RoutedEventArgs e)
  55. {
  56. if (textbox1.Text != string.Empty)
  57. {
  58. listbox1.Items.Add("我:" + textbox1.Text);

  59. if (msgId != -1)
  60. device.StopPublishingMessage(msgId);

  61. msgId = device.PublishMessage("Windows.MyMsgType", textbox1.Text);
  62. }
  63. }
  64. }
复制代码
现在我们看看在模拟器中的效果,如下图。模拟器中实现NFC的模拟效果请下载:http://proximitytapper.codeplex.com
四、获取网络状态
很多时候,应用可能需要利用到网络,这个时候我们需要获取一些信息,比如网络是否连接,当前是连接到WiFi还是运营商蜂窝网络。这些信息关系到您的应用是否能正常工作,或者是否处于免费网络下可执行高流量下载等操作。
1. 数据感知
数据感知功能可以用来获取网络成本信息以及流量计划,帮助用户合理使用手机流量,我们看看使用方法。
[C#]
  1. var connectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile();

  2. //网络接口类型
  3. var ianaInterfaceType = connectionProfile.NetworkAdapter.IanaInterfaceType;

  4. //连接成本信息
  5. var connectionCost = connectionProfile.GetConnectionCost();

  6. //当前的网络使用成本
  7. var networkCostType = connectionCost.NetworkCostType;
  8. //计划流量是否快用完
  9. var approachingDataLimit = connectionCost.ApproachingDataLimit;
  10. //是否超过计划流量
  11. var overDataLimit = connectionCost.OverDataLimit;
  12. //是否漫游
  13. var roaming = connectionCost.Roaming;
复制代码
2. 网络信息获取
我们可以通过API获取网络接口状态,检查手机数据网络以及WiFi连接情况等。
[XAML]
  1. <!--ContentPanel - 在此处放置其他内容-->
  2. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  3. <TextBlock x:Name="textblock1" HorizontalAlignment="Left" Margin="157,10,0,0" TextWrapping="Wrap" Text="未知" VerticalAlignment="Top"/>
  4. <TextBlock HorizontalAlignment="Left" Margin="17,10,0,0" TextWrapping="Wrap" Text="移动运营商:" VerticalAlignment="Top"/>
  5. <TextBlock x:Name="textblock2" HorizontalAlignment="Left" Margin="154,50,0,0" TextWrapping="Wrap" Text="未知" VerticalAlignment="Top" Height="220" Width="292"/>
  6. <TextBlock HorizontalAlignment="Left" Margin="14,50,0,0" TextWrapping="Wrap" Text="网络信息:" VerticalAlignment="Top"/>
  7. <TextBlock x:Name="textblock3" HorizontalAlignment="Left" Margin="91,275,0,0" TextWrapping="Wrap" Text="未知" VerticalAlignment="Top" Height="182" Width="365"/>
  8. <TextBlock HorizontalAlignment="Left" Margin="17,275,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="106" Width="69">
  9. <Run Text="套接字连接信息:"/>
  10. </TextBlock>
  11. <Button Content="<-" HorizontalAlignment="Left" Margin="370,617,0,0" VerticalAlignment="Top" Width="86" Click="Button_Click_1"/>
  12. </Grid>
复制代码
[c#]
  1. Socket socket;
  2. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  3. {

  4. //移动运营商
  5. textblock1.Text = DeviceNetworkInformation.CellularMobileOperator;



  6. //网络信息
  7. System.Text.StringBuilder sb = new System.Text.StringBuilder();
  8. sb.Append("网络是否可用: ");
  9. sb.AppendLine(DeviceNetworkInformation.IsNetworkAvailable.ToString());
  10. sb.Append("是否启用蜂窝数据: ");
  11. sb.AppendLine(DeviceNetworkInformation.IsCellularDataEnabled.ToString());
  12. sb.Append("是否允许漫游: ");
  13. sb.AppendLine(DeviceNetworkInformation.IsCellularDataRoamingEnabled.ToString());
  14. sb.Append("是否启用Wi-Fi: ");
  15. sb.AppendLine(DeviceNetworkInformation.IsWiFiEnabled.ToString());

  16. //网络接口信息
  17. sb.Append("网络接口类型: ");
  18. var networkInterfaceType = NetworkInterface.NetworkInterfaceType;
  19. var networkInterfaceTypeString = networkInterfaceType.ToString() + "(" + InterfaceTypeConvert.Convert(networkInterfaceType) + ")";
  20. sb.AppendLine(networkInterfaceTypeString);

  21. sb.Append("网络接口子类型: ");
  22. var networkSubInterfaceTypeString = string.Empty;
  23. DeviceNetworkInformation.ResolveHostNameAsync(new DnsEndPoint("www.baidu.com", 80),
  24. new NameResolutionCallback(x =>
  25. {
  26. networkSubInterfaceTypeString = x.NetworkInterface.InterfaceSubtype.ToString() + "[" + InterfaceTypeConvert.ConvertSub(x.NetworkInterface.InterfaceSubtype) + "]";

  27. sb.AppendLine(networkSubInterfaceTypeString);
  28. Dispatcher.BeginInvoke(() => { textblock2.Text = sb.ToString(); });
  29. }), null);



  30. //套接字连接信息
  31. DnsEndPoint hostEntry = new DnsEndPoint("www.baidu.com", 80);
  32. socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  33. //设置连接要求,必须为使用蜂窝技术网络
  34. socket.SetNetworkRequirement(NetworkSelectionCharacteristics.Cellular);
  35. SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
  36. socketEventArg.RemoteEndPoint = hostEntry;
  37. socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e1)
  38. {
  39. NetworkInterfaceInfo netInterfaceInfo = socket.GetCurrentNetworkInterface();
  40. StringBuilder sb2 = new StringBuilder();
  41. sb2.AppendLine("最后更新: " + DateTime.Now.ToString());
  42. sb2.Append("网络接口名: ");
  43. sb2.AppendLine(netInterfaceInfo.InterfaceName);
  44. sb2.Append("网络接口状态: ");
  45. sb2.AppendLine(netInterfaceInfo.InterfaceState.ToString());
  46. sb2.Append("网络接口类型: ");
  47. sb2.AppendLine(netInterfaceInfo.InterfaceType.ToString());
  48. sb2.Append("网络接口子类型: ");
  49. sb2.AppendLine(netInterfaceInfo.InterfaceSubtype.ToString());
  50. Dispatcher.BeginInvoke(() => textblock3.Text = sb2.ToString());
  51. });
  52. socket.ConnectAsync(socketEventArg);



  53. base.OnNavigatedTo(e);
  54. }

  55. private void Button_Click_1(object sender, RoutedEventArgs e)
  56. {
  57. NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
  58. }
复制代码
3. 检测网络状态改变
手机的网络连接并不如电脑稳定,当你到信号不好的地方,或者自动连接上WiFi等情况,怎么通过代码自动监测呢,下面演示了当手机网络改变时,列举出日志清单,并实时刷新网络信息。
[XAML]
  1. <!--LayoutRoot 是包含所有页面内容的根网格-->
  2. <Grid x:Name="LayoutRoot" Background="Transparent">
  3. <Grid.RowDefinitions>
  4. <RowDefinition Height="Auto"/>
  5. <RowDefinition Height="*"/>
  6. </Grid.RowDefinitions>

  7. <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
  8. <TextBlock x:Name="ApplicationTitle" Text="网络状态改变测试" Style="{StaticResource PhoneTextNormalStyle}"/>
  9. </StackPanel>

  10. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  11. <Grid.RowDefinitions>
  12. <RowDefinition Height="Auto"/>
  13. <RowDefinition Height="Auto"/>
  14. <RowDefinition Height="Auto"/>
  15. <RowDefinition Height="*"/>
  16. <RowDefinition Height="Auto"/>
  17. <RowDefinition Height="Auto"/>
  18. <RowDefinition Height="Auto"/>
  19. </Grid.RowDefinitions>
  20. <TextBlock Grid.Row="0" Text="可用的网络接口" FontSize="{StaticResource PhoneFontSizeLarge}"/>
  21. <ListBox Grid.Row="1" x:Name="lbNetworkInterfaces" ItemsSource="{Binding}" Background="LightGray" >
  22. <ListBox.ItemTemplate>
  23. <DataTemplate>
  24. <TextBlock Text="{Binding}" Margin="5,5,0,5" Foreground="Black"/>
  25. </DataTemplate>
  26. </ListBox.ItemTemplate>
  27. </ListBox>
  28. <TextBlock Grid.Row="2" Text="事件日志" FontSize="{StaticResource PhoneFontSizeLarge}"/>
  29. <ScrollViewer Grid.Row="3" Background="LightGray" BorderThickness="1">
  30. <ListBox x:Name="lbNetworkChanges" ItemsSource="{Binding}">
  31. <ListBox.ItemTemplate>
  32. <DataTemplate>
  33. <TextBlock Text="{Binding}" Foreground="Black"
  34. FontSize="{StaticResource PhoneFontSizeNormal}" TextWrapping="Wrap" Margin="5,10,0,10" />
  35. </DataTemplate>
  36. </ListBox.ItemTemplate>
  37. </ListBox>
  38. </ScrollViewer>
  39. <TextBlock Grid.Row="4" Text="网络状态" FontSize="{StaticResource PhoneFontSizeLarge}"/>
  40. <Grid Grid.Row="5" Background="LightGray" >
  41. <Grid.RowDefinitions>
  42. <RowDefinition Height="Auto"/>
  43. <RowDefinition Height="Auto"/>
  44. <RowDefinition Height="Auto"/>
  45. </Grid.RowDefinitions>
  46. <Grid.ColumnDefinitions>
  47. <ColumnDefinition Width="Auto"/>
  48. <ColumnDefinition Width="*"/>
  49. </Grid.ColumnDefinitions>
  50. <TextBlock Grid.Row="0" Grid.Column="0" Text="网络是否可用" Foreground="Black" Margin="5,5,0,5" />
  51. <TextBlock Grid.Row="0" Grid.Column="1" x:Name="tbIsNetworkAvailable" HorizontalAlignment="Center" Foreground="Black" />

  52. <TextBlock Grid.Row="1" Grid.Column="0" Foreground="Black" Margin="5,5,0,5" >
  53. <Run Text="WiFi是否可用"/>
  54. </TextBlock>
  55. <TextBlock Grid.Row="1" Grid.Column="1" x:Name="tbIsWiFiEnabled" HorizontalAlignment="Center" Foreground="Black"/>

  56. <TextBlock Grid.Row="2" Grid.Column="0" Text="是否启用蜂窝数据" Foreground="Black" Margin="5,5,0,5" />
  57. <TextBlock Grid.Row="2" Grid.Column="1" x:Name="tbIsCellularDataEnabled" HorizontalAlignment="Center" Foreground="Black"/>
  58. </Grid>
  59. <Button Grid.Row="6" x:Name="btnChangeNetworkSettings" Content="飞行" Click="Button_Click_3" Margin="314,0,46,0"/>
  60. <Button Content="->" Margin="391,0,-15,0" Grid.Row="6" Click="Button_Click_1"/>
  61. <Button Content="刷新" Margin="-15,0,370,0" Grid.Row="6" Click="Button_Click_2"/>
  62. <Button Content="WiFi" Margin="66,0,288,0" Grid.Row="6" Click="Button_Click_3" />
  63. <Button Content="网络" Margin="150,0,204,0" Grid.Row="6" Click="Button_Click_3" />
  64. <Button Content="蓝牙" Margin="232,0,122,0" Grid.Row="6" Click="Button_Click_3" />
  65. </Grid>
  66. </Grid>
复制代码
[c#]
  1. public partial class Page1 : PhoneApplicationPage
  2. {

  3. public ObservableCollection<string> Changes { get; set; }

  4. public ObservableCollection<string> NetworkInterfaces { get; set; }

  5. public Page1()
  6. {
  7. InitializeComponent();


  8. // 网络可用性改变事件日志
  9. Changes = new ObservableCollection<string>();
  10. lbNetworkChanges.DataContext = Changes;

  11. //当前可用的网络接口
  12. NetworkInterfaces = new ObservableCollection<string>();
  13. lbNetworkInterfaces.DataContext = NetworkInterfaces;
  14. //网络可用性改变时
  15. DeviceNetworkInformation.NetworkAvailabilityChanged += new EventHandler<NetworkNotificationEventArgs>(ChangeDetected);

  16. UpdateNetworkInterfaces();
  17. UpdateNetworkStatus();
  18. }

  19. void ChangeDetected(object sender, NetworkNotificationEventArgs e)
  20. {
  21. string change = string.Empty;
  22. switch (e.NotificationType)
  23. {
  24. case NetworkNotificationType.InterfaceConnected:
  25. change = "连接: ";
  26. break;
  27. case NetworkNotificationType.InterfaceDisconnected:
  28. change = "断开: ";
  29. break;
  30. case NetworkNotificationType.CharacteristicUpdate:
  31. change = "变更: ";
  32. break;
  33. default:
  34. change = "未知: ";
  35. break;
  36. }

  37. string changeInformation = String.Format(" {0} {1} {2} ({3})",
  38. DateTime.Now.ToShortTimeString(), change, e.NetworkInterface.InterfaceName,
  39. InterfaceTypeConvert.Convert(e.NetworkInterface.InterfaceType) + "," + InterfaceTypeConvert.ConvertSub(e.NetworkInterface.InterfaceSubtype));

  40. Dispatcher.BeginInvoke(() =>
  41. {
  42. Changes.Add(changeInformation);
  43. UpdateNetworkStatus();
  44. UpdateNetworkInterfaces();

  45. });

  46. }

  47. //更新网络接口
  48. private void UpdateNetworkInterfaces()
  49. {

  50. NetworkInterfaces.Clear();
  51. //获取网络接口列表
  52. NetworkInterfaceList networkInterfaceList = new NetworkInterfaceList();
  53. foreach (NetworkInterfaceInfo networkInterfaceInfo in networkInterfaceList)
  54. {
  55. NetworkInterfaces.Add(String.Format("{0} ({1},{2})",
  56. networkInterfaceInfo.InterfaceName,
  57. InterfaceTypeConvert.Convert(networkInterfaceInfo.InterfaceType),
  58. InterfaceTypeConvert.ConvertSub(networkInterfaceInfo.InterfaceSubtype)));
  59. }
  60. }

  61. //更新网络状态
  62. private void UpdateNetworkStatus()
  63. {
  64. tbIsCellularDataEnabled.Text = (DeviceNetworkInformation.IsCellularDataEnabled) ? "是" : "否";
  65. tbIsNetworkAvailable.Text = (DeviceNetworkInformation.IsNetworkAvailable) ? "是" : "否";
  66. tbIsWiFiEnabled.Text = (DeviceNetworkInformation.IsWiFiEnabled) ? "是" : "否";
  67. }

  68. //连接设置
  69. private void Button_Click_3(object sender, RoutedEventArgs e)
  70. {
  71. var settringTypeString = string.Empty;
  72. var button = sender as Button;
  73. if (button != null) settringTypeString = Convert.ToString(button.Content);
  74. var settringType = ConnectionSettingsType.WiFi;
  75. switch (settringTypeString)
  76. {
  77. case "飞行": settringType = ConnectionSettingsType.AirplaneMode;
  78. break;
  79. case "网络": settringType = ConnectionSettingsType.Cellular;
  80. break;
  81. case "蓝牙": settringType = ConnectionSettingsType.Bluetooth;
  82. break;
  83. default: break;
  84. }

  85. //连接设置选择框
  86. ConnectionSettingsTask connectionSettings = new ConnectionSettingsTask();

  87. // 连接设置的类型
  88. connectionSettings.ConnectionSettingsType = settringType;
  89. connectionSettings.Show();
  90. }

  91. //刷新
  92. private void Button_Click_2(object sender, RoutedEventArgs e)
  93. {
  94. UpdateNetworkStatus();
  95. UpdateNetworkInterfaces();
  96. Changes.Clear();
  97. }

  98. private void Button_Click_1(object sender, RoutedEventArgs e)
  99. {
  100. NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
  101. }

  102. }
复制代码
五、访问web的几种方式
Windows phone中访问Internet的方式主要有:通过套接字、WebClient 类、HttpWebRequest 类、服务引用等。套接字我们已经讲过。我主要讲解后面三种。
WebClient 类:一般用于通过访问URL获取特定的资源,下面是使用方法:
[C#]
  1. WebClient webClient = new WebClient();

  2. webClient.DownloadStringAsync(new Uri("http://www.baidu.com", UriKind.Absolute));
  3. webClient.DownloadStringCompleted += (a, b) =>
  4. {
  5. if (b.Error == null && !b.Cancelled)
  6. {
  7. Dispatcher.BeginInvoke(() => MessageBox.Show(b.Result));
  8. }
  9. };
复制代码
HttpWebRequest 类:对http做了基本的实现,相当于比直接用socket方便一点。
[C#]
  1. Uri uri = new Uri("http://192.168.100.212");
  2. HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
  3. httpWebRequest.Method = "POST";
  4. //异步获取HTTP请求正文流
  5. httpWebRequest.BeginGetRequestStream(new AsyncCallback(a =>
  6. {
  7. var httpWebRequest2 = a.AsyncState as HttpWebRequest;
  8. var stream = httpWebRequest2.EndGetRequestStream(a);
  9. var streamWriter = new StreamWriter(stream);
  10. //在HTTP请求正文流中写入要POST的参数
  11. streamWriter.WriteLine("wd=111");
  12. streamWriter.Close();
  13. //开始异步的向远程主机发送HTTP请求
  14. httpWebRequest2.BeginGetResponse(new AsyncCallback(b =>
  15. {
  16. try
  17. {
  18. var httpWebRequest3 = b.AsyncState as HttpWebRequest;
  19. //请求执行完成,得到HTTP相应
  20. WebResponse webResponse = httpWebRequest3.EndGetResponse(b);
  21. var s = webResponse.ContentType;
  22. //获取到HTTP相应正文流
  23. var stream3 = webResponse.GetResponseStream();
  24. //读出来,转换成字符串
  25. var streamReader = new StreamReader(stream3, Encoding.UTF8);
  26. var text = streamReader.ReadToEnd();

  27. Dispatcher.BeginInvoke(() => MessageBox.Show(text));
  28. }
  29. catch (Exception ex)
  30. {
  31. var c = ex.Message;
  32. }

  33. }), httpWebRequest2);

  34. }), httpWebRequest);
复制代码
服务引用:其实于一般的服务引用一样,只不过这里只支持异步实现。
[C#]
  1. //添加服务引用后,下面代码为异步调用web服务
  2. ServiceReference1.WebService1SoapClient c = new ServiceReference1.WebService1SoapClient();
  3. c.HelloWorldAsync("");
  4. c.HelloWorldCompleted += (a, b) =>
  5. {
  6. Dispatcher.BeginInvoke(() => MessageBox.Show(b.Result));
  7. };
复制代码
 wp8_3_1.zip (25.8 KB, 下载次数: 8) 
 wp8_3_4.zip (40.8 KB, 下载次数: 9) 
 wp8_3_3.zip (67.29 KB, 下载次数: 6) 
 wp8_3_2.zip (61.16 KB, 下载次数: 5) 

06142324-13538e49d4d54d9fa3a7df3342879b6f.jpg (149.42 KB, 下载次数: 2)

06142324-13538e49d4d54d9fa3a7df3342879b6f.jpg
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值