Introduction to Advanced Windows Store App Development using HTML5 and JavaScript

  • 10/15/2013
In this chapter from Exam Ref 70-482: Advanced Windows Store App Development using HTML5 and JavaScript, you learn how to create background tasks, implement the appropriate interfaces, and consume tasks using timing and system triggers. You also find out how to request lock screen access and create download and upload operations using background transferring for Windows Store applications written in Hypertext Markup Language (HTML)/JavaScript (formerly called Windows Store apps using JavaScript). The last part of the chapter is dedicated to creating and consuming Windows Metadata (WinMD) components.

Objectives in this chapter:

  • Objective 1.1: Create background tasks

  • Objective 1.2: Consume background tasks

  • Objective 1.3: Integrate WinMD components into a solution

Objective 1.1: Create background tasks

Microsoft Windows 8 changes the way applications run. Windows Store application life-cycle management of the Windows Runtime is different from previous versions of Windows: only one application (or two in snapped view) can run in the foreground at a time. The system can suspend or terminate other applications from the Windows Runtime. This behavior forces the developer to use different techniques to implement some form of background work—for example, to download a file or perform tile updates.

This section covers how to implement a background task using the provided classes and interfaces, and how to code a simple task.

Creating a background task

In Windows Store apps, when users work on an app in the foreground, background apps cannot interact directly with them. In fact, due to the architecture of Windows 8 and because of the application life-cycle management of Windows Store apps, only the foreground app has the focus and is in the Running state; the user can choose two applications in the foreground using the snapped view.

All the other background apps can be suspended, and even terminated, by the Windows Runtime. A suspended app cannot execute code, consume CPU cycles or network resources, or perform any disk activity such as reading or writing files.

You can define a task that runs in the background, however, even in a separate process from the owner app, and you can define background actions. When these actions need to alert users about their outcomes, they can use a toast.

A background task can execute code even when the corresponding app is suspended, but it runs in an environment that is restricted and resource-managed. Moreover, background tasks receive only a limited amount of system resources.

You should use a background task to execute small pieces of code that require no user interaction. You can also use a background task to communicate with other apps via instant messaging, email, or Voice over Internet Protocol (VoIP). Avoid using a background task to execute complex business logic or calculations because the amount of system resources available to background apps is limited. Complex background workloads consume battery power as well, reducing the overall efficiency and responsiveness of the system.

To create a background task, you have to create a new JavaScript file with a function that runs in the background when the task is triggered. The name of the file is used to launch the background task.

The function uses the current property of the WebUIBackgroundTaskInstance object to get a reference to the background task, and it contains the doWork function that represents the code to be run when the task is triggered. See Listing 1-1.

Listing 1-1. JavaScript function skeleton for a background task

(function () {
    "use strict";

    //
    // Get a reference to the task instance.
    //
    var bgTaskInstance = Windows.UI.WebUI.WebUIBackgroundTaskInstance.current;

    //
    // Real work.
    //
    function doWork() {
        // Call the close function when you have done.
        close();
    }

    doWork();
})();

Remember to call the close function at the end of the worker function. If the background task does not call this method, the task continues to run and consume battery, CPU, and memory, even if the code has reached its end.

Then you have to assign the event that will fire the task. When the event occurs, the operating system calls the defined doWork function. You can associate the event, called a trigger, via the SystemTrigger or the MaintenanceTrigger class.

The code is straightforward. Using an instance of the BackgroundTaskBuilder object, associate the name of the task and its entry point by using the path to the JavaScript file. The entry point represents the relative path to the JavaScript file, as shown in the following code excerpt:

Sample of JavaScript code

var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
builder.name = "BikeGPS";
builder.taskEntryPoint = "js\\BikeBackgroundTask.js";

Then you must create the trigger to let the system know when to start the background task:

var trigger = new Windows.ApplicationModel.Background.SystemTrigger(
    Windows.ApplicationModel.Background.SystemTriggerType.timeZoneChange, false);
builder.setTrigger(trigger);

The complete enumeration, which is defined by the SystemTriggerType enum, is shown in Listing 1-2.

Listing 1-2. Types of system triggers

// Summary:
// Specifies the system events that can be used to trigger a background task.
[Version(100794368)]
public enum SystemTriggerType
{
    // Summary:
    //     Not a valid trigger type.
    Invalid = 0,
    //
    // Summary:
    // The background task is triggered when a new SMS message is received by an
    // installed mobile broadband device.
    SmsReceived = 1,
    //
    // Summary:
    // The background task is triggered when the user becomes present. An app must
    // be placed on the lock screen before it can successfully register background
    // tasks using this trigger type.
    UserPresent = 2,
    //
    // Summary:
    // The background task is triggered when the user becomes absent. An app must
    // be placed on the lock screen before it can successfully register background
    //     tasks using this trigger type.
    UserAway = 3,
    //
    // Summary:
    // The background task is triggered when a network change occurs, such as a
    // change in cost or connectivity.
    NetworkStateChange = 4,
    //
    // Summary:
    // The background task is triggered when a control channel is reset. An app must
    // be placed on the lock screen before it can successfully register background
    // tasks using this trigger type.
    ControlChannelReset = 5,
    //
    // Summary:
    // The background task is triggered when the Internet becomes available.
    InternetAvailable = 6,
    //
    // Summary:
    // The background task is triggered when the session is connected. An app must
    // be placed on the lock screen before it can successfully register background
    // tasks using this trigger type.
    SessionConnected = 7,
    //
    // Summary:
    // The background task is triggered when the system has finished updating an
    // app.
    ServicingComplete = 8,
    //
    // Summary:
    // The background task is triggered when a tile is added to the lock screen.
    LockScreenApplicationAdded = 9,
    //
    // Summary:
    // The background task is triggered when a tile is removed from the lock screen.
    LockScreenApplicationRemoved = 10,
    //
    // Summary:
    // The background task is triggered when the time zone changes on the device
    // (for example, when the system adjusts the clock for daylight saving time).
    TimeZoneChange = 11,
    //
    // Summary:
    // The background task is triggered when the Microsoft account connected to
    // the account changes.
    OnlineIdConnectedStateChange = 12,
}

You can also add conditions that are verified by the system before starting the background task. The BackgroundTaskBuilder object exposes the AddCondition function to add a single condition, as shown in the following code sample. You can call it multiple times to add different conditions.

builder.addCondition(new Windows.ApplicationModel.Background.SystemCondition(
    Windows.ApplicationModel.Background.SystemConditionType.internetAvailable))

The last line of code needed is the registration of the defined task:

var task = builder.register();

Declaring background task usage

An application that registers a background task needs to declare the feature in the application manifest as an extension, as well as the events that will trigger the task. If you forget these steps, the registration will fail. There is no <Extensions> section in the application manifest of the standard template by default, so you need to insert it as a child of the Application tag.

Listing 1-3 shows the application manifest for the sample task implemented by Listing 1-2. The <Extensions> section is shown in bold.

Listing 1-3. Application manifest

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
  <Identity Name="e00b2bde-0697-4e6b-876b-1d611365485f"
            Publisher="CN=Roberto"
            Version="1.0.0.0" />
  <Properties>
    <DisplayName>BikeApp</DisplayName>
    <PublisherDisplayName>Roberto</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>
  <Prerequisites>
    <OSMinVersion>6.2.1</OSMinVersion>
    <OSMaxVersionTested>6.2.1</OSMaxVersionTested>
  </Prerequisites>
  <Resources>
    <Resource Language="x-generate"/>
  </Resources>
  <Applications>
    <Application Id="App"
        Executable="$targetnametoken$.exe"
        EntryPoint="BikeApp.App">
      <VisualElements
          DisplayName="BikeApp"
          Logo="Assets\Logo.png"
          SmallLogo="Assets\SmallLogo.png"
          Description="BikeApp"
          ForegroundText="light"
          BackgroundColor="#464646">
        <DefaultTile ShowName="allLogos" />
        <SplashScreen Image="Assets\SplashScreen.png" />
      </VisualElements>
      <Extensions>
          <Extension Category="windows.backgroundTasks"
                     EntryPoint="js\BikeBackgroundTask.js">
          <BackgroundTasks>
            <Task Type="systemEvent" />
          </BackgroundTasks>
        </Extension>
      </Extensions>
    </Application>
  </Applications>
  <Capabilities>
    <Capability Name="internetClient" />
  </Capabilities>
</Package>

You have to add as many task elements as needed by the application. For example, if the application uses a system event and a push notification event, you have to add the following XML node to the BackgroundTasks element:

<BackgroundTasks>
   <Task Type="systemEvent" />
   <Task Type="pushNotification" />
</BackgroundTasks>

You can also use the Microsoft Visual Studio App Manifest Designer to add (or remove) a background task declaration. Figure 1-1 shows the same declaration in the designer.

Figure 1.1

Figure 1.1. Background task declaration in Visual Studio App Manifest Designer

Enumerating registered tasks

Be sure to register the task just once in your application. If you forget to check the presence of the task, you risk registering and executing the same task many times.

To check whether a task is registered, you can iterate all the registered tasks using the BackgroundTaskRegistration object and checking for the Value property that represents the task that, in turns, exposes the Name property, as follows:

Sample of JavaScript code

var taskName = "bikePositionUpdate";
var taskRegistered = false;

var background = Windows.ApplicationModel.Background;
var iter = background.BackgroundTaskRegistration.allTasks.first();

while (iter.hasCurrent) {
    var task = iter.current.value;

    if (task.name === taskName) {
        taskRegistered = true;
        break;
    }
    iter.moveNext();
}

Using deferrals with tasks

If the code for the doWork function is asynchronous, the background task needs to use a deferral (the same techniques as the suspend method). In this case, use the GetDeferral method, as follows:

(function () {
    "use strict";
    //
    // Get a reference to the task instance.
    //
    var bgTaskInstance = Windows.UI.WebUI.WebUIBackgroundTaskInstance.current;

    //
    // Real work.
    //
    function doWork() {

        var backgroundTaskDeferral = bgTaskInstance.getDeferral();

        // Do work

        backgroundTaskDeferral.complete();

        // Call the close function when you have done.
        close();
    }

    doWork();
});

After requesting the deferral using the GetDeferral method, use the async pattern to perform the asynchronous work and, at the end, call the Complete method on the deferral. Be sure to perform all the work after requesting the deferral and before calling the Complete and the Close method. Otherwise, the system thinks that your job is already done and can shut down the main thread.

Objective summary

  • A background task can execute lightweight action invoked by the associated event.

  • A task needs to be registered using WinRT classes and defined in the application manifest.

  • There are many system events you can use to trigger a background task.

  • You have to register a task just once.

  • You can enumerate tasks that are already registered.

Objective review

Answer the following questions to test your knowledge of the information in this objective. You can find the answers to these questions and explanations of why each answer choice is correct or incorrect in the Answers section at the end of this chapter.

  1. How can an application fire a background task to respond to a network state modification?

    1. By using a time trigger, polling the network state every minute, and checking for changes to this value

    2. By using a SystemTrigger for the InternetAvailable event and checking whether the network is present or not

    3. By using a SystemTrigger for the NetworkStateChange event and using false as the second constructor parameter (called oneShot)

    4. By using a SystemTrigger for the NetworkStateChange event and using true as the second constructor parameter

  2. Which steps do you need to perform to enable a background task? (Choose all that apply.)

    1. Register the task in the Package.appxmanifest file.

    2. Use the BackgroundTaskBuilder to create the task.

    3. Set the trigger that will fire the task code.

    4. Use a toast to show information to the user.

  3. Is it possible to schedule a background task just once?

    1. Yes, using a specific task.

    2. No, only system tasks can run once.

    3. Yes, using a parameter at trigger level.

    4. No, only a time-triggered task can run once at a certain time.