Friday, July 19, 2013

Windows Phone Tip: Checking Network Availability

If you are writing networked applications, it is always important to be able to know if the device has network connectivity. In addition, it is also very useful to know if the device is connected to the WiFi, or the cellular data network. If the device is connected to the cellular data network, you could limit the amount of data transferred as this could cost impose additional cost on the user.  

All the code in this tip and tricks uses the following namespaces, so ensure that you import them into your page:

using Windows.Networking.Connectivity;
using System.Diagnostics;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
using Microsoft.Phone.Net.NetworkInformation;
using Windows.System.Threading;
using System.Threading.Tasks;

To know if there is network connectivity on your device, use the GetIsNetworkAvailable() method from the NetworkInterface class:

    if (NetworkInterface.GetIsNetworkAvailable()){

    }

This method returns a boolean value indicating if there is any form of network connectivity on your device.

To know what kind of connectivity you have, you can access the NetworkInterfaceType property of the NetworkInterface class:

        private NetworkInterfaceType GetNetworkInterfaceType()
        {
            //---this is a blocking call---
            var interfaceType =
                NetworkInterface.NetworkInterfaceType;
            return interfaceType;
        }

However, do take note that the NetworkInterfaceType property is a blocking call – it typically takes about a couple of seconds to return you the network type. Hence, be sure not to call it directly. Instead, you should put it into a method and call it asynchronously using the async and await keywords:

        private async void CheckNetworkType()
        {
            //---call the GetNetworkInterfaceType() method
            // asynchronously---
            var interfaceType = await
                Task.Run(() =>
                    GetNetworkInterfaceType()
                );
        }

You can check the type of connectivity you have by comparing the interface type with the enumerations in the NetworkInterfaceType:

        private async void CheckNetworkType()
        {
            //---call the GetNetworkInterfaceType() method
            // asynchronously---
            var interfaceType = await
                Task.Run(() =>
                    GetNetworkInterfaceType()
                );

            if (interfaceType ==
            NetworkInterfaceType.Wireless80211)
            {
                Debug.WriteLine("Wireless");
                GetMyIPAddress();
                GetMyPublicIPAddress();
            }
            else if (interfaceType ==
            NetworkInterfaceType.MobileBroadbandGsm ||
            interfaceType ==
            NetworkInterfaceType.MobileBroadbandCdma)
            {
                Debug.WriteLine("Cellular network");
                GetMyIPAddress();               
            }
            else if (interfaceType ==
            NetworkInterfaceType.None)
            {
                Debug.WriteLine("None");
            }
        }

You can get your IP address by using the following method:

        public void GetMyIPAddress()
        {
            var hostNames = NetworkInformation.GetHostNames();
            foreach (var hostName in hostNames)
            {
                if (hostName.IPInformation != null)
                {
                    string ipAddress = hostName.DisplayName;
                    Debug.WriteLine("IP address: " +
                        ipAddress);
                }
            }
        }

If you are connected to a WiFi, it is often that your IP address is a local one – one that that the router assigns to you using DHCP. If you want to know the IP address that your service provider assigns to your router, you can use a JSON service located at  http://ip.jsontest.com/. This service will return you the IP address that is assigned to your router by your service provider.

To use this service, first define a class called Json_Result:

    [DataContract]
    public class Json_Result
    {
        [DataMember(Name = "ip")]
        public string IP { get; set; }
    }

You can call the JSON service using the WebClient class, like the following code snippet:

        private void GetMyPublicIPAddress()
        {
            //---find my public ip address---
            WebClient client = new WebClient();
            client.OpenReadCompleted +=
                client_OpenReadCompleted;
            client.OpenReadAsync(new
                Uri("http://ip.jsontest.com/"),
                UriKind.Absolute);
            //---returning result is
            //    {"ip":"xxx.xxx.xxx.xxx"}---
        }

        void client_OpenReadCompleted(object sender,
        OpenReadCompletedEventArgs e)
        {
            var serializer = new
                DataContractJsonSerializer(
                    typeof(Json_Result));
            Json_Result ipResult =
                (Json_Result)serializer.ReadObject(e.Result);           
            Debug.WriteLine("My public IP address: " +
                ipResult.IP);
        }

The above code snippet is also useful in helping you determine if you have actual Internet access. Having network connectivity does not mean you have Internet connectivity - hence if the above code is able to fetch your IP address, it means that you have Internet connectivity.

Finally, if you want to programmatically monitor for changes to network connectivity on your device, you can set an event handler for the NetworkAvailabilityChanged event:

//---monitor for changes in network availability---            DeviceNetworkInformation.NetworkAvailabilityChanged +=
    DeviceNetworkInformation_NetworkAvailabilityChanged;

void DeviceNetworkInformation_NetworkAvailabilityChanged(
object sender, NetworkNotificationEventArgs e)
{
    CheckNetworkType();
}

Full Code Listing

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using MyIPAddress.Resources;

using Windows.Networking.Connectivity;
using System.Diagnostics;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
using Microsoft.Phone.Net.NetworkInformation;
using Windows.System.Threading;
using System.Threading.Tasks;

namespace MyIPAddress
{
    [DataContract]
    public class Json_Result
    {
        [DataMember(Name = "ip")]
        public string IP { get; set; }
    }

    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();

            //---monitor for changes in network
            // availability---                         DeviceNetworkInformation.NetworkAvailabilityChanged +=            DeviceNetworkInformation_NetworkAvailabilityChanged;

            if (NetworkInterface.GetIsNetworkAvailable())
            {
                CheckNetworkType();
            }
            else
            {
                Debug.WriteLine("No network available");
            }                  
        }

        private async void CheckNetworkType()
        {
            //---call the GetNetworkInterfaceType() method
            // asynchronously---
            var interfaceType = await
                Task.Run(() =>
                    GetNetworkInterfaceType()
                );

            if (interfaceType ==
            NetworkInterfaceType.Wireless80211)
            {
                Debug.WriteLine("Wireless");
                GetMyIPAddress();
                GetMyPublicIPAddress();
            }
            else if (interfaceType ==
            NetworkInterfaceType.MobileBroadbandGsm ||
            interfaceType ==
            NetworkInterfaceType.MobileBroadbandCdma)
            {
                Debug.WriteLine("Cellular network");
                GetMyIPAddress();               
            }
            else if (interfaceType ==
            NetworkInterfaceType.None)
            {
                Debug.WriteLine("None");
            }
        }

        void       
        DeviceNetworkInformation_NetworkAvailabilityChanged(
        object sender, NetworkNotificationEventArgs e)
        {
            CheckNetworkType();
        }

        private NetworkInterfaceType GetNetworkInterfaceType()
        {
            //---this is a blocking call---
            var interfaceType =
                NetworkInterface.NetworkInterfaceType;
            return interfaceType;
        }
       
        private void GetMyPublicIPAddress()
        {
            //---find my public ip address---
            WebClient client = new WebClient();
            client.OpenReadCompleted +=
                client_OpenReadCompleted;
            client.OpenReadAsync(new
                Uri("http://ip.jsontest.com/"),
                UriKind.Absolute);
            //---returning result is
            //    {"ip":"xxx.xxx.xxx.xxx"}---
        }

        public void GetMyIPAddress()
        {
            var hostNames = NetworkInformation.GetHostNames();
            foreach (var hostName in hostNames)
            {
                if (hostName.IPInformation != null)
                {
                    string ipAddress = hostName.DisplayName;
                    Debug.WriteLine("IP address: " +
                        ipAddress);
                }
            }
        }
       
        void client_OpenReadCompleted(object sender,
        OpenReadCompletedEventArgs e)
        {
            var serializer = new
                DataContractJsonSerializer(
                    typeof(Json_Result));
            Json_Result ipResult =
                (Json_Result)serializer.ReadObject(e.Result);           
            Debug.WriteLine("My public IP address: " +
                ipResult.IP);
        }
    }

}

No comments: