MSDN Library
信息
您所需的主题如下所示。但此主题未包含在此库中。

如何检测 Windows Phone 8 的网络更改

2014/6/18

适用于:Windows Phone 8 和 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

 

当创建 Windows Phone 应用时,您可能希望知道可用网络何时发生更改。例如,当您的应用进入已知 WLAN 网络覆盖范围内时,可能发生此种情况。 如果该网络突然变得可用,则您的应用就有机会充分利用此高带宽网络接口进行通信。您可以通过注册 NetworkAvailabilityChanged 事件监听网络可用性的更改。本主题介绍如何注册此事件,以及当激发该事件时如何解释网络更改的内容。

本主题包括以下部分。

 

在本节中,您将创建用于演示如何接收和显示网络可用性更改的 UI。当应用启动时,它会列出所有可用的网络接口。它还会订阅以接收网络可用性更改的通知。当发生更改时,将会激发 NetworkAvailabilityChanged 事件。该应用会处理此事件,并将更改输出为 UI 上列表的一个字符串。该应用还会提供一种启动 ConnectionSettingsTask 以手动打开或关闭网络设置的方式。

创建应用 UI

  1. 在 Visual Studio 中,通过选择“文件” | “新建项目”菜单命令创建新的项目。

  2. 将显示“新建项目”窗口。展开“Visual C#”模板,然后选择“Windows Phone”模板。

  3. 选择 Windows Phone 应用  模板。在“名称”中填入您选择的名称。

  4. 单击“确定”。将创建一个新的项目,并且“MainPage.xaml”将在 Visual Studio 设计器窗口中打开。

  5. “MainPage.xaml”中,删除名为“LayoutRoot”的 Grid 的 XAML 代码,然后使用以下代码进行替换:

    
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="Network Change Detector" Style="{StaticResource PhoneTextNormalStyle}"/>
        </StackPanel>
    
        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" Text="Available Network Interfaces" FontSize="{StaticResource PhoneFontSizeLarge}"/>
            <ListBox Grid.Row="1" x:Name="lbNetworkInterfaces" ItemsSource="{Binding}" Background="LightGray" >
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" Margin="5,5,0,5" Foreground="Black"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <TextBlock Grid.Row="2" Text="Events" FontSize="{StaticResource PhoneFontSizeLarge}"/>
            <ScrollViewer Grid.Row="3" Background="LightGray" BorderThickness="1">
                <ListBox x:Name="lbNetworkChanges" ItemsSource="{Binding}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding}" Foreground="Black" 
                                        FontSize="{StaticResource PhoneFontSizeNormal}" TextWrapping="Wrap" Margin="5,10,0,10"  />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </ScrollViewer>
            <TextBlock Grid.Row="4" Text="Networking Status" FontSize="{StaticResource PhoneFontSizeLarge}"/>
            <Grid Grid.Row="5" Background="LightGray" >
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.Column="0" Text="IsNetworkAvailable" Foreground="Black" Margin="5,5,0,5" />
                <TextBlock Grid.Row="0" Grid.Column="1" x:Name="tbIsNetworkAvailable" HorizontalAlignment="Center" Foreground="Black" />
                    
                <TextBlock Grid.Row="1" Grid.Column="0" Text="IsWiFiEnabled" Foreground="Black" Margin="5,5,0,5" />
                <TextBlock Grid.Row="1" Grid.Column="1" x:Name="tbIsWiFiEnabled" HorizontalAlignment="Center" Foreground="Black"/>
                    
                <TextBlock Grid.Row="2" Grid.Column="0" Text="IsCellularDataEnabled" Foreground="Black" Margin="5,5,0,5" />
                <TextBlock Grid.Row="2" Grid.Column="1" x:Name="tbIsCellularDataEnabled" HorizontalAlignment="Center" Foreground="Black"/>
            </Grid>
            <Button Grid.Row="6" x:Name="btnChangeNetworkSettings" Content="Change Network Settings" Click="btnChangeNetworkSettings_Click"/>
        </Grid>
    </Grid>
    
    
    

    前面的 XAML 代码会创建一个类似于以下屏幕快照的简单用户界面。

    Network Detector User Interface

    UI 分为四个部分。在屏幕的顶端,我们将会显示所有可用的网络接口。可以从 NetworkInterfaceList 集合中检索此数据。在应用启动后,只要应用接收到 NetworkAvailabilityChanged 事件,就会加载它。屏幕的下一部分将会显示有关应用接收的关于任何 NetworkAvailabilityChanged 事件的信息。屏幕的下一部分会显示手机网络功能的整体状态。最后,屏幕的底端会显示一个按钮,该按钮用于启动 ConnectionSettingsTask 以手动更改网络设置,并激发 NetworkAvailabilityChanged 事件。以下各节中介绍了驱动此 UI 的代码。

为了检测网络可用性的更改,应用会注册 NetworkAvailabilityChanged 事件。

注册网络可用性更改

  1. 打开“MainPage”的代码隐藏文件,并将下列 using 指令添加到页面的顶部。

    
    using System.Collections.ObjectModel;
    using Microsoft.Phone.Net.NetworkInformation;
    using Microsoft.Phone.Tasks;
    
    
  2. 在 MainPage 类顶部添加以下变量声明。

    
    // List of all changes detected while the app is running.
    public ObservableCollection<string> Changes { get; set; }
    
    // List of all currently available network interfaces
    public ObservableCollection<string> NetworkInterfaces { get; set; }
    
    
    
  3. 使用下面的代码替换代码隐藏类中的 MainPage 构造函数。此方法会初始化页面,将 UI 绑定到上一个步骤中声明的列表并订阅 NetworkAvailabilityChanged 事件。此事件的回调方法被定义为 ChangeDetected,并且这会在后续步骤中进行介绍。最后,它会调用两种方法以初始化 UI 的“网络接口”“网络状态”区域。这些方法会在后面的步骤中定义。现在我们已经注册了网络可用性更改。下一节介绍如何解释检测的更改。

    
    // Constructor
    public MainPage()
    {
        InitializeComponent();
    
        // Initialise the Changes list.
        Changes = new ObservableCollection<string>();
    
        // Bind the ListBox to the Changes list
        lbNetworkChanges.DataContext = Changes;
    
        NetworkInterfaces = new ObservableCollection<string>();
        lbNetworkInterfaces.DataContext = NetworkInterfaces;
    
        // Subscribe to the NetworkAvailabilityChanged event
        DeviceNetworkInformation.NetworkAvailabilityChanged += new EventHandler<NetworkNotificationEventArgs>(ChangeDetected);
    
        UpdateNetworkInterfaces();
        UpdateNetworkStatus();
    }
    
    
    

在上一节中,我们注册了 NetworkAvailabilityChanged 事件。只要检测到更改,就会调用我们在注册事件时定义的回调。本节介绍如何处理该回调方法中接收的数据。

处理网络可用性更改

  1. 在代码隐藏文件中添加以下方法。这是我们在订阅 NetworkAvailabilityChanged 事件时提供的回调方法。NetworkNotificationEventArgs 参数包含所有与我们通知的变更相关的信息。在本示例中,我们会生成一个信息字符串,该字符串可以告知用户检测到何种更改、出现此更改的接口名称,以及此接口的类型。我们会将此信息字符串添加到与 UI 的“事件”区域绑定的 Changes 列表中。因此,添加此字符串时后,UI 的事件区域就会立即利用此附加信息进行更新。此时,UI 的网络接口列表和网络状态区域也会更新。因为这些操作为 UI 交互,不会在 UI 线程上激发事件,所以我们会将 UI 交互包装在 BeginInvoke 中以确保它们在 UI 线程上执行。执行失败将会导致应用中跨线程违反异常。

    
    // In this callback, we examine the change that was detected. In this example, we are 
    // creating a simple information string and adding that to the event list on the UI. 
    // In a real application, this is where you might adjust your communication connection 
    // in order to take advantage of a network availability change. 
    void ChangeDetected(object sender, NetworkNotificationEventArgs e)
    {
        string change = string.Empty;
        switch (e.NotificationType)
        {
            case NetworkNotificationType.InterfaceConnected:
                change = "Connected to ";
                break;
            case NetworkNotificationType.InterfaceDisconnected:
                change = "Disconnected from ";
                break;
            case NetworkNotificationType.CharacteristicUpdate:
                change = "Characteristics changed for ";
                break;
            default:
                change = "Unknown change with ";
                break;
        }
    
        string changeInformation = String.Format(" {0} {1} {2} ({3})",
                    DateTime.Now.ToString(), change, e.NetworkInterface.InterfaceName,
                    e.NetworkInterface.InterfaceType.ToString());
    
        // We are making UI updates, so make sure these happen on the UI thread.
        Dispatcher.BeginInvoke(() =>
        {
            Changes.Add(changeInformation);
            UpdateNetworkStatus();
            UpdateNetworkInterfaces();
                    
        });
               
    }
    
    
    
  2. 在 MainPage 类中,添加以下方法。这些方法会更新 UI 的“网络接口”“网络状态”区域。在应用启动后,只要网络可用性发生更改,就会调用它们。UpdateNetworkInterfaces 会实例化 NetworkInterfaceList 对象以填充我们在此类中类级别范围上定义的 NetworkInterfaces 列表。因为 UI 的“网络接口”区域已绑定到该列表,并且该列表为 ObservableCollection<T>,所以进行这些操作时 UI 将会利用这些更改进行更新。UpdateNetworkStatus 方法会使用 DeviceNetworkInformation 对象上的静态属性更新 UI 的“网络状态”区域。这些是布尔型数值,但是为了简单起见,我们会将这些内联转换为简单的“Yes”和“No”字符串。一种替代方法是将 boolean 用作 string typeconverter

    
    private void UpdateNetworkInterfaces()
    {
    
        NetworkInterfaces.Clear();
        NetworkInterfaceList networkInterfaceList = new NetworkInterfaceList();
        foreach (NetworkInterfaceInfo networkInterfaceInfo in networkInterfaceList)
        {
            NetworkInterfaces.Add(networkInterfaceInfo.InterfaceName);
        }
    }
    
    private void UpdateNetworkStatus()
    {
        tbIsCellularDataEnabled.Text = (DeviceNetworkInformation.IsCellularDataEnabled) ? "Yes" : "No";
        tbIsNetworkAvailable.Text = (DeviceNetworkInformation.IsNetworkAvailable) ? "Yes" : "No";
        tbIsWiFiEnabled.Text = (DeviceNetworkInformation.IsWiFiEnabled) ? "Yes" : "No";
    }
    
    

本节演示如何引起网络变更以激发应用中的 NetworkAvailabilityChanged 事件。它会使用 ConnectionSettingsTask 来打开和关闭手机上的 AirplaneMode。在此操作结束后,您可以导航回应用的主页面,并在屏幕的“事件”区域中查看结果事件。演示网络更改的这一方法具有一定限制。尤其是,启动 ConnectionSettingsTask 会导致应用被置于后台中。当其位于后台中时,将不会接收到任何事件。当导航回应用时,它才会回到前台。这意味着会出现有时候未获取到某些网络可用性更改。但是,此方法足以演示应用的行为了。在现实世界中,当连接和取消连接 WLAN 连接时,一旦您移出网络连接的范围时或者当连接特性发生变化时,应用网络就会变化。例如,当您在手机网络上漫游时,网络特性会更改。

重要说明重要说明:

建议在物理设备(与模拟器相对)上测试应用。这是因为模拟器不会激发这些事件。相反,应该使用 USB 连接将物理设备连接到桌面并进行调试。

测试应用的步骤

  1. 在应用中的 MainPage 代码隐藏文件中,添加以下事件处理程序。此方法会启动飞行模式的 ConnectionSettingsTask。您可以使用此任务打开和关闭飞行模式。当飞行模式为打开状态时,所有网络连接将会关闭。当飞行模式为关闭状态时,所有网络连接将会恢复。使用此方法,您可以更改飞行模式设置,导航回应用,并观察更改飞行模式引起的网络可用性更改。

    
    // For testing purposes, we provide a way to change the network connection
    // settings by launching the ConnectionSettingsTask. However, because we are moving 
    // our application to the background and then to the foreground when we navigate back from
    // the ConnectionSettingTask, there is a chance we may not receive all NetworkAvailabilityChanged events.
    // Alternatively, you can test by physically disconnecting a Wi-Fi connection, by connecting and disconnecting
    // your device to your desktop, or by moving out of range of your Wi-Fi network.
    private void btnChangeNetworkSettings_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("This action will launch the ConnectionSettingsTask where you can change the network settings." + 
                            " As soon as you have made your changes, use the hardware Back button to get back to this page so that you can observe the NetworkAvailabilityChanged events.");
    
        //Use the ConnectionSettingsTask to bring up the connection settings
        ConnectionSettingsTask connectionSettings = new ConnectionSettingsTask();
    
        // We are using the Connection Settings page for AirplaneMode.
        connectionSettings.ConnectionSettingsType = ConnectionSettingsType.AirplaneMode;
        connectionSettings.Show();
    
        // Note: Once you have changed the settings (switched from On to Off for example)
        // use the hardward Back button on your device to go back to this page and catch
        // the NetworkAvailabilityChanged events.
    }
    
    
    
  2. 通过选择“调试”|“启动”调试 (F5) 菜单命令运行应用。应用将会启动,并且当前可用网络接口会在 UI 的“网络接口”区域中显示。网络的当前状态也会在 UI 的“网络状态”区域中显示。

  3. 如果您正在使用物理设备,您可以通过以物理方式关闭 WLAN 网络、移出网络范围、取消设备与 USB 连接的连接(连接到桌面时)以及许多其他方式初始化网络更改。此外,您还可以按应用上的“更改网络设置”按钮,这会启动 ConnectionSettingsTask。打开或关闭“飞行模式”,然后在切换飞行模式后尽快使用手机硬件“返回”按键返回到应用。

  4. 当网络可用性更改发生时,您可以在应用的“事件”区域中观察它们。每次接收到更改时,还会更新“网络接口”“网络状态”区域。

    提示提示:

    如果您不希望测试飞行模式,您可以更改以前的代码以启动蜂窝连接或 Wi-Fi 的 ConnectionSettingsTask

显示:
© 2016 Microsoft