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:
- When app is started or page navigated to text and progress rings indicate that internet connection and roaming information is being updated
- The app then displays correct icons and text
- In the background a task has been registered
- Changes in network will result in the task doing something particular (in this example it wont do anything, it only has an OnCompleted method)
- 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
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 :)
Awesome, thank for share great article.
Last modified on 2012-07-04