What’s New in Windows Phone 8.1- New features overview (Part 4 out of 5)

April 2, 2014

With convergence, WP8.1 received many interesting feature from Windows 8.x. In this post I will overview some of them:

* Geofencing
* Sharing
* Roaming
* Background tasks
* Push notifications, Tiles and Toasts
* WP Emulator and Tools

 

Geofencing

Geofencing APIs enables scenarios such as notifications when the device enters or leaves an app-specified geographic region. This makes possible app scenarios such as displaying a reminder when the user arrives at home or notifying the user of deals at stores in area he is currently. Let’s see how to setup the geofence an respond on the geofencing events. First of all, the app must declare a “Location” capability in application manifest:

image

Next, the good idea is to check access status to the Geolocator:

try 

{

    //Get geolocator

    geolocator = new Geolocator();

 

    //Optionally

    await geolocator.GetGeopositionAsync().AsTask(token);                                                                

} 

catch (UnauthorizedAccessException) 

{ 

    //...

}

This code ensures that user enabled location services and helps adjust app flow in case he doesn’t. Please note, that app can still set up a Geofence without location permissions but it won’t receive any notifications until the permissions have been enabled.

Setting up a geofence is pretty easy – every app has a collection of geofences identified by Id and defined by region of interest. In addition, the geofence definition contains properties such as MonitoredStates (which indicate what geofence events you want to receive notifications for), DwellTime (indicates how long the user must be in or out of the defined area before the enter/exit events are triggered), StartTime (indicates when to start monitoring the geofence) and others.

//Create a geoshape object that indicates area of interest

var geocircle = new Geocircle(position, radius);

 

//Define which events should be reported to the app

var mask = MonitoredGeofenceStates.Entered | MonitoredGeofenceStates.Exited;

 

//Define how long user should be in or our of area of interest before the event is raised

var dwellTime = TimeSpan.FromSeconds(5);

 

//Create a new object and add it to the collection of geofences

var geofence = new Geofence(id, geocircle, mask, false, dwellTime);

GeofenceMonitor.Current.Geofences.Add(geofence);

Geofence object supports different types of areas – in the code snippet above I used a circular area, but you can define rectangular area (GeoboundingBox), series of geographic points (Geopath) or even single geographic point (Geopoint).

Also, it could be a good practice to check the presence of specific geofence in the geofences collection as they are preserved between application sessions by system-wide GeofenceMonitor component. The geofences are not removed from the collection automatically and must be manually removed by the app.

When geofence is added to the collection, the app could subscribe to the state changes and read the report from the reports:

//...

GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;

//...

 

private async void OnGeofenceStateChanged(GeofenceMonitor sender, object args)

{

    var reports = sender.ReadReports();

 

    //Run in dispatcher if needed to update some UI elements

    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

    {

        foreach (var report in reports)

        {

            //Each report conteains info about new state, position and geofence object

            var state = report.NewState;

            var geofence = report.Geofence;

 

            if (state == GeofenceState.Entered)

                //App logic...

            else if (state == GeofenceState.Exited)

                //App logic...

        }

    });

}

Geofencing could be debugged via new WP emulator – I will talk about the emulator later in this post.

 

Sharing

Additional new feature supported on WP8.1 form Win8.x s Sharing. While the UI is different as WP doesn’t support charms, the API is the same. To share from the app, simply. It is initiated by the following line of code:

Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareUI();

The sharing UI on WP8.1 looks as follows:

image

To react on data sharing requests, the app should subscribe to relevant event and set shared data as follows:

//...

DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();

dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(ShareTextHandler);

//...

 

private void ShareTextHandler(DataTransferManager sender, DataRequestedEventArgs args)

{

    //Get the request object

    DataRequest request = args.Request;

 

    //Setup sharing properties

    request.Data.Properties.Title = "Share Text from WP 8.1";

    request.Data.Properties.Description = "A demonstration that shows how to share text.";

    //Set shared data

    request.Data.SetText("Hello WP Blue!");

}

Sharing with build-in Messaging app produce the following:

image

In order to support sharing (be the share target), app must declare a “Shared Target” declaration in application manifest and specify data formats supported by the app:

image\

Note: those declarations and the following code snippets are pretty similar to Win8.x sharing.

When app is registered as shared target, it will appear in the list of apps that declared support of data formats being transferred by the source app:

image

If user select the app, it can response on activation events and handle the data shared in the data package:

protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)

{

    base.OnShareTargetActivated(args);

 

    //App can process shared data with or without UI. This app navigates to dedicated "Sharing" page

    var frame = Window.Current.Content as Frame;

    if (frame == null)

    {

        frame = new Frame();

 

        Window.Current.Content = frame;

    }

 

    //Sharing operation object is passed to the dedicated page

    frame.Navigate(typeof(SharingPage), args.ShareOperation);

}

Handling the data depends on the app logic. Sample code shows how to pull some supported data formats form the data package:

protected async override void OnNavigatedTo(NavigationEventArgs e)

{

    base.OnNavigatedTo(e);

 

    //Pull sharing operation from the parameters

    args = e.Parameter as ShareOperation;

 

    //Check for supported data format and pull it from the package

    if (args.Data.Contains(StandardDataFormats.Text))

    {

        var message = await args.Data.GetTextAsync();

        //...

    }

 

    if (args.Data.Contains(StandardDataFormats.WebLink))

    {

        var uri = await args.Data.GetWebLinkAsync();

        //...

    }

 

    //...

}

To support long-running share operations, the ShareOperation object supports reporting various sharing states such as Started, DataRetreived, Completed.

 

Roaming

WP8.1 supports data and settings roaming through same APIs as Win8.1.

To access roaming settings use Windows.Storage.ApplicationData.Current.RoamingSettings.
To access roaming folder use Windows.Storage.ApplicationData.Current.RoamingFolder.

The data in roaming settings/folder will be synchronized between all devices of the same user with this app installed. Note, that data roaming is limited to approx. 100kb of data.

 

Background Tasks

Another converged feature of WP8.1 is background tasks that works almost exactly like on Win8.1. Let’s quickly overview how to create a simple background task.

First of all – the task itself is hosted as Windows Runtime Component and implements IBackgroundTask interface. Sample worker looks like the following:

public sealed class MyTask : IBackgroundTask

    {

        public async void Run(IBackgroundTaskInstance taskInstance)

        {

            var deferral = taskInstance.GetDeferral();

 

            //Cancelled events are not fired on WP8.1 so the task must handle the canellation gracefully

            taskInstance.Canceled += (s, e) => { };

 

            System.Diagnostics.Debug.WriteLine("Background task is running...");

 

            for (int i = 0; i <= 100; i++ )

            {

                //Report progress to the foreground app if it is active and listerning

                taskInstance.Progress = (uint)i;

 

                //Simulate some work...

                await Task.Delay(TimeSpan.FromMilliseconds(50));

            }

 

            System.Diagnostics.Debug.WriteLine("Background task is finished...");

            deferral.Complete();

        }

    }

Next, after adding a references to the project, the background task must be declared in the declarations section of the application manifest:

image

Note, that entry point points to the class in the component created previously. Also, the supported task type is set to Timer, which means it will run on timer triggered by the system.

Next, and this is the difference from Win8.1, the app must request access to run in the background:

//Check that the app has an access to background tasks and request if needed

var accessStatus = BackgroundExecutionManager.GetAccessStatus();

 

if (accessStatus == BackgroundAccessStatus.Unspecified ||

    accessStatus == BackgroundAccessStatus.Denied)

    accessStatus = await BackgroundExecutionManager.RequestAccessAsync();

 

//Check that the background tasks are allowed and connectivity matches the task needs

if (accessStatus == BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity ||

    accessStatus == BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity)

{

    //...

}

Once app has an access to the background tasks, the task could be registered (or unregistered if needed) as follows:

string TaskName = "MyTask";

IBackgroundTaskRegistration taskRegistration = null;

 

//Optionally check existing background tasks and skip the registration

if (BackgroundTaskRegistration.AllTasks.Count > 0)

{ 

    foreach (var task in BackgroundTaskRegistration.AllTasks.Values)

    {

        if (task.Name == TaskName)

            taskRegistration = task;

    }

}

 

//Optionally, if task is already registred it could be managed by the app - in this example unregistered

if (null != taskRegistration)

{

    Debug.WriteLine("Task is already registered.");

 

    //Unregister if needed

    if (taskRegistration.Name == TaskName)

        taskRegistration.Unregister(true);

}

else

{

    Debug.WriteLine("Task is not registered, registering...");

 

    //Register the background task if not registered yet...

    BackgroundTaskBuilder builder = new BackgroundTaskBuilder();

    builder.Name = TaskName;

    builder.TaskEntryPoint = typeof(BackgroundWorker.MyTask).FullName;

 

    //Set the trigger - must match the trigger type declared in the manifest

    TimeTrigger triger = new TimeTrigger(15, false);

    builder.SetTrigger(triger);

 

    taskRegistration = builder.Register();

}

Finally, if app requires to get notifications about the task progress/complete (only when in foreground) the taskRegistration could be used to subscribe to the events:

taskRegistration.Completed += taskRegistration_Completed;

taskRegistration.Progress += taskRegistration_Progress;

and handled according to app’s business logic:

void taskRegistration_Progress(BackgroundTaskRegistration sender, BackgroundTaskProgressEventArgs args)

{

    Debug.WriteLine("Task reports progress: " + args.Progress);

    //...

}

 

void taskRegistration_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)

{

    try

    {

        //Call this to get an exception if the background task completed event has reported an error

        args.CheckResult();

 

        Debug.WriteLine("Task completed succesfully");

        //...

    }

    catch

    {

        Debug.WriteLine("Task failed");

        //...

    }

 

}

Visual Studio comes handy when need to debug the background tasks as it provides a simulation of lifecycle events and background tasks through the “Debug Location” menu and helps to simulate the trigger that launches the background task under the debugger:

image

 

Push Notifications, Tiles and Toasts

WP8.1 supports different type of push notifications depending on the technology used to develop the app. If the app is SL8.1 app, the dev can choose “good-old” WP approach using MPN (Microsoft Push Notification Server) or opt-in newer WNS (Windows Notification Server) approach which is shared with Win8.1. This selection is done in WPAppManifest – the old portion of SL8.1 phone app:

image

This selection influences which types of tiles will be supported by the app. The MPN selection will leave the app with WP8.0 compatible tiles selection (Flip, Cycle and Iconic) and related APIs. The WNS selection will force the app to use WinRT tiles and APIs.

If the app is WinRT app, then only WNS push notifications are supported. WNS supports delivering Toasts, Tiles, Badges and Raw XML push notifications exactly like on Win8.1.

Working with either MPN or WNS and preparing the app to work with either one of them will follow exact pattern of WP8.0 app (for MPN) or Win8.x app (for WNS). For full info, please refer to the relevant APIs/documentation.

While MPN tiles/toast selection are not changed from WP8.0, the WNS tiles and toasts are converged with Win8.1. Let’s overview the the converged toasts and tiles and how to create manage them on WP8.1.

Toasts & Action Center

Technically, WP8.1 supports all toast templates from Win8.1, but since the toast notification is presented differently on the device all templates being rendered the same. It  means that regardless to the selected toast template form ToastTemplateType enum, user will be presented with the same standard WP toast experience:

image

The toast could be raised from active app, push notification or while running in background task. Following is the sample of how to show toast notification from the running app:

//Create toast notification

ToastNotification toast = new ToastNotification(ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText03));

 

//Update toast fields with info

//...

 

//Show the toast

ToastNotificationManager.CreateToastNotifier().Show(toast);

In addition to simply showing the notification, WP8.1 enables app to manage them through Action Center. Action Center enable app to show/present up to 20 notifications and persist them up to 7 days in the Action Center. In the Action Center user can chase the notification (tap to open the app) and remove notification (single, all, group).

Developer can manage app notifications by adding a new notification, removing or replacing existing notification, grouping and tagging notifications for easy management, set an expiration time on the notification and send a “Ghost” notification which is shown only as an icon in Action Center but not pops up as regular toast. The following code snippet shows how to manage the notifications from the app:

//Create toas notification

ToastNotification toast = new ToastNotification(ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText03));

//Update info

//...

 

//Set a group for the toast

toast.Group = "Blog post";

//Tag a toast so it could be found (and removed)

toast.Tag = "Sample_toast";

//Set expiration time (up to 7 days)

toast.ExpirationTime = (DateTimeOffset.Now + TimeSpan.FromMinutes(10));

//Specify a "Ghost" mode - this notification will be shown only as an icon and not as popup

toast.SuppressPopup = true;

//Show the toast

ToastNotificationManager.CreateToastNotifier().Show(toast);

 

//...

 

//Remove all app notifications

ToastNotificationManager.History.Clear();

 

//Remove specific notification by the tag

ToastNotificationManager.History.Remove("Sample_toast");

 

//Remove specific notification by the tag from specific group

ToastNotificationManager.History.Remove("Sample_toast", "Blog Post");

 

//Remove all notifications from the group

ToastNotificationManager.History.RemoveGroup("Blog Post");

The “Ghost” notification produced from the code above looks like the following:

image

To show tiles the app must be set as “Toast capable” in the application manifest:

image

Tiles & Badges

The tile feature is more “visually” converged, share about 40 tile templates with Win8.1 platform but still have some minor UI differences to support native WP UX.

First, WP still supports only 3 sizes of the tiles – this means that Square 310×310 (aka Huge) tile is not supported on WP.

Next, while the APIs are exactly the same, the presentation of the tiles is different. For example “peek” animation on WP presented as flip animation, “Image collection” on WP looks exactly like Cycle tile, “Block” looks like Iconic tile.

Lastly, badges shown show platform specific UI and WP doesn’t support all badge types, but only numbers and “alert” + “attention” glyphs.

The code below shows how to update main app tile using new converged templates:

//Create a tile XML -- could be create using different approaches such as TileTemplateType enum, NotificationExtensions from Win8 SDK, etc.

string theTileXML = @"<tile>

                        <visual version=""2"">

                            <binding template=""TileSquare150x150PeekImageAndText01"" fallback=""TileSquarePeekImageAndText01"">

                                <image id=""1"" src=""ms-appx:///assets/Tile150x150.png"" alt=""alt text""/>

                                <text id=""1"">Blog post</text>

                                <text id=""2"">sample tile</text>

                                <text id=""3"">by</text>

                                <text id=""4"">Alex Golesh</text>

                            </binding>  

                        </visual>

                    </tile>";

 

 

//Create XML document and load the content

XmlDocument tileDoc = new XmlDocument(); 

tileDoc.LoadXml(theTileXML); 

//Create a tile

TileNotification myNewTile = new TileNotification(tileDoc); 

//Create tile updater and update main app tile

TileUpdater myTileUpdater = TileUpdateManager.CreateTileUpdaterForApplication(); 

myTileUpdater.Update(myNewTile);

The resulting tile looks as follows (flip tile, two sides):

imageimage

Secondary tiles use the same templates and same APIs as on Win8.1 and produce same type of visuals as described above.

Finally, WP8.1 supports periodical tile updates. It requires some web-based resource that generates tile response and could be used by the app for periodic tile update. Tile update frequency set in application manifest, similarly to Win8.1:

image

Note: this tile update mechanism could be used also to update the app’s tile on install as the tile will be updated right after installing the app with such declaration in application manifest.

 

WP Emulator & Tools

New version of WP SDK brings improved WP emulator and few changes/improvements in the tools. What’s new there?

First of all – many different WP 8.1 emulator images:

image

Next – new project templates, that help to create either Silverlight or WinRT apps:

image

Next, it brings so-called “Universal apps” templates that creates a project that supports two target platforms. Lets’ review such project structure:

image

The solution includes phone-specific app, windows-specific app and shared part that will be compiled in both projects. This shared project can include XAML and code files, assets, folders, etc. The code in “Shared” project is not a portable library code, but full WinRT code to be compiled with target app similarly to source file linking.

VS helps moving files between platform-specific projects and sharing project:

image

While editing shared code, the VS provides scope switch so the same file could be “seen” using target-platform definitions such as constants, platform-specific references, conditional compilation symbols, etc:

image

To distinguish between two platforms in shared code file the project defines a conditional compilation symbols:

WINDOWS_APP for Win8.1

WINDOWS_PHONE_APP for WP8.1

In such case the context switch described above helps to visually distinguish between active/inactive code

imageimage

Same switch exists also in XAML editor:

image

image

In addition to editor improvements, the SDK supplies new set of developer tools, that can help with fine tuning the app:

image

The tools are working with either emulator or real device and can monitor specific areas of the app:

image

Helps to monitor real time app performance:

image

and record specific information to identify potential problematic areas or debug real app problems:

image

New version of tools removes Simulation Dashboard from WP8.1 apps (still available for WP8.0 apps with old version of emulator) but updated emulator has all the functionality.

The updated version of WP emulator includes touch emulation (finally!), physical buttons emulation (volume up/down, power, camera), additional tools such as network condition emulation, SD card emulation, push notifications emulation, hardware sensors emulation and emulator checkpoints management to help preserve configured emulator instance (for example with some uploaded images and email accounts).

image

Emulator camera supports both WP8.0 and WP8.1 modes (configurable through Sensors tab) and WP8.1 UI also looks slightly different:

image

By default new emulator image has quite few apps pre-installed, but still not full OS image as on the real device:

image

 

 

That’s it for new features brief overview. Next time I will be showing how to update existing WP8.0 app to WP8.1.

Stay tuned,

Alex

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*