- 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. :)
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.
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
bool Microsoft.Phone.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable(): Indicates whether any network connection is available. This is exactly the same as
Types of internet connection.
- None There is no network available for accessing the internet.
- Ethernet The network interface uses an Ethernet connection. Ethernet is defined in IEEE standard 802.3.
- 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.
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.
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.
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):
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.
First of all, reading this property blocks the UI thread. The blocking time mostly depends on the from/to
- 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.
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.
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.
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:
- The App has just started and the
GetIsNetworkAvailable() function returns
TRUE, which means that we are connected to a
Network, and the
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.
- 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.
online=True (the phone still has an IP). This state can be detected by polling only.
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.
public NetworkAvailableEventArgs(bool isOnline): contains just the
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;
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
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
True, they are fired every time the framework’s
NetworkAddressChanged event happens or the Polling runs its Tick event
public void AsyncGetNetworkType()
IsInstantRequestPresent = true;
requestStatus = NetworkTypeRequestStatus.Started;
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 NetworkTypeRequestStatus GetRequestStatus()
public bool DetailedMode
detailedMode = value;
public bool GetZuneStatus()
AsyncGetNetworkType: Starts an instant and single request to determine the current
NetworkType. When done, raises the
OnAsyncGetNetworkTypeCompleted event with the current
Function SetNetworkPolling(int Minutes, int Seconds, int Milliseconds): Starts a
NetworkType polling with the User provided time interval
DisableNetworkPolling: Stops the
GetCurrentNetworkType: Returns with the Currently stored
GetRequestStatus: Returns with the status of the
BackgroundWorker, determines whether the
NetType request is present (
NetworkTypeRequestStatus.Started) or not (
GetZuneStatus: Is the Zune connected(
true) or not(
DetailedMode: This is a
set boolean property which determines if the events are going to be raised every time when the framework raises them including
true), or just when the
NetworkType is really changed (
False is the default setting in order to hide framework malfunctions.
First of all in the App.xaml.cs, set a reference to the
private void Application_Launching(object sender, LaunchingEventArgs e)
nd = NetworkDetector.Instance;
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
- 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.
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!
This article can be found on my WP7 Blog too: