Here is a quick (but quite useful) tip for anyone who want to use NFC tags on its application.

NFC tags can be used on Windows (Phone) to open Internet links but they can also be used to open a particular application on your system.

For that, you just need to use/create a LaunchApp message that will be written on the tag:

var proximityDevice = Windows.Networking.Proximity.ProximityDevice.getDefault();
if (proximityDevice) {
    proximityDevice.ondevicearrived = function(device) {
        var launchArgs = "user=Thomas LEBRUN";

        // Package.manifest -> View XML Source -> <Application Id="...">
        var appId = "App";

        var appName = Windows.ApplicationModel.Package.current.id.familyName + "!" + appId;

        var launchAppArgs = launchArgs + "\tWindows\t" + appName;

        var dataWriter = new Windows.Storage.Streams.DataWriter();
        dataWriter.unicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.utf16LE;
        dataWriter.writeString(launchAppArgs);

        var launchAppId = proximityDevice.publishBinaryMessage("LaunchApp:WriteTag", dataWriter.detachBuffer());
       proximityDevice.stopPublishingMessage(launchAppId);
   };
}

The content of the tag is a string, where all the items are separated by “\t”:

  1. Some arguments that you want to use when the app starts
  2. The plateform (in our case, we need to specify “Windows”)
  3. The application name, which contains:
    1. The application id (this one can be found in the manifest file, under the attribute Id of the tag Application)
    2. The current package family name

Using this parameters, we can publish a particular message: LaunchApp:WriteTag. This tag/message will be recognize by the platform which will then ask for the user to open the dedicated application.

So you can easily imagine use this technique to create an new kind of authentification in your application (at least to provide the username).

 

Happy coding!

Scrolling in Windows Store applications is mostly done in horizontal mode. This is something quite easy to do with the GridView which support scrolling with mouse wheel but this can be a quite more complicated to do in Webview.

Indeed, in the Webview control, the mouse wheel scroll is done in vertical mode so here is a quick fix to perform the same scroll in horizontal mode.

To do this, you can use a JQuery plugin like JQuery.MouseWheel: https://github.com/brandonaaron/jquery-mousewheel

In your Webview, load JQuery and this plugin:

var scriptJQuery = "<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.js'></script>";
var scriptJQueryMouseWheel = "<script type='text/javascript' src='ms-appx-web:///Views/web/jquery.mousewheel.js'></script>";

var content = "<!doctype html><html lang=\"fr\"><head><link rel=\"stylesheet\" href=\"ms-appx-web:///Views/web/web.css\" type=\"text/css\" media=\"screen\" />" scriptJQuery + scriptJQueryMouseWheel + "</head>" +
    "<div id=\"articleContent\"><font id=\"article\" face=\"Segoe UI\">" +
        SelectedNews.Description +
    "</div></font>" +
"</html>";

webView.NavigateToString(content);

Once this is done, we can just add a small JavaScript function to handle the “MouseWheel” event:

var mouseWheelScript = "<script type=\"text/javascript\">" +
                        "$(function() {" +
                            "$('html, body').mousewheel(function(event, delta) {" +
                                "this.scrollLeft -= (delta * 50);" +
                                "event.preventDefault();" +
                            "});" +
                        "});" +
                    "</script>";

So the complete code is the following one:

var scriptJQuery = "<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.js'></script>";
var scriptJQueryMouseWheel = "<script type='text/javascript' src='ms-appx-web:///Views/web/jquery.mousewheel.js'></script>";

var mouseWheelScript = "<script type=\"text/javascript\">" +
                        "$(function() {" +
                            "$('html, body').mousewheel(function(event, delta) {" +
                                "this.scrollLeft -= (delta * 50);" +
                                "event.preventDefault();" +
                            "});" +
                        "});" +
                    "</script>";

var content = "<!doctype html><html lang=\"fr\"><head><link rel=\"stylesheet\" href=\"ms-appx-web:///Views/web/web.css\" type=\"text/css\" media=\"screen\" />" + scriptResize + scriptVideo + scriptJQuery + scriptJQueryMouseWheel + mouseWheelScript + "</head>" +
    "<div id=\"articleContent\"><font id=\"article\" face=\"Segoe UI\">" +
        SelectedNews.Description +
    "</div></font>" +
"</html>";

webView.NavigateToString(content);

Now, each time the Webview will get the focus, user will be able to perform a horizontal scrolling using the mousewheel.

Pretty simple when you know!

Please note that the plugin’s file is loaded from ms-appx-web to allow Webview to load it correctly.

 

Happy coding!

Here is a problem we met recently with my colleague Jonathan.

Indeed, in one of the Windows 8 applications we are working, we have a Webview that is loaded thanks to the method NavigateToString:

WebviewNews.NavigateToString(content);

(where content is the HTML fragment that will be displayed in the Webview).

On that HTML, we wanted to insert a custom CSS file so we tried the following:

 var content =
    "<html><head><link rel=\"stylesheet\" href=\"ms-appx:///Views/web/web.css\" type=\"text/css\" media=\"screen\" /></head>" +
         "<font face=\"Segoe UI\">" +
             NewsDetailPageViewModel.SelectedNews.Description +
         "</font>" +
     "</html>";
 WebviewNews.NavigateToString(content);

Unfortunately, this does not work: the code is correct but the CSS rules were not applied.

After a quick look, it appears that the fix is simple: instead of using ms-appx, we needed to use ms-appx-web. Content referenced via this scheme is loaded from the local package, but runs with the abilities and restrictions of the web context.

The correct code was:

 var content =
    "<html><head><link rel=\"stylesheet\" href=\"ms-appx-web:///Views/web/web.css\" type=\"text/css\" media=\"screen\" /></head>" +
         "<font face=\"Segoe UI\">" +
             NewsDetailPageViewModel.SelectedNews.Description +
         "</font>" +
     "</html>";
 WebviewNews.NavigateToString(content);

Using this syntax, the CSS rules were correctly loaded and the HTML content was correctly modified according to our CSS rules.

 

Happy coding!

I’m glad to announce that my first MSDN article (Building and Validating Windows Store Apps with Team Foundation Service) is now available !

It’s a topic I’ve already covered on my blog but I hope you’ll get more information and details in the new and revisited version!

The article is available here: http://msdn.microsoft.com/en-us/magazine/dn166931.aspx

Happy coding (and building) !

A small tip for anyone who look for the information.

Using a custom font in any Windows Store apps (C# / XAML) is easy and the same as you can do in WPF or Silverlight application.

Indeed, the first step is to add the font file to your solution and mark it as “Content” (on the file’s properties). Then, when you want to use your new font, just set the FontFamily property:

 <TextBlock Text="u"
                    FontSize="72"
                    Foreground="Red"
                    FontFamily="Assets/MyNewFont.ttf#My Font Name"/>

As you can see, you just need to point to the right file and add the font name after the # character (this is because a single file can contains multiple fonts so using this syntax, you know exactly which font will be used).

Note that Visual Studio and Expression Blend both support the feature so you’ll be able to see the change directly in the designers.

 

Happy coding!

Windows 8 provide a new Transcoding API that can help you to transcode an audio or video file from one format to another one.

The API is really simple to use and consist of two majors classes:

  1. MediaEncodingProfile, which contains the settings that will determine how the destination file will be transcoded
  2. MediaTranscoder, which will perform the transformation

First, you need to create a profile to indicate how to transcode the file:

var encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD1080p);

MediaEncodingProfile contains factory methods like CreateMp4 or CreateWmv. The parameter of the methods gives the target resolution (in our case 1080p).

Next, you can call PrepareFileTranscodeAsync to transcode the file (after checking if the source can really be transcoded):

var prepareTranscodeResult = await transcoder.PrepareFileTranscodeAsync(sourceFile, destinationFile, encodingProfile);

if (prepareTranscodeResult.CanTranscode)
{
    await prepareTranscodeResult.TranscodeAsync();
}

And voila! Again, you can see that the API is very simple and flexible (you can, if you want, load a profile from a file or trim the destination file using the properties TrimStartTime and TrimStopTime!).

For my tests, I’ve worked with a WMV file of 30 seconds for 25Mb. After converted it in MP4 (1080p), the result file was 65Mb (more bigger for more quality) and another conversion to VGA gave a file of 11Mb: as you can see, the result file depend of the quality you decide to use.

So now, you’re ready to create you own audio/video editor in a cool Windows Store app!

 

Happy coding!

Windows Azure Mobile Services is a awesome product that will help you to deliver great apps using a Windows Azure backend.

One of the feature I like is the possibility to send push notifications to modify tiles in just few lines of code. There is just a small drawback to this technique: as the queue notification must be enable from the client code, you won’t be able to get animated tiles.

But (as there is always a “but” ;), the next part of this post will provide you a simple but useful technique to get animated tiles for you Windows Store app.

In fact, instead of of send a classic notification, we’ll use the sendRaw method of the wns object to send a Raw notification. As a reminder, a raw notification is a notification that’s not displayed on the screen: as a developer, your code is notified that the notification is coming and you have to perform what you want/need.

So first, you have to create your server script (here is mine as an example):

var LASTEST_QUOTES_NUMBER = 5;

var payload;
var idx;

function cleanChannels(callback) {
    var channelsTable  = tables.getTable('Channel');

    channelsTable.read({
        success: function(channels) {
            if(channels.length > 0) {
                channels.forEach(function(channel){
                    if(channel.expirationTime < new Date()){
                        channelsTable.del(channel.id);
                    }
                })
            }

            if(callback) {
                callback();
            }
        }
    })
}

function preparePayload(movie, quote){
     payload += "<QuoteWithMovie>" +
                    "<Movie Title=\"" + movie.title + "\" FrontCover=\"" + movie.poster_path + "\" BackCover=\"" + movie.backdrop_path + "\" />" +
                    "<Quote Text=\"" + quote.text.substring(100) + "\" />" +
                "</QuoteWithMovie>";

    idx++;

    if(idx == LASTEST_QUOTES_NUMBER) {

        payload += "</Results>";

        cleanChannels(function() {
            var channelsTable  = tables.getTable('Channel');

            channelsTable.read({
                success: function(channels) {
                    if(channels.length > 0) {
                        for (var i = 0; i < channels.length; i++) {
                            var channel = channels[i];

                            push.wns.sendRaw(channel.uri, payload);
                        }
                    }
                }
            });
        });
    }
}

function sendLatestQuotes() {

    payload = "";
    idx = 0;

    var moviesTable = tables.getTable('Movie');
    var quotesTable = tables.getTable('Quote');

    quotesTable.where({ ispublished: true })
    .orderBy('date')
    .take(LASTEST_QUOTES_NUMBER)
    .read({
        success: function(latestQuotes) {
            payload += "<Results>";

            latestQuotes.forEach(function(quote) {
                moviesTable.where({ movieid: quote.movieid })
                .read({
                    success: function(movies) {
                       preparePayload(movies[0], quote);
                    }
                })
            })
        }
    })
}

As you can see, the code is pretty simple: a XML payload is construct from some database records and, when I have the number of notification I want (5 because notification queuing allow you to switch up to 5 notifications), I send a raw notification, using the payload constructed before.

On the client side, the code use the PushNotificationReceived event to be notified and, if a raw notification is coming, the code use the content (the XML payload) to update the tile:

 var currentChannel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
currentChannel.PushNotificationReceived += async (sender, args) =>
{
    if (args.NotificationType == PushNotificationType.Raw && args.RawNotification != null)
    {
        await MainTileUpdateTask.UpdateMainTileAsync(args.RawNotification.Content);

        // The raw notification should not be passed to its background task
        args.Cancel = true;
    }
};

The code to update the tile and animate it is dedicated to your application but, for you records, here is the one I’m using:

internal static async Task UpdateMainTile(string content)
{
    _isUpdatingTile = true;

    var tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
    tileUpdater.EnableNotificationQueue(true);

    tileUpdater.Clear();

    var xElement = XElement.Parse(content);
    var quotesWithMovies = from q in xElement.Elements("QuoteWithMovie")
                                            let movie = q.Element("Movie")
                                            let quote = q.Element("Quote")
                                            select new QuoteWithMovie
                                            {
                                                  MovieTitle = movie.Attribute("Title").Value,
                                                  FrontCover = movie.Attribute("FrontCover").Value,
                                                  BackCover = movie.Attribute("BackCover").Value,
                                                  Text = quote.Attribute("Text").Value
                                            };

    var quoteWithMovies = quotesWithMovies as IList<QuoteWithMovie> ?? quotesWithMovies.ToList();
    if (quoteWithMovies.Any())
    {
        for (int index = 0; index < quoteWithMovies.Count; index++)
        {
            var quote = quoteWithMovies[index];

            var frontCoverFileFullUrl =
            await MoviesService.Current.GetFullCoverImageUrlAsync(quote.FrontCover, "w154");
            var backCoverFileFullUrl =
            await MoviesService.Current.GetFullCoverImageUrlAsync(quote.BackCover, "w300");

            var squareImageFilename = string.Format("Square_{0}.jpg", index);
            var wideImageFilename = string.Format("Wide_{0}.jpg", index);

            FileHelpers.DownloadFile(ApplicationData.Current.LocalFolder, squareImageFilename,
            frontCoverFileFullUrl);

            FileHelpers.DownloadFile(ApplicationData.Current.LocalFolder, wideImageFilename,
            backCoverFileFullUrl);

            var wideTile = Core.UI.Notifications.TileContentFactory.CreateTileWideImageAndText01();
            wideTile.Branding = TileBranding.None;
            wideTile.RequireSquareContent = false;
            wideTile.Image.Src = string.Format("ms-appdata:///local/{0}", wideImageFilename);
            wideTile.Image.Alt = quote.MovieTitle;
            wideTile.TextCaptionWrap.Text = quote.Text;

            var squareTile = Core.UI.Notifications.TileContentFactory.CreateTileSquareImage();
            squareTile.Branding = TileBranding.None;
            squareTile.Image.Src = string.Format("ms-appdata:///local/{0}", squareImageFilename);
            squareTile.Image.Alt = quote.MovieTitle;

            var wideTileNotification = wideTile.CreateNotification();
            var squareTileNotification = squareTile.CreateNotification();

             tileUpdater.Update(wideTileNotification);
             tileUpdater.Update(squareTileNotification);
         }
    }

    _isUpdatingTile = false;
}

The might be others techniques to perform the same results but I like this one for one reason: raw notification can be received by BackgroundTask!

So if you add a BackgroundTask (which set its trigger to PushNotificationTrigger) and put you server code in a Mobile Services Scheduler, you’ll be able to update the tile even if the app is not running!

 

Happy coding!

Indeed, there are no Size or Length properties exposed by the StorageFile class. So a simple but useful trick is to read the content of the file as a Buffer and access to the Length property to access the basic properties of the file and use the Size property:

public async static Task<ulong> GetFileSizeAsync(this IStorageFile file)
{
    var properties = await file.GetBasicPropertiesAsync();

    return properties.Size;
}

Happy coding !

During my last holidays, I’ve started to work on a new Windows 8 project (more details on that later) that use Windows Azure Mobile Services as a backend.

During the development, I’ve encountered the following issue which, I suppose, is a bug that will be fixed later.

On my application, I used the following code:

var allItems = await ServiceClient.GetTable<Items>().Where(i => i.IsPublished).ToListAsync();

return allItems;

Unfortunately, this code thrown, every time, the following error:

image

After taking a look in Fiddler, I found the problem:

image

As you may know, Mobile Services use REST to access data on the server and the following REST query does not seem to be valid because there is no query operator (like eq for equal, etc.) and no value. So, I’ve tried to modify my code like this:

var allItems = await ServiceClient.GetTable<Items>().Where(i => i.IsPublished == true).ToListAsync();

return allItems;

As you can see, I’ve just append “== true” to the Where clause and all seems to work like a charm. Indeed, no exception was rise and, looking at the REST query, we can see that all is OK:

image

 

Happy coding!

If you’ve never tried TFS Service yet, you might give it a try right now. Indeed, based on Team Foundation Server 2012, it provides to developers source control feature, build, test and more!

The Build service is really cool because you’ll be able to build any kind of applications and, because it’s cloud-based, you won’t need to have your server running by yourself!

But, even if it’s cool, Build service on TFS Service is still in preview and so, there might be some issues. The first one is that you can’t build Windows Store apps. Indeed, if you try, you’ll encountered the following error:

image

At least, this is a very clear message. Fortunately, as it’s based on TFS 2012, we’ll be able to add a new Build Controller/Agent to indicate to TFS Service that we want to build Windows Store apps on a particular machine (one with Windows 8).

So, first step is to create a Windows 8 virtual machine (I won’t detailed this procedure here as it’s easy to do). Once the VM is ready, we can install all the stuff that we might need: Visual Studio 2012, Windows SDK, etc. (I know that installing VS on build machine might not be the proper way to do but, at least, it works every time).

Once the machine is ready, we’ll add a new build controller and build agent on it. For that, start the installation of Team Foundation Server 2012:

image

Once the installation is done, the Configuration Center is displayed on screen. Here, we won’t choose to configure Team Foundation Application Server but only the Team Foundation Build Service so select this entry and click on “Start Wizard”:

image

On the next screen that appears, you are asking to select the Team Project collection you are configuring build services for:

image

So click on the “Browse” button and add your TFS Service server:

image

Once authenticated, you can select the Team Project Collection that you want:

image

Then, you’ll be back to the previous screen, with the information dedicated to the build services for your team project collection (if you just start, you may see the same thing as the screenshot below: 0 build controller(s) and 0 build agent(s) because even if there are already a build controller/agent for TFS Service, they are is idle state until you trigger a new build):

image

Next, you are ask to configure the number of build controller(s)/agent(s) you want to install on the machine. For now, we’ll just install the build service so choose to configure later (we’ll do it after):

image

Please, note that the number of build agent(s) recommended is proposed according by your server specs (as build agents run concurrently and do processor-intensive work).

Next, you need to provide the account that will run the Build Service. You can use one of the system account but I’m not a big fan of this possibility. I prefer to create dedicated account (but feel free to do as you want for this part):

image

Once the readiness checks has been validated, you’re ready to configure the Build Service:

image

image

Once finish, click on “Close”:

image

You can now see that the Build Service is installed and configured:

image

Now that the service is installed, it’s time to add a controller and an agent. Launch the Team Foundation Server Administration Console from the Start Menu:

image

From the console, select “Build Configuration” to see that the Build Service is configured for the Team Project Collection you’ve chosen and that there is no controller(s)/agent(s):

image

Now, we’ll add a new controller to the Build Service. Why this is needed ? Because you cannot add/attach an on-premise build agent to a hosted build controller (the one available in TFS Service):

image

So click on the “New Controller…” link and add a new one:

image

Once the controller is up & running, we are now ready to add an agent on it so click on the link “New Agent…”:

image

Be sure to select the controller that you’ve just created otherwise, you’ll encountered the previous error. Also, note that I’ve added a tag. This is not necessary but when I’ll create the build definition (later), it’ll help to to be sure that only this agent will be used because this is the only one able to build Windows 8 apps

image

Now that controller and agent are ready, it’s the moment to create the Build definition that will use them to build Windows 8 apps:

image

In Visual Studio, open the Team Explorer, select “Builds” and, under “Actions”, click on “Manage Build Controllers…”:

image

The screen that appears display the list of all controllers/agents available for the Team Project Collection and, as you can see, the controller and agent we have created are correctly displayed (marked as Available):

image

Now, click on the link “New Build Definition” and fill the information needed (I won’t detailed all the screens as they are simples). the most important part is the “Build Defaults” where you have to select the controller we have installed previously and the path where the build outputs will be sent:

image

One the next screen (“Process”), choose the items to build but, most important (under Advanded –> Agent Settings), select the tag corresponding to the agents you want to use to perform this build:

image

image

Save the build definition then start a new build:

image

And voila ! :)

image

The build has been executed successfully and, if you look in the output/drop folder, you’ll see that the package has been deployed correctly:

image

 

Bonus:

Now that your build service is able to build Windows Store apps, you can keep your Virtual Machine on your own DataCenter or, thanks to Windows Azure Virtual Machine, you can upload it in Windows Azure to use it from here. The task to upload a VHD in Windows Azure is really well described here http://www.windowsazure.com/en-us/manage/windows/common-tasks/upload-a-vhd/ or here http://msdn.microsoft.com/en-us/library/windowsazure/gg465385.aspx

Once uploaded (be careful, it can take a very long time according to the VM size), follow the following steps to create a Virtual Machine from VHD (in Windows Azure): http://www.cloudtec.ch/blog/tech/create-virtual-machine-vhd-in-azure.html

 

Now, you don’t have any excuse to not have a real continuous integration for you Windows Store apps!

 

Happy building!