このページは役に立ちましたか。
このページのコンテンツについての ご意見をお待ちしております
その他にご意見はありますか。
残り 1500 文字
エクスポート (0) 印刷
すべて展開

方法: Windows Phone のネットワーク変更を検出する

2012/02/09

作成する Windows Phone アプリケーションで、利用可能なネットワークが変化したときにそのことを認識できるようにしたい場合があります。ネットワークの変化は、ユーザーがアプリケーションの使用中に既知の Wi-Fi ネットワーク圏内に入ったときなどに発生します。そのようにして急に利用可能になったネットワークをアプリケーション側で活用することで、高帯域幅のネットワーク インターフェイスを使った通信を実現することができます。ネットワークの利用可能性をリッスンするには、NetworkAvailabilityChanged イベントに登録します。このトピックでは、このイベントに登録する方法と、イベントが発生したときにネットワークにどのような変更が生じたかを解釈する方法について説明します。

このトピックは、次のセクションで構成されています。

このセクションでは、ネットワーク利用可能性の変化を受け取って表示するための UI を作成します。アプリケーションが起動すると、利用可能なネットワーク インターフェイスをすべて一覧表示します。また、ネットワークの利用可能性が変化したことを知らせる通知をサブスクライブします。変化が生じると、NetworkAvailabilityChanged イベントが発生します。このアプリケーションはこのイベントを処理して、変化内容を UI のリスト上に文字列として出力します。またネットワーク設定を手動でオン/オフするための ConnectionSettingsTask を起動する方法も提供します。

アプリケーションのユーザー インターフェイスを作成するには

  1. Visual Studio 2010 Express for Windows Phone で、[ファイル] メニューの [新しいプロジェクト] をクリックして新しいプロジェクトを作成します。

  2. [新しいプロジェクト] ウィンドウが表示されます。Visual C# のテンプレートを展開してから、Silverlight for Windows Phone のテンプレートを選択します。

  3. Windows Phone アプリケーション テンプレートを選択します。[名前] に選択した名前を入力します。

  4. [OK] をクリックします。新しいプロジェクトが作成され、Visual Studio のデザイナー ウィンドウに MainPage.xaml が表示されます。

  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>
    
    
    

    上記の XAM コードでは、次のスクリーンショットのような簡単なユーザー インターフェイスが作成されます。

    ネットワーク検出機能のユーザー インターフェイス

    UI は 4 つの部分に分かれています。画面の最上部には、現在利用可能なネットワーク インターフェイスがすべて表示されます。このデータは、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 のネットワーク インターフェイス部分とネットワークの状態部分を初期化するために 2 つのメソッドを呼び出します。呼び出すメソッドは以降の手順で定義します。これで、ネットワーク利用可能性の変化イベントに登録できました。次のセクションでは、検出した変化を解釈する方法について説明します。

    
    // 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 インタラクションが確実に UI スレッド上で実行されるよう、UI インタラクションを BeginInvoke 内にラップします。そうしないと、アプリケーション内でスレッド間違反例外が発生します。

    
    // 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 は、このクラスのクラスレベルのスコープで定義した NetworkInterfaces リストへの読み込みを行うために NetworkInterfaceList オブジェクトをインスタンス化します。UI のネットワーク インターフェイス部分はこのリストにバインドされており、リストは ObservableCollection であるため、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 の起動によってアプリケーションがバックグラウンドに置かれます。バックグラウンドにある間はイベントは受け取られません。アプリケーションに移動すると、アプリケーションがフォアグラウンドに戻ります。このため、ネットワーク利用可能性の変化が検知されない時間が生じます。しかしこの方法は、アプリケーションの動作を確認するには十分です。現実のアプリケーション利用環境では、Wi-Fi への接続、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 を起動する [Change Network Settings (ネットワーク設定の変更)] ボタンを押すこともできます。フライト モードのオン/オフを切り替えたらすぐに、ハードウェアの [戻る] ボタンを使用してアプリケーションに戻ります。

  4. ネットワーク利用可能性の変化が発生すると、アプリケーションのイベント部分でそれを確認することができます。ネットワーク インターフェイス部分とネットワークの状態部分も変化が検出されるたびに更新されます。

    ヒントヒント:

    フライト モード以外でテストしたい場合は、ConnectionSettingsTask を起動するためのコードを Cellular や Wi-Fi などに設定することもできます。

表示:
© 2015 Microsoft