Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Zune Detection and Network Awareness

0.00/5 (No votes)
16 Nov 2010 2  
How to detect the Zune connection and the Network State inside your WP7 Application

NetworkAwarenessTest.jpg

Contents

Foreword

  • I used a wired sync for all the tests, because for some reason I couldn't sync over WiFi. The post will be updated if I succeed.
  • There were a lot of emails between me and the Microsoft guys, because they couldn't reproduce most of the strange behaviour of the network functions, even though I sent them videos about some of the issues. But I have to tell that I’m quite happy about this, because this probably means that the Phones with the final hardware are much better than the one I'm using for development (LG GW910 with 7003 firmware). I can’t wait to get a final version of the device. :)

Introduction

Detecting the status of the network is an important task. Applications that utilize the network capabilities should be aware whether the phone has internet connection or not, and what is the type of the connection exactly. In the namespaces “System.Net.NetworkInformation” and “Microsoft.Phone.Net.NetworkInformation”, there are methods and events specifically for this. The two namespaces are similar but have different capabilities.

Background

System.Net.NetworkInformation Namespace

  • bool System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable(): Indicates whether any network connection is available.
  • event System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged: Raises an event if the network status changes (referred to also as Changed Event).

Usage and sample: http://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface.getisnetworkavailable%28v=VS.95%29.aspx

Microsoft.Phone.Net.NetworkInformation Namespace

bool Microsoft.Phone.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable(): Indicates whether any network connection is available. This is exactly the same as System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable().

enum Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType:

Types of internet connection.

  • None There is no network available for accessing the internet.
  • AsymmetricDsl
  • Atm
  • BasicIsdn
  • Ethernet The network interface uses an Ethernet connection. Ethernet is defined in IEEE standard 802.3.
  • Ethernet3Megabit
  • FastEthernetFx
  • FastEthernetT
  • Fddi
  • GenericModem
  • GigabitEthernet
  • HighPerformanceSerialBus
  • IPOverAtm
  • Isdn
  • Loopback
  • MultiRateSymmetricDsl
  • Ppp
  • PrimaryIsdn
  • RateAdaptDsl
  • Slip
  • SymmetricDsl
  • TokenRing
  • Tunnel
  • Unknown
  • VeryHighSpeedDsl
  • Wireless80211 The network interface uses a wireless LAN connection (IEEE 802.11 standard).
  • MobileBroadbandGsm The network interface uses a GSM cellular network.
  • MobileBroadbandCdma The network interface uses a CDMA cellular network.

Source: http://msdn.microsoft.com/en-us/library/microsoft.phone.net.networkinformation.networkinterfacetype%28v=VS.92%29.aspx

Property Microsoft.Phone.Net.NetworkInformation.NetworkInterface.NetworkInterfaceType

Usage: http://msdn.microsoft.com/en-us/library/microsoft.phone.net.networkinformation.networkinterface.networkinterfacetype%28v=VS.92%29.aspx

On the emulator the NetworkInterfaceType is mostly Wireless80211 if the computer is connected to the internet, or None if it is disconnected. However, if you have a possibility to test on a device like me, you can get valid results, and this is what I am going to use to detect whether the device is connected to the machine, or not. In the next section, I am going to explain how these functions work on the LG test device with the final 7003 RTM firmware release.

Network Behaviour and Priority

The priority of the network interfaces is the following:

If the Zune or WPDTConnect is running on the PC and the phone is synced, the device connects to the internet through the PC (NetworkInterfaceType=="Ethernet"). If the PC doesn't have internet connection, the device is stuck without internet and the NetworkInterfaceType will be "None". Without sync connection, the phone chooses between WiFi and Broadband connection. The WiFi has higher priority over the Broadband. If neither of them are available or the connected WiFi doesn't have internet access, the NetworkInterfaceType will be "None". After losing a higher priority connection, the device automatically tries to connect to the next available connection type. Notice!! If synced with Zune/WPDT with no internet present, the phone won't switch to available or predefined WiFi/Broadband.

NetworkAddressChanged Event Details

This event is present since Silverlight 3 and also supported on Windows Phone 7. Basically the event occurs when the IP of the phone changes, typically with one of the following scenarios:

  • Zune/WPDT starts (sync cable connecting or already connected)
  • Zune/WPDT stops
  • disconnect sync cable when synced
  • WiFi/Broadband connected/disconnected(accessing/leaving area)

During sync, the phone gets its IP from the PC, and because we can't get this IP from code (so far), we have to rely on this event and the NetworkInterfaceType property. The event will not occur if the device already has a higher priority connection established.

Detecting a Zune/WPDT connection state change and raising the event is relatively fast (2-5 sec) but if the WiFi/Broadband connection is lost, sometimes it can be 20-30 sec to raise the event. After disconnecting Zune, the event raising is nearly instantaneous (0-3 sec), however if the system is switching to WiFi/broadband, this amount of time is probably not always enough to establish the WiFi connection properly, so be careful with the event based UI/code refreshes. If a higher priority network becomes available, the phone automatically tries to connect to it, and if it succeeds, this change event is raised (priorities: Zune,WiFi,Broadband). During the network change, the Changed event could occur several times one after another. There were some cases when I started the app with broadband, then switched ON a router which I had connected my phone before, and after approx 45-60 seconds ~3-4 connection changed event raised. The NetworkInterfaceType-s order was the following with the events (I checked them within the event handler):

MobileBroadbandGsm, Wireless80211, Wireless80211, Wireless80211. So the first was the Broadband, which was the initial connection, then came 3 WiFi connections, which could be the result of some unexplainable IP changes. This situation can happen at any network type switching, so better be prepared for it.

Microsoft.Phone.Net.NetworkInformation.NetworkInterface.NetworkInterfaceType Property Details

First of all, reading this property blocks the UI thread. The blocking time mostly depends on the from/to NetworkType.

  • Pull out the sync cable while Zune is connected-> WiFi connects: The NetworkType blocks ~1 second (once again, this is not always enough for the phone to connect the WiFi properly)
  • Synced, Zune connected, the PC connects to the internet with WiFi-> PC WiFi switch OFF->the NetworkType blocks the UI for 20-30 seconds!!!!! The result will be "None" NetworkType, but if the WiFi is switched ON again during this 20 second freeze, the resulting NetType will be Ethernet instead of None, just like nothing has happened.

The solution: Put it into a BackgroundWorker, continue reading for the details.

Connection/Sync Problems

On our developer phone, there were several times when I synced the phone and the Network Changed event wasn't raised. In this scenario, the NetworkType contained WiFi type instead of Ethernet. What I'm trying to say, that based on our developer device these functions can't be 100% trusted. I hope that on the final ones, they are.

Zune Detection

So far, the WP7 can't play videos on the device when the Zune software is connected. There is a shortcut to use the WPDTPTConnect64/32 programs which can connect the phone to the PC without blocking the media, but it's just used by developers. I'd say that it has to be a basic functionality to detect whether the Zune is connected or not. In the WP7 SDK, I can't find anything dedicated to this scenario. But there is a workaround to this that utilizes the functions above.

Maybe you have already noticed that you get a MediaFailed event which contains a AG_E_NETWORK_ERROR ErrorMessage when you try to open a MediaFile in a MediaElement or a SmoothStreamingMediaElement while Zune is connected. Detecting this has to be the last defence line of the Zune Detection on Windows Phone 7.

If it's possible, we need to avoid getting this far and have to detect the Connected status before we try to play a MediaFile. Using the Changed event and NetworkType property, we can notify the user right after connecting, or at least when clicking on the play button.

About the None NetworkType

This NetworkType represents a state where the phone doesn't have Internet access. Switching to this state or being in this state, the NetType request nearly always lasts long (10-60 sec, especially when switching to). Also a big problem with this state is, that we don't necessarily know from where we got here. For example:

  1. The App has just started and the GetIsNetworkAvailable() function returns TRUE, which means that we are connected to a Network, and the NetType is None!! In this situation, the correct connection could be a PC synced with the phone without Internet, or a WiFi router connected to the phone without Internet.
  2. The App just started and the GetIsNetworkAvailable() function returns FALSE which means that we are not connected to any Network and the NetType is obviously None!! Then the phone Sync with a PC which has no internet connection or the phone connects to a router which has no internet connection.

If it's the one with the PC, then the Zune is connected but we can't be sure about it, because it can be WiFi too. I know that these are highly unlikely situations, but still can happen. In the code I'm not dealing with these situations, but if you have a considerable solution for this, please let me know. You can leave a comment, or send an e-mail to the dolhaig at gmail adress.

Another important thing about this NetworkType: The framework will not fire the Changed Event when switching to this state if the phone has another network connected. Let me explain this a little further:

  • You will get a changed event: The phone doesn't have WiFi or Broadband preconfigured and currently is connected to the PC over Zune sync. Break the connection and you will get a changed event because the phone loses its IP and there are no available connections to connect to. The NetType will be None and the "online" variable will be False in my code (OnNetworkOFF event fires also).
  • No changed event: The phone is on WiFi/Ethernet (Zune) and the Router/PC loses the Internet connection. NetworkType=None, online=True (the phone still has an IP). This state can be detected by polling only.

Let's Take A Look at the Code

I made a Singleton class that uses these functions to simplify the Network Interface usage. For Zune detection, I simply check if the returned NetworkType is "Ethernet", if yes, then the Zune must be connected. With my class, you can get notifications when:

  • Different connection types become activated/deactivated
  • All the network lost/some found
  • Zune connected/disconnected

Although the class hides the actual working of the framework functions from the rest of your code, it is possible to get all the events and Networktype changes from the framework when you set the DetailedMode boolean value to True. Polling the NetworkType in User provided time intervals is also possible.

About the Events

  • public NetworkAvailableEventArgs(bool isOnline): contains just the NetworkAvailability status true/false, when false the phone is absolutely unconnected from the network
  • public NetworkDetectorEventArgs(bool isOnline, Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType netType): NetworkAvailability and Network Type
public event EventHandler OnNetworkON;
public event EventHandler OnNetworkOFF;
public event EventHandler OnNetworkChanged;

public event EventHandler OnZuneConnected;
public event EventHandler OnZuneDisconnected;
public event EventHandler OnConnectedEthernet;
public event EventHandler OnConnectedWifi;
public event EventHandler OnConnectedNone;
public event EventHandler OnConnectedBroadbandGsm;
public event EventHandler OnConnectedBroadbandCdma;
public event EventHandler OnConnectedOther;
public event EventHandler OnLostNetworkType;

public event EventHandler OnAsyncGetNetworkTypeCompleted;
  • OnNetworkON and OnNetworkOFF: raised when the phone connects to any network from a no network state or loses all the network connections
  • OnNetworkChanged: can be raised only when DetailedMode=True, happens when the framework raises the System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged
  • OnZuneConnected and OnZuneDisconnected: speaks for itself, raised only in the beginning of connecting/losing the Ethernet network type
  • OnLostNetworkType: raised when the NetworkType is changed. The NetType property of this event contains the previous NetworkType, contrary to the other events, where it contains the actual Type when present
  • OnAsyncGetNetworkTypeCompleted: returning event after the AsyncGetNetworkType public function is called
  • OnConnectedXXX: These events are raised when the framework throws a NetworkAddressChanged event and the NetworkType is changed compared to the previous NetworkType. When DetailedMode is True, they are fired every time the framework’s NetworkAddressChanged event happens or the Polling runs its Tick event

Public Properties and Functions

public void AsyncGetNetworkType()
{
    //requestQueue.Enqueue(System.DateTime.Now.Ticks);
    IsInstantRequestPresent = true;
    if (!networkWorker.IsBusy)
    {
        requestStatus = NetworkTypeRequestStatus.Started;
        networkWorker.RunWorkerAsync();
    }
    if (!updateTimer.IsEnabled) updateTimer.Start();
}

public void SetNetworkPolling(int Minutes, int Seconds, int Milliseconds)
{
    pollTimer.Interval = new TimeSpan(0, 0, Minutes, Seconds, Milliseconds);
    if (!pollTimer.IsEnabled) pollTimer.Start();
}

public void DisableNetworkPolling()
{
    if (pollTimer.IsEnabled) pollTimer.Stop();
}

public Microsoft.Phone.Net.NetworkInformation.NetworkInterfaceType 
	GetCurrentNetworkType()
{
    return net;
}

public NetworkTypeRequestStatus GetRequestStatus()
{
    //NetworkTypeRequestStatus temp = requestStatus;
    //if (requestStatus == NetworkTypeRequestStatus.Ended) 
    //requestStatus = NetworkTypeRequestStatus.Default;
    //return temp;
    return requestStatus;
}

public bool DetailedMode
{
    get
    {
        return detailedMode;
    }
    set
    {
        detailedMode = value;
    }
}

public bool GetZuneStatus()
{
    return isZuneConnected;
}
  • Function AsyncGetNetworkType: Starts an instant and single request to determine the current NetworkType. When done, raises the OnAsyncGetNetworkTypeCompleted event with the current NetType
  • Function SetNetworkPolling(int Minutes, int Seconds, int Milliseconds): Starts a NetworkType polling with the User provided time interval
  • Function DisableNetworkPolling: Stops the NetworkType polling
  • Function GetCurrentNetworkType: Returns with the Currently stored NetworkType
  • Function GetRequestStatus: Returns with the status of the BackgroundWorker, determines whether the NetType request is present (NetworkTypeRequestStatus.Started) or not (NetworkTypeRequestStatus.Ended).
  • Function GetZuneStatus: Is the Zune connected(true) or not(false)
  • Property DetailedMode: This is a get/set boolean property which determines if the events are going to be raised every time when the framework raises them including NetworkPolling (true), or just when the NetworkType is really changed (false). False is the default setting in order to hide framework malfunctions.

Using the Code

First of all in the App.xaml.cs, set a reference to the Singleton class:

NetworkDetector nd;
// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
    nd = NetworkDetector.Instance;
}

// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
    nd = NetworkDetector.Instance;
}

In this way, you can prepare for changes right from the beginning, even when your code returns from tombstone.

Then depending on the speed of your application and your trust in the Framework, choose the way you want to use the code:

  • Single request from time to time or User Polling: You can call the AsyncGetNetworkType function whenever you want and it will return the current state in the OnAsyncGetNetworkTypeCompleted event.
  • If you completely trust the framework, that it will be throwing NetworkAddressChanged events at the right moments, then you can sign up to the right events and it will be raised in time.
  • You don’t trust the framework (because it’s Evil :) ) or you just need to know the network state all the time scenario: Set up a polling with the SetNetworkPolling function with a suitable polling interval and sign up to the right events. Thanks to the BackgroundWorker even in heavy polling the UI stays completely responsive. During my tests, I noticed that even setting the polling interval to 100 milliseconds the framework wasn’t capable to serve more than approximately 3 requests per second.

Watching a Specific NetworkType

For example, let’s suppose that you are a very watchful developer and you don’t want the user to give his/her whole salary to the Mobile Operators, so you want to watch for the connection type, and when the system uses Broadband connection limit the used amount of data, then when a better connection is available send the heavy load.

You just sign up to the broadband events and the OnLostNetworkType event. On the OnLostNetworkType, you get what the previous network was and then you can get the current network with GetCurrentNetworkType or poll manually with the AsyncGetNetworkType function to determine if the current connection is right for you to send a lot of data or not.

Important!!! This Library is just as good as the framework. I believe that the final phones will be far better than our Developer one that was already good enough to make it possible to create workarounds for most of the problems.

My code can be used freely for anyone, under the MS-PL license. The Singleton class can be found in the NetworkDetector.cs.

If you found this article useful, please vote!

Good to Know

This article can be found on my WP7 Blog too:

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here