Iris Classon
Iris Classon - In Love with Code

Example Metro app /WinRT: background task that uppdates internet connection and metering (roaming) information based on network changes

Continuing on my Metro app, working myself through all the requirements, I’ve made another example and downloadable simple example.

Problem:
You have to notify the user if he/she is connected to the internet or not, and display metering information (Data limit, approaching data limit etc) if roaming is activated.

Some requriements applicable from Application Profile Survey:
Performance: UI is always responsive and provides visual feedback on interactions
User Experience - PLM: Makes appropriate use of backgrounds tasks

  • Accessibility and user consideration

The example I’ve put together does the following:

  1. When app is started or page navigated to text and progress rings indicate that internet connection and roaming information is being updated
  2. The app then displays correct icons and text
  3. In the background a task has been registered
  4. Changes in network will result in the task doing something particular (in this example it wont do anything, it only has an OnCompleted method)
  5. Once completed the UI will be updated with new icons and text

The full project can be dowloaded here

OBS! it takes about 30-45 sec for the changes in network to be registered by the background task

Progress rings indicates that connectivity and roaming information is being updated

Icons and text updated to indicate connection and roaming status

Changes in network followed by a background task triggers the UpdateUI method

Displating metering information, more info is available

How the project looks

Adding the background task declared in code in your manifest

View

[sourcecode language=“XML”]

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">  
    <StackPanel Margin="10" VerticalAlignment="Center" HorizontalAlignment="Center" Width="auto" Height="50" Background="White">  
        <StackPanel Orientation="Horizontal" Margin="10" HorizontalAlignment="Center">  
            <ProgressRing IsActive="true" Width="30" Height="30" x:Name="ConnectionProgressRing"/>  
            <Image x:Name="ConnectionIcon" Width="30" Height="30" Visibility="Collapsed"></Image>  
            <TextBlock x:Name="NotifyConnection" FontSize="12" Foreground="SlateGray" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="15,0,0,0">Checking for internet connectivity</TextBlock>  
            <ProgressRing IsActive="true" Width="30" Height="30" x:Name="RoamingProgressRing"/>  
            <Image x:Name="ConnectionCostIcon" Width="30" Height="30" Margin="10,0,0,0" Visibility="Collapsed"></Image>  
            <TextBlock x:Name="NotifyRoaming" FontSize="12" Foreground="SlateGray"  VerticalAlignment="Center" HorizontalAlignment="Left" Margin="15,0,0,0">Getting roaming information</TextBlock>  
        </StackPanel>  
    </StackPanel>  
</Grid>  

Codebehind for the view - here is the ‘magic’

[sourcecode language=“csharp”]

using System;
using System.Net;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Networking.Connectivity;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;

namespace BackgroundTaskConnection
{

public sealed partial class MainPage : Page  
{  

    public MainPage()  
    {  
        this.InitializeComponent();  
    }  

    protected override void OnNavigatedTo(NavigationEventArgs e)  
    {  
        UpdateUI();  
        Register();  
    }  

    private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)  
    {  
        UpdateUI();  
    }  

    void Register()  
    {  
        var task = BackgroundTaskSample.RegisterBackgroundTask("Tasks.SampleBackgroundTask",  
                                                   "SampleBackgroundTask",  
                                                   new SystemTrigger(SystemTriggerType.NetworkStateChange, false),  
                                                   null);  
        task.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);  
        UpdateUI();  
    }  

    private async void UpdateUI()  
    {  
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,  
        () =>  
            {  
                NotifyUser();  
        });  
    }  

    private bool roaming;  
    private string connectionProfileInfo;  

    private async Task NotifyUser()  
    {  
        bool connected = await CheckForConnection();  
        NotifyConnection.Text = connected ? "You are connected" : "You are NOT connected";  
        NotifyRoaming.Text = roaming ? connectionProfileInfo : "No Roaming";  
        SetIcons(connected, "ms-appx:///Assets/Connected.png", "ms-appx:///Assets/ConnectedFalse.png", ConnectionIcon, ConnectionProgressRing);  
        SetIcons(roaming, "ms-appx:///Assets/ConnectedRoaming.png", "ms-appx:///Assets/ConnectedRoamingFalse.png", ConnectionCostIcon, RoamingProgressRing);  
    }  

    void SetIcons(bool isActive, string activeIcon, string inactiveIcon, Image canvas, ProgressRing progressring)  
    {  
        canvas.Visibility = Visibility.Visible;  
        canvas.Source = GetImage(isActive ? activeIcon : inactiveIcon);  
        progressring.IsActive = false;  

    }  

    ImageSource GetImage(string uri)  
    {  
        return new BitmapImage(new Uri(uri, UriKind.Absolute));  
    }  

    private async Task<bool> IsConnectedToInternet()  
    {  
        HttpWebRequest webReq;  
        HttpWebResponse resp = null;  
        Uri url = null;  
        url = new Uri("http://abc.com");  
        webReq = (HttpWebRequest)WebRequest.Create(url);  
        try  
        {  
            resp = (HttpWebResponse)await webReq.GetResponseAsync();  
            webReq.Abort();  
            webReq = null;  
            url = null;  
            resp = null;  
            return true;  
        }  
        catch  
        {  
            webReq.Abort();  
            webReq = null;  
            return false;  
        }  
    }  

    private async Task<bool> CheckForConnection()  
    {  
            bool isConnected = await IsConnectedToInternet();  

            ConnectionProfile internetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();  

            if (isConnected)  
            {  
                if(internetConnectionProfile!= null)//Gets metereing info, Connectionprofile gives false positives when used to check for internet connectivity  
                {  
                    GetMeteringInformation(internetConnectionProfile);  
                }  
                else  
                {  
                    connectionProfileInfo = "Roaming information not available";  
                    roaming = false;  
                }  
                return true;  
            }  
            return false;  
    }  

    private async Task GetMeteringInformation(ConnectionProfile connectionProfile)  
    {  
        ConnectionCost connectionCost = connectionProfile.GetConnectionCost();  

        roaming = connectionCost.Roaming;  

        connectionProfileInfo = "Over Data Limit :" + connectionCost.OverDataLimit + " | Approaching Data Limit :" +  
                                connectionCost.ApproachingDataLimit;  
    }  
}  

}
[/sourcecode]

The backgroundtask registration class

[sourcecode language=“csharp”]
using System;
using Windows.ApplicationModel.Background;
using Windows.Storage;

namespace BackgroundTaskConnection
{
class BackgroundTaskSample
{
public static BackgroundTaskRegistration RegisterBackgroundTask(String taskEntryPoint, String name, IBackgroundTrigger trigger, IBackgroundCondition condition)
{
var builder = new BackgroundTaskBuilder();

        builder.Name = name;  
        builder.TaskEntryPoint = taskEntryPoint;  
        builder.SetTrigger(trigger);  

        BackgroundTaskRegistration task = builder.Register();  

        var settings = ApplicationData.Current.LocalSettings;  
        settings.Values.Remove(name);  

        return task;  
    }  

}  

}
[/sourcecode]

Where the ’template’ for the task is set, notice the namespace

[sourcecode language=“csharp”]
using Windows.ApplicationModel.Background;

namespace Tasks
{

public sealed class SampleBackgroundTask : IBackgroundTask  
{  
    BackgroundTaskDeferral \_deferral = null;  

    public void Run(IBackgroundTaskInstance taskInstance)  
    {  
        \_deferral = taskInstance.GetDeferral();  
        \_deferral.Complete();  
    }  

}  

}
[/sourcecode]

Comments

Leave a comment below, or by email.
beyondblog
1/28/2013 7:16:25 PM
var icp = NetworkInformation.GetInternetConnectionProfile();
  if (icp == null || icp.GetNetworkConnectivityLevel() != NetworkConnectivityLevel.InternetAccess)
{
//  error....
} 
Me La
5/1/2013 8:42:20 AM
What about a progressRing in a ExpendedSplashScreen? 
How and where to load data there if I'm I'm loading data from a XML file? and when to set ProgressRing.isActive = false? 
Can You provide us an example please? Thank you :) 
Waqas Ghouri
5/15/2014 4:53:11 AM
Awesome, thank for share great article. 
Iris Classon
5/30/2014 4:06:38 PM
Reply to: Waqas Ghouri
Thank you for the kind words 


Last modified on 2012-07-04

comments powered by Disqus