Sunday, March 15, 2015

Universal App Platform (UAP) in the Windows 10 SDK

Microsoft finally disclosed the first information about app development for Windows 10 at the Mobile World Congress in Barcelona.

I was lucky enough to be there in person, so I'll try to recap here what's new in the Windows 10 SDK for those who weren't.


One of the most important point is that Windows 10 takes the Universal App Platform (UAP) concept to the next level:
The same binary will run on phones, tablets, desktops, Xbox, etc.



The fact that the same binary runs on every platform brings interesting new challenges.
Indeed, today when sharing code between projects, developers are used to add conditional compilation statements to adapt the code to devices specifics.
Example:

#if WINDOWS_PHONE_APP
    Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#endif

When this code is compiled for Windows 8.1 (not Phone), the resulting binary will not contain the equivalent instructions.
That means that the resulting binary depends on the platform it is built for.

Tomorrow if we want to have only one single binary that runs on every device, we need all the instruction in the final assembly, even the device-specifics ones. So instead of relying on conditional compilation, the developer will now have to query platform-specific features at runtime.

The equivalent of the previous code with conditional statements becomes:
if(Windows.Foundation.Metadata.ApiInformation
    .IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
    Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
}


The trick is that the UAP adds stubs of classes for platforms that are not concerned with a given API (example: Kinect on Windows Phone) in order to be able to compile, and it is up to the developer to check that the platform the app is running on is supporting this API (if he does not, the app will crash).

Sunday, November 9, 2014

Windows Phone emulator screenshot automation

Taking apps screenshots on various screen sizes & multiple languages is a very time-consuming process.

For example:
If I want to show 6 screenshots on the store
and I support two different screen sizes (768 x 1,280 and 720 x 1,280)
and my app is localized in 7 languages
=> 6 * 2 * 7 = 84 screenshots required!

That's a lot of repetitive work that it I'd like to see automated.

In theory it should be possible to write code that drives the app onto the desired pages with the desired data and culture.
At each step, that code would:
  1. open the page we want to take a screenshot of,
  2. inject the culture-specific sample data (easy if the project uses MVVM and Dependency Injection patterns),
  3. render the entire page via the WinRT RenderTargetBitmap API (or WriteableBitmap.Render in Silverlight apps),
  4. save the resulting image in the emulator virtual SD card so that it appears directly in the mapped folder (on the computer),
  5. name that image with the step number, culture info and screen size.
I'll probably try to work on that project soon (I'll blog about it here).

Wednesday, June 4, 2014

Ideas of improvements for the Windows Dev Center

Here are two ideas I've had when developing my Windows Phone apps that could improve the Windows Dev Center experience:

Staged rollouts

That feature would consist in making new versions of an app available to only a subset of the entire user base (example: 10% of all my users).
It would help limit the impact of unexpected bugs, help anticipate server load, and enable developers to gauge user feedback with a random sample of users.

Publishing APIs

That feature would allow developers to automate the process of updating an app, instead of forcing them to use the Windows Dev Center portal manually.

For example, it could be a RESTful API that I could use in one of my build definitions.
App description, screenshots and icons could also be updated with that API.

Tuesday, February 19, 2013

ASP.NET, IIS7, IIS8 and MIME types for HTML5/CSS3



I recently installed Windows 8 on my laptop. Windows 8 comes with the new IIS version : IIS 8.0.
First surprise after the deployment of the web application I work on: it crashes.
HTTP Error 500.19 - Internal Server Error (The requested page cannot be accessed because the related configuration data for the page is invalid).
The detailed error message indicates that the error comes from the "mimeMap" section of the web.config file:
Cannot add duplicate collection entry of type ‘mimeMap’ with unique key attribute ‘fileExtension’ set to ‘.svg’.

Why do I have a mimeMap tag in my web.config?

That's because at the time, IIS7.x did not support HTML5 and CSS3 mime types like "svg", "woff", etc. We had to excplicitely tell it to handle them or ended up with a 404.3 error and the message "The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.".

But thigs have changed since, and IIS 8 now knows how to handle these mime types out of the box.
So when I ask IIS 8 to handle MIME types it already knows, it crashes. He's like "man, I already KNOW that...".

So what do we do?

A quick fix could be to simply remove these "mimeMap" tags from the web.config, but the problem is that the application would not support IIS7 anymore.
We could also create two web.config (or use web.config transforms) : one for IIS7 and one for IIS8 but IMHO that's not a pretty solution. What I wanted was to have the same web.config on IIS7 or IIS8.

So what I did was simply to use the "remove" tag to remove the MIME type beforehand. The I can safely add them with the "mimeMap" tag:

      <remove fileExtension=".svg" />
      <remove fileExtension=".svgz" />
      <remove fileExtension=".eot" />
      <remove fileExtension=".otf" />
      <remove fileExtension=".woff" />
      <mimeMap fileExtension=".svg" mimeType="images/svg+xml" />
      <mimeMap fileExtension=".svgz" mimeType="images/svg+xml" />
      <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
      <mimeMap fileExtension=".otf" mimeType="font/otf" />
      <mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />

Hope this helps.

Thursday, November 22, 2012

How to add test images on the Windows Phone emulator

When developing an app, and especially a photo app, it is common to have the need
to access photos from the Media Library of the phone in order to test and debug the code if necessary. The Windows Phone emulator comes with some sample photos (7 photos
on WP7 and 8 photos on WP8):
While that helps for basic testing like opening a photo, I like being able to test
with pictures I specifically chose. That way, I can test my app with different kind
of pictures, with different resolutions, etc. In this article, I will show you how
to add your test images to the emulator.

What I wanted was:

  • being able to add specific images in the media library
  • don't affect the XAP size when compiling in Release
  • don't affect performance when running in Release
  • only add images when running in the emulator (my device already has a lot of images
    to test with)

Steps:

1 - Create the 'TestImages'  directory in the project and add your test images

2 - Set the 'Build action' to 'Content' on the files in the Visual Studio properties 

3 - Edit the .csproj (right click on the project, 'Unload Project' then right click,
'edit .csproj') 

4 - Add the configuration condition on the lines that include the files in the project, like this:

<Content Include="TestImages\img1.jpg" Condition="'$(Configuration)' == 'Debug'" />

5 - Add the following code in the App constructor:

#if DEBUG
            if (Microsoft.Devices.Environment.DeviceType == DeviceType.Emulator)
            {
                EmulatorHelper.AddDebugImages();
            }
#endif

6 - Add the EmulatorHelper class:

using System;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using Microsoft.Xna.Framework.Media;
 
namespace MyPhotoApp
{
    public static class EmulatorHelper
    {
        const string flagName = "__emulatorTestImagesAdded";
 
        public static void AddDebugImages()
        {
            bool alreadyAdded = CheckAlreadyAdded();
            if (!alreadyAdded)
            {
                AddImages();
                SetAddedFlag();
            }
        }
 
        private static bool CheckAlreadyAdded()
        {
            IsolatedStorageSettings userSettings = IsolatedStorageSettings.ApplicationSettings;
 
            try
            {
                bool alreadyAdded = (bool)userSettings[flagName];
                return alreadyAdded;
            }
            catch (KeyNotFoundException)
            {
                return false;
            }
            catch (ArgumentException)
            {
                return false;
            }
        }
 
        private static void SetAddedFlag()
        {
            IsolatedStorageSettings userSettings = IsolatedStorageSettings.ApplicationSettings;
            userSettings.Add(flagName, true);
            userSettings.Save();
        }
 
        private static void AddImages()
        {
            string[] fileNames = { "img1""img2""img3""img4""img5" };
            foreach (var fileName in fileNames)
            {
                MediaLibrary myMediaLibrary = new MediaLibrary();
                Uri myUri = new Uri(String.Format(@"TestImages/{0}.jpg", fileName), UriKind.Relative);
 
                System.IO.Stream photoStream = App.GetResourceStream(myUri).Stream;
                byte[] buffer = new byte[photoStream.Length];
                photoStream.Read(buffer, 0, Convert.ToInt32(photoStream.Length));
                myMediaLibrary.SavePicture(String.Format("{0}.jpg", fileName), buffer);
                photoStream.Close();
            }
        }
    }
}
What you have now is a project that automatically adds test images to the Windows Phone Photo
Library, at the condition that
  • the build Configuration is 'Debug'
  • the app is running in the emulator
  • the images have not already been added
The advantage is that is does not impact the Release XAP in any way (performance
or size).

Sunday, November 18, 2012

Windows Phone 8 photo orientation EXIF bug

I noticed a weird bug when testing my photo apps on the new Nokia Lumia 920: photos taken with the PhotoCamera object (ie not with the PhotoChooserTask) are turned upside down!

This blog post is a summary of my investigations for understanding that behavior. First, let me remind you the description of the PhotoCamera class from the MSDN:
Provides the basic camera functionality for a Windows Phone still camera application. This class includes members for enabling and configuring functionality such as image capture, focus, resolution, and flash mode. Also, it provides events for camera focus, image capture, and image availability.
A lot of Windows Phone apps use that class. It appeared in Windows Phone 7.5 and before Windows Phone 8, it was the only way to show a camera viewfinder directly within the app (the Windows Phone 7.0 way to take a photo was to use the CameraCaptureTask).

Once the camera has finished capturing the scene, the PhotoCamera object raises the CaptureImageAvailable event, passing the Stream of the photo as a parameter. In order to show the picture in the good orientation, a good practice since Windows Phone 7.0 and the PhotoChooseTask was to look at the EXIF metadata orientation tag and rotate the photo accordingly. Here was the standard code for doing that:

int angle;
switch (info.Orientation)
{
    case ExifOrientation.TopLeft:
    case ExifOrientation.Undefined:
        angle = 0;
        break;
    case ExifOrientation.TopRight:
        angle = 90;
        break;
    case ExifOrientation.BottomRight:
        angle = 180;
        break;
    case ExifOrientation.BottomLeft:
        angle = 270;
        break;
}

The problem is that Windows Phone 8 seems to have changed the orientation values indicated in the photo EXIF metadata when using the PhotoCamera class. That change causes a compatibility issue for existing apps running on Windows Phone 8 devices: the orientation is wrong.

An app update is necessary to workaround this problem. Here are the values that you need to use:

EXIF orientationAngle on WP7Angle on WP8
TopLeft00
BottomRight180180
TopRight90270
BottomLeft27090

The updated sample code that I use is the following:

// Get the Windows Phone version
int osVersion = Environment.OSVersion.Version.Major;
int angle = 0;
 
if (orientation == ExifOrientation.BottomRight)
    angle = 180;
else if (orientation == ExifOrientation.TopRight)
{
    if (osVersion == 7)
        angle = 90;
    else
        angle = 270;
}
else if (orientation == ExifOrientation.BottomLeft)
{
    if (osVersion == 7)
        angle = 270;
    else
        angle = 90;
}

If you have more information on this subject or a better workaround, I'm interested!



Tuesday, June 26, 2012

Why most of Windows Phone apps that connect with Facebook will stop working on July 5, 2012

When developing apps that connects to social networks like Facebook or Twitter, the common practice is to show the user a web control that allows him to authenticate.

To provide a better user experience, it is recommended to use the appropriate display mode:
  • 'page' for desktop web browsers
  • 'popup' for desktop web browsers without a page redirect
  • 'touch' for touch devices (smartphones, tablets, etc.)
  • 'wap' for mobile phones (deprecated)

The problem is that currently the 'touch' display mode is not supported by Facebook on Windows Phone, so it falls back on 'wap'.

But 'wap' is deprecated and will stop working on July 5.

So the question is: What are we supposed to do?

Here are the options I see:
  1. Wait for Facebook to stop redirecting to 'wap' when asking for 'touch' display mode. The problem is that we don't know when that will happen
  2. Use another display mode. The problem is that the 'page' or 'popup' display modes are completely unusable on mobile devices. The user has to zoom in to enter his credentials then zoom out and scroll down to find where is the confirm button

Anyway, most of the Windows Phone apps that connect to Facebook might stop allowing authentication. Or at least show an unusable login form.

Please, Facebook, help us connecting our apps to your platform!

Links on that subject:
http://www.rudyhuyn.com/blog/2012/04/09/1220/
https://developers.facebook.com/bugs/355102764525510
https://developers.facebook.com/bugs/442450199109200