Best Practices for Web-connected Apps - Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 (2014)

Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 (2014)

Chapter 7. Best Practices for Web-connected Apps

In this final chapter, we're going to look at what we need to do to prepare our apps for store certification and to improve user experience (UX) with respect to network connectivity and push notifications.

There are certain criteria your app must meet to be published on the store and guidelines to help create better UX. Windows Store app guidelines are pretty comprehensive and cover everything needed for Windows Phone apps too. There are some specifics that need particular notice for any web-connected app and apps that implement push notifications.

App certification requirements for the Windows Store

It's worth reading through the App certification requirements for the Windows Store section for general requirements of the applications (at the time of writing this, the document version is 4.7, October 17, 2013), available at http://msdn.microsoft.com/en-us/library/windows/apps/hh694083.aspx.

In particular, the following apply to this subject:

4.1.1 Your app must have a privacy statement if it is network-capable

If your app has the technical ability to transmit data, you must maintain a privacy policy. You must provide access to your privacy policy in the Description page of your app, as well as in the app's settings as displayed in the Windows Settings charm.

App capability declarations that make your app network-capable include: internetClient, internetClientServer and privateNetworkClientServer.

Your privacy policy must inform users of the personal information transmitted by your app and how that information is used, stored, secured and disclosed, and describe the controls that users have over the use and sharing of their information, how they may access their information, and it must comply with applicable laws and regulations.

4.2 Your app must respect system settings for notifications and remain functional when they are disabled

This includes the presentation of ads and notifications to the customer, which must also be consistent with the customer's preferences, whether the notifications are provided by the Windows Push Notification Service or any other service. If a customer disables the notification function, either on an app-specific or a system-wide basis, your app must remain functional.

This means, we need to provide a privacy policy and make sure our apps function when notifications are disabled either through the operating system or from our app. It's a good idea to allow users to control notifications from the app. Let's take a look at how to do it.

UX guidelines

The user guidelines are a good resource for helping us create user-friendly applications:

http://msdn.microsoft.com/en-us/library/windows/apps/hh465424.aspx

Of particular interest is the Guidelines for connection usage data section available at http://msdn.microsoft.com/en-us/library/windows/apps/hh452974.aspx, specifically the following table:

Network Cost Type

Recommended App Behavior

Unrestricted

Use the network connection freely.

Variable/Approaching Data Cap

· Delay or schedule lower priority operations until an unrestricted network is available.

· When streaming content to a user, such as a movie or a video, use a lower bit-rate. For example, if your app is streaming HD-Quality video, stream Standard Definition when on a metered network.

· Use less bandwidth. For example, switching to header-only mode when receiving emails.

· Use the network less frequently. An example solution is to reduce the frequency of any polling operations for syndicating news feeds, refreshing content for a website, or getting web notifications.

· Allow users to explicitly choose to stream HD-Quality video, retrieve full emails, download lower priority updates, etc., rather than doing so by default.

· Explicitly ask for user permission prior to using the network.

Unknown

If the network cost type is unknown, then treat it as an unrestricted network.

Also, read the Guidelines for push notifications (Windows Store apps) section at http://msdn.microsoft.com/en-us/library/windows/apps/hh761462.aspx, with particular attention to the following points:

· Respect your user's battery life

· Do not use push notifications for spam or with malicious intent

· Be aware that WNS has no delivery guarantees

· Do not send confidential or sensitive data through push notifications

· Keep your app server credentials a secret

The following guidelines are also worth referring to:

· Guidelines for toast notifications (Windows Store apps): http://msdn.microsoft.com/en-us/library/windows/apps/hh465391.aspx

· Guidelines for tiles and badges (Windows Store apps): http://msdn.microsoft.com/en-us/library/windows/apps/hh465403.aspx

Implementing a privacy policy

When we create applications that connect to Internet services, we need to provide a privacy policy that can be viewed in the app and that is needed for a Windows Store app submission.

A privacy policy can be embedded in the app, but it's easier to have one on your website (you need a website when you fill in your app's details on the store), and then put a link on the settings page. There are a number of free policy generators that can be used to quickly produce a policy. There's a good overview of different generators available at http://www.applicationprivacy.org/do-tools/privacy-policy-generator/.

Checking the network connection

Before we connect to our services or try and authenticate the user, we can check if the device actually has the capability of making a request using the NetworkInterface.GetIsNetworkAvailable method. We can also examine the cost involved using theNetworkInformation.GetInternetConnectionProfile method to determine whether we should warn the user about potentially high data costs (these are the same for Windows 8 and Windows Phone 8). This is shown in the following code snippet:

using System;

using System.Net.NetworkInformation;

using System.Threading.Tasks;

using Windows.Networking.Connectivity;

using Windows.UI.Popups;

namespace TileTapper.Helpers

{

public class NetworkHelper

{

public async static Task<bool> CheckAvailablity()

{

// Check network availability

if (!NetworkInterface.GetIsNetworkAvailable())

return false;

// Check cost

var cp = NetworkInformation.GetInternetConnectionProfile();

var cost = cp.GetConnectionCost();

if (cost.NetworkCostType == NetworkCostType.Unrestricted

|| cost.NetworkCostType == NetworkCostType.Unknown)

return true;

else if ((cost.NetworkCostType == NetworkCostType.Fixed

|| cost.NetworkCostType == NetworkCostType.Variable

) && (!cost.OverDataLimit && !cost.Roaming))

return true;

// If none of the above criteria are met, ask user if they // wish to continue

bool available = false;

var title = "Network Usage Warning";

var content = "The application needs to get data over the internet, but your current network cost may be high. Do you wish to proceed?";

var md = new MessageDialog(content, title);

md.Commands.Add(new UICommand("Yes", (e) => { available = true; }));

md.Commands.Add(new UICommand("No"));

md.CancelCommandIndex = 1;

md.DefaultCommandIndex = 0;

await md.ShowAsync();

return available;

}

}

}

For Windows Phone, the MessageDialog class is replaced with a MessageBox class, otherwise, the methods are the same.

It is also possible to detect when the connection changes using the NetworkAddressChanged event. In the TileTapper game, the constructor hooks the event and then checks the network in the MainVM constructor. If the network becomes available and the game has not initialized, this is then done:

public MainVM()

{

// Constructor code removed for brevity

// Detect network changes and check current state

System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged + = (s, e) => CheckNetwork();

this.CheckNetwork();

}

private async void CheckNetwork()

{

// Check network is available

if (! await NetworkHelper.CheckAvailablity())

this.IsNetworkOverlayVisible = true;

else

{

// Initialise if required

if (!this._isInitialised)

{

this.Initialise();

this._isInitialised = true;

}

this.IsNetworkOverlayVisible = false;

}

}

}

Managing notifications settings

For the Windows 8 app, we will use the TagHelper class discussed in Chapter 6, Scaling Up with the Notifications Hub, to manage the types of notifications that the user is interested in. For the Windows Phone app, a new SettingsHelper singleton class is used, which just manages a single property accessed by the view model and the ChannelHelper class. This is shown in the following code snippet:

namespace TileTapper.Helpers

{

public class SettingsHelper

{

private const string PUSH_ENABLED = "PUSH_ENABLED";

// Singleton instance

public static readonly SettingsHelper Default = new SettingsHelper();

private SettingsHelper() { }

public bool IsPushEnabled

{

get {return StorageHelper.GetSetting<bool>(PUSH_ENABLED);}

set {StorageHelper.StoreSetting(PUSH_ENABLED, value, true);}

}

}

}

The ChannelHelper class is modified to close and dispose the channel and unregister with the service and hub, if needed. This is shown in the following code snippet:

public async Task SetupChannel()

{

try

{

bool attach = false;

// Try to find the push channel

if (this._pushChannel == null)

{

attach = true;

this._pushChannel = HttpNotificationChannel.Find(CHANNEL_NAME);

}

// Check if user has enabled

bool enabled = SettingsHelper.Default.IsPushEnabled;

// If the channel was not found, then create a new connection // to the push service.

if (this._pushChannel == null && enabled)

{

this._pushChannel = new HttpNotificationChannel(CHANNEL_NAME);

this.AttachEvents();

this._pushChannel.Open();

// Bind channel for Tile events.

this._pushChannel.BindToShellTile();

// Bind channel for Toast events

this._pushChannel.BindToShellToast();

}

// If channel was found but not required, close it

else if (this._pushChannel != null && !enabled)

{

await this.UnRegister();

this._pushChannel.Close();

this._pushChannel.Dispose();

this._pushChannel = null;

}

// Channel is found and needed so just attach

else if (this._pushChannel != null && enabled && attach)

this.AttachEvents();

}

catch (Exception ex)

{

System.Diagnostics.Debug.WriteLine(ex.ToString());

}

}

public async Task UnRegister()

{

try

{

// UnRegister with service

var service = new DataService();

await service.DeleteChannel(this.GetDeviceUniqueName());

// UnRegister with hub

var hub = new NotificationHub(this.HUB_NAME, this.CONNECTION_STRING);

await hub.UnregisterAllAsync(this._pushChannel.ChannelUri.AbsoluteUri);

}

catch (Exception ex)

{

System.Diagnostics.Debug.WriteLine(ex.ToString());

}

}

I've left out the methods we've already discussed, and you can always refer to the code.

Implementing settings pages

In the Windows Phone game, I've put in a settings page (Settings.xaml) that has a single ToggleSwitch to control whether the push channel is open and registered with the hub or our service. The ToggleSwitch is bound to a property in the view model, which exposes the SettingsHelper.Default.IsPushEnabled property and calls the ChannelHelper.Default.SetupChannel method on change. This is shown in the following screenshot:

Implementing settings pages

There is also Version information and a button that launches a web browser with our privacy policy using the WebBrowserTask method. Please refer to the code for full view and view model implementations.

Windows Store apps of course have a dedicated settings panel exposed via the Charm bar. Fortunately, Windows 8.1 has a new SettingsFlyout control, which makes creating settings flyouts vastly easier than in 8.0. Also, AppSettingsFlyout.xaml allows the user to choose categories that they want to be notified about and the type of notification. The toggle switches bind to properties in the TagHelper class and calls the TileTapperPush.UploadChannel; method on change:

Implementing settings pages

There is also Version information and a button which launches a web browser with our privacy policy using the Launcher.LaunchUriAsync method. As with the phone app, please refer to the code for full view and view model implementations.

Summary

Well, we've reached the end of the book and covered all the things we need to develop our applications enabled with Windows Azure Mobile Service. By this point, we've probably got some polishing up to do in our code and UI (I know I have), but we can also get our service ready for production by doing the following things:

· Have a look at the logs and make sure there are no errors you need to fix.

· Turn off the automatic database schema function. In the portal's CONFIGURE, tab under the Dynamic Schema section, disable the ENABLE DYNAMIC SCHEMA switch.

· Review the Rules for choosing permissions section in Chapter 3, Securing Data and Protecting the User, and check if the permissions are correct on all the tables and APIs.

· Pull a copy of the scripts using Git and back them up.

· Check any scheduled tasks are scheduled properly, if required.

· Check your scaling configuration.

Once we're live, we can then use the dashboard to monitor how our services are performing and tune them once the apps are live.

Hopefully, you've enjoyed the book. I've had fun writing it! I've tried to put a lot of stuff into the code samples to help round off the book, so make sure you check these out too and feel free to copy and reuse as much as you can. The source is available athttp://www.packtpub.com.