방법: Windows Phone의 네트워크 변경 검색

2012-02-09

Windows Phone 응용프로그램을 만드는 경우 사용 가능한 네트워크가 변경될 때 해당 알림을 받는 것이 좋습니다. 예를 들어 응용프로그램이 알려진 Wi-Fi 네트워크의 적용 범위에 들어오는 경우가 있습니다. 갑자기 해당 네트워크를 사용할 수 있게 되며 응용프로그램이 고대역폭 네트워크 인터페이스를 통신에 이용할 수 있습니다. NetworkAvailabilityChanged 이벤트에 등록하면 네트워크 가용성 변경 사항을 수신 대기할 수 있습니다. 이 항목에서는 이 이벤트에 등록하는 방법 및 이벤트가 발생할 때의 네트워크 변경 사항을 해석하는 방법에 대해 설명합니다.

이 항목은 다음 섹션으로 이루어져 있습니다.

이 단원에서는 네트워크 가용성 변경 사항을 받고 표시하는 방법을 보여 주는 UI를 만듭니다. 응용프로그램이 시작되면 사용 가능한 모든 네트워크 인터페이스를 나열합니다. 또한 네트워크 가용성 변경 사항 알림을 수신하도록 구독합니다. 가용성이 변경되면 NetworkAvailabilityChanged 이벤트가 발생합니다. 응용프로그램이 이 이벤트를 처리하고 변경 사항을 UI의 목록에 문자열로 출력합니다. 또한 네트워크 설정을 수동으로 켜거나 끄기 위해 ConnectionSettingsTask를 시작하는 방법도 제공됩니다.

응용프로그램 사용자 인터페이스를 만들려면

  1. Windows Phone용 Visual Studio 2010 Express 에서 파일 | 새 프로젝트 메뉴 명령을 선택하여 새 프로젝트를 만듭니다.

  2. 새 프로젝트 창이 표시됩니다. Visual C# 템플릿을 확장하고 Windows Phone용 Silverlight 템플릿을 선택합니다.

  3. Windows Phone 응용프로그램 템플릿을 선택합니다. 이름에 선택한 이름을 입력합니다.

  4. 확인을 클릭합니다. 새 프로젝트가 생성되고 MainPage.xaml이 Visual Studio 디자이너 창에서 열립니다.

  5. MainPage.xaml에서 Grid의 XAML 코드("LayoutRoot")를 제거하고 다음 코드로 바꿉니다.

    
    <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 코드는 다음 스크린샷과 같은 단순 사용자 인터페이스를 만듭니다.

    네트워크 탐지기 사용자 인터페이스

    UI는 네 부분으로 나뉘어져 있습니다. 화면 맨 위에는 사용 가능한 모든 네트워크 인터페이스가 표시됩니다. 이 데이터는 NetworkInterfaceList 컬렉션에서 검색됩니다. 응용프로그램이 시작될 때 및 응용프로그램에 NetworkAvailabilityChanged 이벤트가 수신될 때마다 데이터가 로드됩니다. 화면의 다음 섹션에는 응용프로그램에 수신된 NetworkAvailabilityChanged 이벤트 정보가 표시됩니다. 화면의 다음 부분에는 단말기 네트워크 기능의 전체 상태가 표시됩니다. 마지막으로, 네트워크 설정을 수동으로 변경하고 NetworkAvailabilityChanged 이벤트가 발생되도록 하기 위해 ConnectionSettingsTask를 시작하는 버튼이 화면 맨 아래에 배치됩니다. 이 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의 Events 영역이 이 추가 정보로 업데이트됩니다. 이때 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의 네트워크 인터페이스네트워킹 상태 영역을 업데이트합니다. 응용프로그램이 시작될 때 및 네트워크 가용성이 변경될 때마다 메서드가 호출됩니다. UpdateNetworkInterfacesNetworkInterfaceList 개체를 인스턴스화하여 이 클래스에서 클래스 레벨 범위로 정의한 NetworkInterfaces 목록을 채웁니다. UI의 네트워크 인터페이스 영역은 이 목록에 바인딩되며 목록이 ObservableCollection이기 때문에 변경되는 즉시 UI가 이러한 변경 사항으로 업데이트됩니다. UpdateNetworkStatus 메서드는 DeviceNetworkInformation 개체의 정적 속성을 사용하여 UI의 네트워킹 상태 영역을 업데이트합니다. 이러한 속성은 부울 값이지만 알아보기 쉽도록 해당 값을 인라인에서 단순 "Yes" 및 "No" 문자열로 변환합니다. 대체 방법은 booleanstring 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를 시작하면 응용프로그램이 백그라운드에 배치됩니다. 백그라운드에 있는 동안에는 이벤트가 수신되지 않습니다. 응용프로그램으로 돌아가면 응용프로그램이 포그라운드로 전환됩니다. 따라서 일부 네트워크 가용성 변경 사항이 검색되지 않는 기간이 있습니다. 하지만 이 메서드는 응용프로그램의 동작을 보여 주기에 충분합니다. 실제 응용프로그램에서는 Wi-Fi 연결을 설정하고 연결을 끊을 때마다, 네트워크 연결 범위를 벗어날 때마다 또는 연결의 특성이 변경될 때 네트워크 변경이 발생합니다. 네트워크 특성 변경의 예로 셀룰러 네트워크에서 로밍하는 경우가 있습니다.

중요중요:

에뮬레이터가 아니라 실제 단말기에서 이 응용프로그램을 테스트하는 것이 좋습니다. 에뮬레이터는 이러한 이벤트를 발생시키지 않기 때문입니다. 대신 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. 실제 단말기를 사용하는 경우 실제로 Wi-Fi 네트워크를 끄거나, 네트워크 범위를 벗어나거나, 데스크톱에 테더링된 경우 USB 연결에서 단말기를 분리하는 등의 여러 방법으로 네트워크 변경을 시작할 수 있습니다. 또는 응용프로그램에서 네트워크 설정 변경 버튼을 눌러 ConnectionSettingsTask를 시작할 수 있습니다. 비행기 모드를 켜거나 끄고, 비행기 모드를 전환한 후 즉시 단말기 하드웨어 뒤로 버튼을 사용하여 응용프로그램으로 돌아갑니다.

  4. 네트워크 가용성이 변경될 경우 응용프로그램의 이벤트 영역에서 관찰할 수 있습니다. 변경 사항이 수신될 때마다 네트워크 인터페이스네트워킹 상태 영역도 업데이트됩니다.

    팁팁:

    비행기 모드로 테스트하지 않으려는 경우 앞의 코드를 변경하여 셀룰러 또는 Wi-Fi에 대한 ConnectionSettingsTask를 시작할 수 있습니다.

표시: