Category Archives: Code

PhoneGap devs–bring your app to Windows Phone and win!

From now until  June 30th, 2013, we are running a competition aimed at developers who have built PhoneGap apps and published in other stores – for example, Apple iTunes, Google Play, Blackberry World, Bada, Symbian, or Palm OS – to take any of their existing PhoneGap apps and port it to Windows Phone 8, like the Untappd app recently ported to Windows Phone 8.

clip_image002

Members of a panel selected from Microsoft, the Adobe PhoneGap team, and industry experts will choose 20 winners, based on apps that are:

  • Original
  • Innovative
  • Easy to use
  • Engaging and visually appealing to the user

The panel will pick 3 grand prize winners who each will receive a Windows Phone 8 and a Surface Pro, and 17 first prize winners who each will receive a Windows Phone 8. All winning apps will be evaluated for featured slots in the Windows Phone Store.

Full details on the Windows Phone Dev Blog here, entry page for the Windows Phone Porting Challenge competition here.

Live Apps: Creating Custom Tile and Lock Screen Images

One of the really great ways that apps in Windows Phone can connect with the user is by supporting Live Tiles – tiles that are more than just a quick launcher, but instead get updated with timely, specific information to connect the user with the data that’s important to them.

As a developer, you can update Tiles in lots of different ways:

For most purposes, the Tile templates are plenty rich enough for the developer to be able to communicate new information to the user. For example, the Flip Tile template allows you to set all the properties shown here:

Windows Phone Flip Tile template properties

However, as you can see the areas for text are fairly limited, and sometimes the developer will want to communicate more than is possible using the available properties. The only way to do this is to create a custom image and draw the text (or additional graphics) onto the custom image, then use that to update the tile.

In Windows Phone 8, your app can also be the Lock Screen image provider. Here, all you can supply is the image, so if you wanted to communicate some up to date information, the only way you can do that is to write onto the image. But what a size of image! Plenty of room for writing additional text, icons or custom graphs for example!

Creating custom images using a User Control

The easiest way to layout a custom tile or lock screen image is to create a User Control of the required size, just as you would lay out a page. Of course, what you put onto the control is entirely up to you, but as an example, here’s the Xaml for a user control for a standard Wide Tile for the FlipTile template:

<UserControl x:Class="RenderImageLibrary.WideTileControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="336" d:DesignWidth="691">
    
    <Grid x:Name="LayoutRoot">
        <Image x:Name="BackgroundImage" Stretch="UniformToFill" />
        <Rectangle Stroke="Black">
            <Rectangle.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#99000000" Offset="0.007"/>
                    <GradientStop Color="#19000000" Offset="1"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock x:Name="TextOverlayTextBox" VerticalAlignment="Center" 
HorizontalAlignment="Center" Text="Text" Margin="31,29,31,77" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" Foreground="White" Width="629" Height="230" /> </Grid> </UserControl>

As you can see, this is layed out in a Grid with an Image element first, and overlaying that is a black filled Rectangle which is semi transparent and overlays the image using a gradient fill. This is there so that the text which forms the top layer – in the TextBlock – and which is drawn in white, is clearly legible, even over a light coloured background image.

image

 

In the code for this control, there is a property to set the text overlay. The background image used is included as content in this sample so is not changeable at runtime, but this could easily be changed so that any new image could be plugged into it.

using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.IO.IsolatedStorage;
using System.Windows.Media.Imaging;

namespace RenderImageLibrary
{
    public partial class WideTileControl : UserControl
    {
        public WideTileControl(string tileText)
        {
            InitializeComponent();

            Text = tileText;
        }

        public string Text { get; set; }

        public event EventHandler<SaveJpegCompleteEventArgs> SaveJpegComplete;

        public void BeginSaveJpeg()
        {
            // Load the background image directly - important thing is to delay 
            // rendering the image to the WriteableBitmap until the image has
            // finished loading
            BitmapImage backgroundImage = 
new BitmapImage(new Uri("DefaultWideTile.jpg", UriKind.Relative)); backgroundImage.CreateOptions = BitmapCreateOptions.None; backgroundImage.ImageOpened += (s, args) => { try { // Set the loaded image BackgroundImage.Source = backgroundImage; // Set the text TextOverlayTextBox.Text = this.Text; // Explicitly size the control - for use in a background agent this.UpdateLayout(); this.Measure(new Size(691, 336)); this.UpdateLayout(); this.Arrange(new Rect(0, 0, 691, 336)); var wb = new WriteableBitmap(691, 336); wb.Render(LayoutRoot, null); wb.Invalidate(); // Create a filename for JPEG file in isolated storage // Tile images *must* be in shared/shellcontent. String fileName = "Tile_" + Guid.NewGuid().ToString() + ".jpg"; var myStore = IsolatedStorageFile.GetUserStoreForApplication(); if (!myStore.DirectoryExists("shared/shellcontent")) { myStore.CreateDirectory("shared/shellcontent"); } using (IsolatedStorageFileStream myFileStream =
myStore.CreateFile(
"shared/shellcontent/" + fileName)) { // Encode WriteableBitmap object to a JPEG stream. wb.SaveJpeg(myFileStream, wb.PixelWidth, wb.PixelHeight, 0, 75); myFileStream.Close(); } // Delete images from earlier execution var filesTodelete =
from f in myStore.GetFileNames("shared/shellcontent/Tile_*")
.AsQueryable()
where !f.EndsWith(fileName) select f; foreach (var file in filesTodelete) { myStore.DeleteFile("shared/shellcontent/" + file); } // Fire completion event if (SaveJpegComplete != null) { SaveJpegComplete(this, new SaveJpegCompleteEventArgs(true,
"shared/shellcontent/" + fileName)); } } catch (Exception ex) { // Log it System.Diagnostics.Debug.WriteLine(
"Exception in SaveJpeg: " + ex.ToString()); if (SaveJpegComplete != null) { var args1 = new SaveJpegCompleteEventArgs(false, ""); args1.Exception = ex; SaveJpegComplete(this, args1); } } }; return; } } }  

 

The most important part of this code is the BeginSaveJpeg method which ensures the control is sized and layed out correctly, renders the control onto a WriteableBitmap which is used to write out the image to a jpg, and then fires the SaveJpegComplete event to inform callers that the work is done. Note that as this is a tile image, the method writes it to the /shared/ShellContent folder which is required for images used for tile updates.

We can now make use of this in – for example – a background agent. Here’s the code from the attached sample that creates a custom image in a background agent:

namespace BackgroundUpdate
{
    public class ScheduledAgent : ScheduledTaskAgent
    {
        ...

        /// <summary>
        /// Agent that runs a scheduled task
        /// </summary>
        /// <param name="task">
        /// The invoked task
        /// </param>
        /// <remarks>
        /// This method is called when a periodic or resource intensive task is invoked
        /// </remarks>
        protected override void OnInvoke(ScheduledTask task)
        {
            // Render a new image for the lock screen
            System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false);

            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (LockScreenManager.IsProvidedByCurrentApplication)
                {
                    LockScreenImageControl cont = new LockScreenImageControl();
                    cont.SaveJpegComplete += (s, args) =>
                        {
                            if (args.Success)
                            {
                                // Set the lock screen image URI - App URI syntax is required!  
Uri lockScreenImageUri = new Uri("ms-appdata:///Local/"
+ args.ImageFileName, UriKind.Absolute); Debug.WriteLine(lockScreenImageUri.ToString());
LockScreen.SetImageUri(lockScreenImageUri); } mre.Set(); }; cont.BeginSaveJpeg(); } }); // Wait for Lock Screen image to complete mre.WaitOne(); // Then reset for the Tile Image operation mre.Reset(); Deployment.Current.Dispatcher.BeginInvoke(() => { // Render the new tile image RenderImageLibrary.WideTileControl wtc = new RenderImageLibrary.WideTileControl( "This text is written onto the image - allows you to specify more text than " + "you can fit onto a standard tile using the available properties in the tile templates"); wtc.SaveJpegComplete += async (s, args) => { try { if (args.Success) { // Set the tile image URI - "isostore:/" is important!
// Note that the control already // puts the image into /Shared/ShellContent which is where tile
// images in the local folder must be
Uri tileImageUri = new Uri("isostore:/"
+ args.ImageFileName, UriKind.RelativeOrAbsolute); Debug.WriteLine(tileImageUri.ToString());
// Set the tile image FlipTileData ftd = new FlipTileData(); ftd.WideBackgroundImage = tileImageUri; ftd.Title = "Set by BG agent"; ShellTile.ActiveTiles.First().Update(ftd); } else { Debug.WriteLine(args.Exception.ToString()); } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } finally { mre.Set(); } }; wtc.BeginSaveJpeg(); } ); // Wait for tile operation to complete mre.WaitOne(); NotifyComplete(); } } }

The result is a pretty custom tile image which you can see after you tap and hold on the sample app where it is listed in the Programs list, and then tap ‘Pin to Start’:

wp_ss_20130328_0001

 

The sample code gives examples for both a custom tile and a custom Lock Screen Image. If you study the code, you can see that the Windows Phone APIs show a shocking disregard (!) for consistency over how the URI of the image must be supplied. For the LockScreen API, the image can be anywhere in local storage, but you must use an ‘Application URI’ format, for example:

Uri lockScreenImageUri = new Uri(“ms-appdata:///Local/myNewLockScreenImage.jpg” UriKind.Absolute);
LockScreen.SetImageUri(lockScreenImageUri);

The ShellTile API is different. Its images must be in /Shared/ShellContent or a subfolder of it, and the URI must be specified as an absolute URI, using the isostore: protocol:

Uri tileImageUri = new Uri(“isostore:/Shared/ShellContent/myNewTileImage.jpg” , UriKind.RelativeOrAbsolute);                            
// Set the tile image
FlipTileData ftd = new FlipTileData
();
ftd.WideBackgroundImage = tileImageUri;
ShellTile.ActiveTiles.First().Update(ftd);

That minor grumble apart, the results are great!

Download the sample solution here

Async and Await for HTTP Networking, Part 2–HttpClient

In my previous post on this topic, Async and Await for Http Networking on Windows Phone, I described how you can use extension methods to create awaitable methods on the WebClient and HttpWebRequest APIs. Courtesy of Microsoft’s .NET Framework team, there have been more developments in this area – the creation of a portable implementation of the HttpClient API, until now available only for Windows 8 Store and .NET Framework 4.5 apps. This API will allow developers to consume HttpClient on Windows Phone 7.5 and higher, Windows Store apps, and .NET Framework 4.0 and higher.

Portable HttpClient for .NET Framework and Windows Phone

As they describe on their blog post here, the .NET Framework team have released a Beta release of the portable version of HttpClient, the modern networking API. The HttpClient library is a set of APIs for .NET which provide a flexible and extensible way to access all things exposed through HTTP. HttpClient exposes the new Task based asynchronous methods, which makes writing responsive and performant UI applications across all platforms a lot simpler.

This is particularly significant for anyone developing apps for both Windows Phone and Windows 8 as it allows you to standardise your networking code around HttpClient.  In addition it also enables other portable library developers who require networking support to use HttpClient while targeting all or a subset of the supported platforms.

To use it, first make sure you have got NuGet v2.1 or later installed (Go to Tools – Extensions and Updates). Then to use the HttpClient package, right click on your solution, go to the Manage Nuget Packages dialog, search for Id Microsoft.Net.Http, and make sure “Include Prerelease” is turned on.

Now you can go ahead and program against the HttpClient API. For example, here’s the code to access the OData feed for the Northwind sample feed at Odata.org:

HttpClient httpClient = new HttpClient();    
httpClient.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
HttpResponseMessage response = null;
try
{            
    response = await httpClient.GetAsync(
        "http://services.odata.org/Northwind/Northwind.svc/Suppliers");

    response.EnsureSuccessStatusCode(); // Throws exception if bad HTTP status code
    Debug.WriteLine(response.StatusCode + " " + response.ReasonPhrase);

    string responseBodyAsText = await response.Content.ReadAsStringAsync();
    var feed = Newtonsoft.Json.JsonConvert.DeserializeObject<SupplierODataFeed>(responseBodyAsText);

    MessageBox.Show("Received payload of " + responseBodyAsText.Length + " characters");

    SuppliersList.ItemsSource = feed.d.results;
}
catch (HttpRequestException hre)
{
    MessageBox.Show("RespCallback Exception raised! Message:{0}" + hre.Message);
}

Using Compression with the Portable HttpClient

Anyone who knows me or has seen the Networking JumpStart video, will know that I am running a bit of  a crusade against the non-application of compression. Too many devs forget the simple fact that mobile apps on cellular networks (that’s not just Phone people – same for Windows 8 machines that have integrated cellular networking!) often find themselves trying to communicate over poor quality networks. Stack the cards in your favour, increase the chance of success and USE COMPRESSION!

Fortunately, many other people share my views on this. The excellent people at AdvancedREI have created the HttpClient.Compression NuGet package, based on original work by the super-excellent Morten Nielsen.

This is also a pre-release NuGet package. After you install that package, all you do is new up an instance of the CompressedHttpClientHandler and pass that into the constructor of HttpClient:

// Requires HttpClient.Compression NuGet package
var handler = new AdvancedREI.Net.Http.Compression.CompressedHttpClientHandler(); 

HttpClient httpClient = new HttpClient(handler); 

As long as your server is configured to serve up compressed content, you will receive data compressed over the wire and the handler will take care of decompression on receipt.

Download the sample code here

Async and Await for Http Networking on Windows Phone

Using async and await for executing long-running operations such as networking calls has many benefits: your code is much cleaner and easier to maintain, the result is automatically marshalled back to the originating thread so you don’t need to use Dispatcher.BeginInvoke to get back to the UI thread, and exception handling is simpler to implement. Many of the APIs in the Windows Runtime on both Windows 8 and and Windows Phone 8 use this pattern. It’s the future way of programming asynchronous operations.

Unfortunately, the networking APIs in Windows Phone 8 have not been upgraded to support async and await. On Windows 8 Store Apps by contrast, HTTP networking APIs have been completely re-implemented to offer only async and await methods: the WebClient API has been removed and replaced with a more performant API, HttpClient, and HttpWebRequest has been revamped and now only offers Async methods. However, by use of some extension methods, we can enjoy the goodness of async and await with the WebClient and HttpWebRequest APIs on Windows Phone 8. It will work with Windows Phone 7.5/7.8 projects as well, as long as you add a reference to the NuGet Microsoft.bcl.Async package which adds in async and Task support for Windows Phone OS 7.1.

First, let’s look at HttpWebRequest. The GetResponseAsync extension method for this allow you to write code that is exactly the same as for Windows 8 – great if you are porting code between the two. Kudos to Mathias Shapiro, colleague at Microsoft, who developed this!

using System.Net;
using System.Threading.Tasks;

namespace WinPhoneExtensions
{
    public static class HttpExtensions
    {
        public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request)
        {
            var taskComplete = new TaskCompletionSource<HttpWebResponse>();
            request.BeginGetResponse(asyncResponse =>
            {
                try
                {
                    HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
                    HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
                    taskComplete.TrySetResult(someResponse);
                }
                catch (WebException webExc)
                {
                    HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
                    taskComplete.TrySetResult(failedResponse);
                }
            }, request);
            return taskComplete.Task;
        }
    }

    public static class HttpMethod
    {
        public static string Head { get { return "HEAD"; } }
        public static string Post { get { return "POST"; } }
        public static string Put { get { return "PUT"; } }
        public static string Get { get { return "GET"; } }
        public static string Delete { get { return "DELETE"; } }
        public static string Trace { get { return "TRACE"; } }
        public static string Options { get { return "OPTIONS"; } }
        public static string Connect { get { return "CONNECT"; } }
        public static string Patch { get { return "PATCH"; } }
    }
}

Using this, your HttpWebRequest calls now look something like this (don’t forget to add a using WinPhoneExtensions; import to the top of your class!):

        private async System.Threading.Tasks.Task GetSuppliers()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://services.odata.org/Northwind/Northwind.svc/Suppliers");
            request.Method = HttpMethod.Get;
            request.Accept = "application/json;odata=verbose";

            try
            {
                HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();

                Debug.WriteLine(response.ContentType);
                // Read the response into a Stream object.
                System.IO.Stream responseStream = response.GetResponseStream();
                string data;
                using (var reader = new System.IO.StreamReader(responseStream))
                {
                    data = reader.ReadToEnd();
                }
                responseStream.Close();

                var feed = Newtonsoft.Json.JsonConvert.DeserializeObject<SupplierODataFeed>(data);
                SuppliersList.ItemsSource = feed.d.results;
            }
            catch (Exception ex)
            {
                var we = ex.InnerException as WebException;
                if (we != null)
                {
                    var resp = we.Response as HttpWebResponse;
                    var code = resp.StatusCode;
                    MessageBox.Show("RespCallback Exception raised! Message:{0}" + we.Message);
                    Debug.WriteLine("Status:{0}", we.Status);
                }
                else
                    throw;
            }
        }

…which is exactly the same as you would use in a Windows 8 store app.

We can do a similar thing for WebClient, though here the benefits are simply that the code you end up writing becomes so much cleaner. You don’t get the benefit of compatibility with Windows 8 since WebClient is not available on that platform.

I won’t list the code of the extension methods here, as it’s a bit lengthier than for HttpWebClient. Please download the samples attached to this post to get the extension methods code. When using the extension methods, you end up with lovely clean code like this:

string url = "https://api.twitter.com/1/statuses/user_timeline.xml?include_entities=true&include_rts=true&screen_name="
    + nameTextBox.Text + "&count=10";

var client = new WebClient();
string response = await client.DownloadStringTaskAsync(new Uri(url));

If you would like to watch me explaining this (and much, much more!) on video, check out the Networking video in the JumpStart series at http://aka.ms/i5qr0z.

Download the accompanying samples for the code!