[Windows Phone 8] Nokia Imaging SDK 2: Editando imágenes

Hola a todos!

Continuamos la serie de artículos sobre el SDK de trabajo con imágenes publicado por Nokia. Si te perdiste los anteriores, puedes verlos aquí:

En este segundo artículo vamos a empezar a trabajar con imágenes. Este SDK nos facilita la edición de las mismas, permitiéndonos rotar y recortar nuestras fotos de una forma rápida y sencilla.

Antes de comenzar a trabajar con el SDK en sí mismo, vamos a repasar la estructura de proyecto que utilizaremos en este y otros ejemplos (la que usamos normalmente en todos los ejemplos de este blog: MVVM).

Estructura del proyecto

Vamos a aislar la lógica de trabajo con imágenes en un servicio llamado ImagingService. Nuestra ViewModel recibirá mediante inyección de dependencias, gracias a nuestro querido Autofac, una instancia de este servicio al que podrá llamar para:

  • Obtener una imagen de la galería.
  • Recortar una porción de imagen seleccionada previamente por el usuario.
  • Rotar una imagen 45 grados desde su orientación original.
  • Rotar una  imagen 270 grados mediante el enumerado de rotaciones.
  • Guardar una imagen.

Por lo tanto, en este proyecto trabajaremos entres niveles:

  • XAML: en el archivo MainPage.xaml definiremos nuestra interface de usuario. Como vamos a usar el ApplicationBar para ejecutar acciones, tendremos que usar code behind para llamar a nuestra viewmodel.
  • ViewModel: en el archivo VMMainPage definiremos nuestra lógica e invocaremos al servicio de imagen siempre que sea necesario.
  • Servicio: en el archivo ImagingService tendremos el código que realiza las acciones sobre la imagen.

Vamos a comenzar!

Sesión de edición y conceptos del SDK de imágenes de Nokia

El primer concepto que debemos tener claro, y que nos servirá para todas las acciones que realicemos con el SDK, es el concepto de sesión de edición.

Siempre que queramos, de alguna forma, trabajar con imágenes usando el SDK de Nokia, tendremos que hacerlo en el contexto de una sesión de edición, definida por la clase EditingSession. Esta clase implementa IDisposable, por lo que la forma recomendada de utilizarla es mediante un bloque using:

Clase EditingSession
using (EditingSession session = new EditingSession(bmp))
{

}

Al crear una nueva instancia de EditingSession debemos indicar la imagen sobre la que deseamos trabajar. Para llevar a cabo esto, podemos pasar al constructor una instancia de tipo IBuffer o una instancia de tipo Bitmap. El tipo Bitmap viene incluido con el SDK de Nokia, en el namespace Nokia.Graphics.Imaging y contiene información de los píxeles de una imagen. Como podremos ver más adelante, tendremos nuevos métodos de extensión que nos permitirán obtener un Bitmap a partir de un WriteableBitmap o un IBuffer a partir de un MemoryStream.

Una vez que hayamos creado nuestra sesión de edición podremos empezar a jugar con nuestra imagen. Básicamente todo el trabajo se realizará en dos pasos:

  • Aplicar modificaciones a la imagen, mediante recortes, filtros…
  • Usar un método de renderizado para aplicar de forma efectiva las modificaciones y obtener la imagen modificada.

Para llevar a cabo el segundo paso, EditingSession nos facilita tres métodos:

  • RenderToBitmapAsync
  • RenderToImageAsync
  • RenderToJpegAsync
  • RenderToWriteableBitmapAsync

Cada uno de estos métodos admite unos parámetros de entrada y nos ofrece un resultado, indicado en su nombre. De esta forma, RenderToBitmapAsync nos pide como parámetro de entrada un Bitmap sobre el que dibujará la imagen. RenderToImageAsync nos pide un control Image sobre el que dibujará y de forma opcional un valor del enumerado OutputOption. Este enumerado, contenido dentro del namespace Nokia.Graphics.Imaging, indica la forma en la que dibujaremos la imagen:

  • PreserveAspectRatio, que indica que se debe conservar el ratio de aspecto de la imagen original (4:3, 16:9…)
  • Stretch, que indica que se descarte el ratio de aspecto original y se ajuste la imagen a las nuevas dimensiones, aunque necesite ser deformada para ello.

RenderToJPegAsync tiene varias sobrecargas. Por defecto no requiere ningún parámetro de entrada y nos devolverá de forma asíncrona la nueva imagen en formato IBuffer. Podemos indicarle el tamaño final que deseamos que tenga la imagen y un valor del enumerado OutputOption. En su tercera sobrecarga podemos indicarle, además, la calidad que deseamos asignar a la imagen y un valor del enumerado OutputColorSpacing:

  • Yuv420, YUV con un subsampling chroma de 4:2:0. Esto es, por cada dos veces que se pasa por Y, se hace una pasada a U y cero a V.
  • Yuv422, YUV con un subsampling chroma de 4:2:2. Esto es, por cada dos veces que se pasa por Y, se pasa una vez por U y V. Este es el formato standard, por norma general en las cámaras Android.

Por último, pero no menos importante, RenderToWriteableBitmapAsync, nos permite volcar nuestra EditingSession a un WriteableBitmap, indicando de forma opcional también el enumerado OutputOption.

Y ahora que ya sabemos como funciona el concepto más básico del SDK de imágenes de Nokia, vamos a pasar a ver como aplicarlo…

Recorte de imágenes con el SDK de Nokia

Es realmente sencillo. Existen, de hecho, varias formas en las que podemos recortar una imagen. Podemos hacerlo antes de comenzar la sesión, al crear un Bitmap como fuente de la misma. O podemos hacerlo al renderizar la sesión mediante el método RenderToBitmapAsync, que en su tercera sobrecarga nos permite indicar un área de recorte.

En mi ejemplo estoy trabajando con WriteableBitmaps, por lo que es más cómodo usar el método RenderToWriteableBitmapAsync y realizar el corte antes de la sesión. Para ello, lo que vamos a hacer es usar el método extensor AsBitmap() para la clase WriteableBitmap, que viene incluido en el namespace Nokia.InteropServices.WindowsRuntime. Este método nos devuelve un Bitmap a partir de un WriteableBitmap. Lo que voy a hacer es crear un nuevo Bitmap y establecer mi WriteableBitmap, usando este método extensor, como su fuente. Esto me permitirá indicar el área del Bitmap original que deseo usar:

Creando un nuevo Bitmap
public async Task<WriteableBitmap> CropImageAsync(WriteableBitmap originalImg, Rect cropArea)
{
    Bitmap bmp = new Bitmap(originalImg.AsBitmap(), cropArea);

}

Con esta simple línea de código, he creado un nuevo Bitmap, al que le he insertado el bitmap original, mediante el método extensor AsBitmap(). Además le paso al constructor un segundo parámetro de tipo Windows.Foundation.Rect, que incluye la porción de la imagen a recortar y usar. Lo bueno de este método es que, si quiero aplicar un efecto o realizar más operaciones sobre la imagen recortada, solo lo voy a hacer sobre la porción recortada, con lo que el consumo de memoria será menor.

Tras crear nuestro bmp recortado, vamos a crear una nueva sesión que lo use como fuente de la imagen y que llame al método RenderToWriteableBitmapAsync:

Sesión para el recorte
using (EditingSession session = new EditingSession(bmp))
{
    WriteableBitmap newWBitmap = new WriteableBitmap((int)session.Dimensions.Width, (int)session.Dimensions.Height);
    await session.RenderToWriteableBitmapAsync(newWBitmap);
    newWBitmap.Invalidate();
    return newWBitmap;
}

Simplemente creamos una nueva instancia de WriteableBitmap, se la indicamos al método RenderToWriteableBitmapAsync, lo invalidamos y lo devolvemos. con esto podremos realizar el recorte de nuestra imagen sin problemas:

image

Como podemos ver, la forma de cortar una foto no nos ha dado ningún problema y lo que es mejor… ilustra perfectamente el uso del SDK de Nokia, tres pasos: Crear un sesión de edición, modificar la imagen, renderizar de nuevo la imagen.

A continuación vamos a ver como aplicar nuestro primer filtro… para realizar una rotación libre de la imagen y una rotación por pasos.

Rotación de imágenes

Para el recorte de imágenes, hemos visto que teníamos dos opciones: Hacerlo antes de crear la sesión o hacerlo al renderizar la sesión. Para la rotación de una imagen tendremos dos opciones también, aunque ambas se ejecutan en el mismo momento. Ambas opciones son filtros que aplicaremos a una sesión ya creada, por supuesto antes de renderizarla.

Aunque más adelante nos centraremos en los tipos de filtro y en el funcionamiento particular de cada uno, vamos a examinar como añadir un filtro a nuestra sesión y como funcionan en general la aplicación de un filtro en la sesión.

Una sesión puede tener uno o más filtros aplicados, de forma acumulada. Esto es, podemos aplicar un filtro de rotación y luego sobre esa imagen rotada, podemos aplicar un filtro de color, etc.. Los filtros se irán acumulando uno sobre otro, en el orden en el que los hallamos indicado.

Para añadir un filtro, usaremos el método AddFilter de la instancia de sesión. Este método recibe un parámetro de tipo IFilter. Para crear un filtro en concreto usaremos la clase FilterFactory, que contiene métodos para crear cada uno de los filtros existentes. En nuestro caso nos interesan dos en concreto: CreateFreeRotationFilter y CreateStepRotationFilter.

El efecto de estos dos filtros es básicamente el mismo: rotar nuestra imagen. Pero lo ejecutan de diferente forma. CreateFreeRotationFilter nos da todo el control. Podemos indicarle los grados de rotación de la imagen, entre 0 y 360 grados, y la forma en la que deseamos que redimensione la imagen tras la rotación, usando el enumerado RotationResizeMode:

  • FitInside, indica que la imagen se redimensionará para que entre dentro de las dimensiones originales. Si rotamos una imagen 30 grados, al quedar ladeada, sus dimensiones crecerán en altura y disminuirán en anchura. Con FitInside, se redimensiona la imagen para que ésta entre en las dimensiones originales.
  • FitOutside, indica que la imagen se redimensionará para que la imagen original entre dentro de la nueva imagen. Justo al contrario que el caso anterior.
  • Ignore, simplemente no se redimensionará la imagen.

Teniendo esto en cuenta, en nuestro ejemplo tendremos un botón que rote una imagen 45 grados. Lo primero que hacemos una vez creada la sesión, es calcular el nuevo tamaño de la imagen:

Calcular nuevo tamaño
private Size CalculateNewImageSize(EditingSession session)
{
    Size imgDimensions = new Size();
    imgDimensions.Width = session.Dimensions.Width;
    imgDimensions.Height = session.Dimensions.Width;
    if ((int)session.Dimensions.Width < session.Dimensions.Height)
    {
        imgDimensions.Width = session.Dimensions.Height;
        imgDimensions.Height = session.Dimensions.Height;
    }
    return imgDimensions;
}

Básicamente, obtenemos las dimensiones de la imagen en la sesión y decidimos entre quedarnos con el Width o con el Height. Al final usamos el mayor de ellos, tanto para el ancho como para la altura.

Una vez obtenido el tamaño final de nuestra imagen, vamos a aplicar el filtro que rotará la imagen y a dibujar el resultado en un nuevo WriteableBitmap:

CreateFreeRotationFilter
public async Task<WriteableBitmap> RotateImage(WriteableBitmap originalImg, double rotationDegrees)
{
    using (EditingSession session = new EditingSession(originalImg.AsBitmap()))
    {
        Size imgDimensions = CalculateNewImageSize(session);
        WriteableBitmap newWBitmap = new WriteableBitmap((int)imgDimensions.Width, (int)imgDimensions.Height);

        session.AddFilter(FilterFactory.CreateFreeRotationFilter(rotationDegrees, RotationResizeMode.FitOutside));
        await session.RenderToWriteableBitmapAsync(newWBitmap);
        newWBitmap.Invalidate();
        return newWBitmap;
    }
}

En este ejemplo podemos ver ya una sesión completa de edición. En primer lugar creamos la instancia de EditingSession dentro de un bloque using. Dentro, lo primero que hacemos es obtener el tamaño de nuestra imagen y crear un nuevo WriteableBitmap con esas dimensiones.

A continuación usamos el método AddFilter de nuestra sesión para añadir un nuevo filtro, usando la clase FilterFactory y el método CreateFreeRotationFilter. Este método recibe como primer parámetro los grados de rotación y como segundo parámetro el enumerado RotationResizeMode.

Tras añadir nuestro filtro, usamos el método RenderToWriteableBitmapAsync, indicando el nuevo WriteableBitmap que hemos creado, que a continuación invalidamos para forzar que se dibuje y lo devolvemos para poder mostrarlo.

¿Porqué usamos un nuevo WriteableBitmap y no, simplemente, sobre escribimos el existente? Al usar nuestro WriteableBitmap como fuente de la sesión, si intentamos escribir en él el resultado de la misma, la imagen se estropeará y se deformará al intentar leer y escribir en una misma instancia.

El uso del segundo filtro de rotación, CreateStepRotationFilter es muy parecido, si cabe mucho más sencillo:

CreateStepRotationFilter
public async Task<WriteableBitmap> RotateImageStep270(WriteableBitmap originalImg)
{
    using (EditingSession session = new EditingSession(originalImg.AsBitmap()))
    {
        Size imgDimensions = CalculateNewImageSize(session);

        session.AddFilter(FilterFactory.CreateStepRotationFilter(Rotation.Rotate270));

        WriteableBitmap newWBitmap = new WriteableBitmap((int)imgDimensions.Width, (int)imgDimensions.Height);
        await session.RenderToWriteableBitmapAsync(newWBitmap);
        newWBitmap.Invalidate();
        return newWBitmap;
    }
}

La única diferencia con el filtro libre, es que en este caso al método CreateStepRotationFilter solo tenemos que indicarle un valor del enumerado Rotation:

  • Rotate0, 0 grados de rotación.
  • Rotate90, 90 grados de rotación.
  • Rotate180, 180 grados de rotación.
  • Rotate270, 270 grados de rotación.

La rotación siempre se hará en el sentido de las agujas del reloj. Una vez que hemos aplicado el filtro, repetimos los pasos anteriores: renderizamos a un nuevo WriteableBitmap, lo invalidamos y lo devolvemos, el resultado a continuación:

image

Y voila! ya podemos recortar y rotar nuestras imágenes con un código muy simple. Ahora, veamos como también este SDK nos ayuda a la hora de guardar en disco las mismas…

Conversiones de tipos gracias a la EditingSession

Esta muy bien poder jugar con nuestras fotos, pero un paso final indispensable es poder guardar el resultado en nuestro dispositivo para poder disfrutar de él más tarde. En Windows Phone guardar una imagen en la librería de imágenes es relativamente sencillo gracias a la clase MediaLibrary en el namespace Microsoft.Xna.Framework. Aunque XNA no esté soportado “per se” para desarrolla juegos, si que se soporta el acceso a sus ensamblados desde una app wp8.

La parte complicada viene al obtener el tipo de datos que requiere MediaLibrary y su método SavePicture: un array de bytes. Hasta ahora hemos trabajado en nuestro ejemplo con WriteableBitmap solamente y no existe una forma sencilla de obtener un array de bytes desde el directamente. Lo que vamos a hacer es usar el método RenderToJpegAsync de EditingSession, para obtener un IBuffer, del que podemos obtener una MemoryStream que podemos leer para obtener los bytes:

Guardando una imagen
public async Task SavePicture(WriteableBitmap originalImg)
{
    using (MediaLibrary library = new MediaLibrary())
    {
        using (EditingSession session = new EditingSession(originalImg.AsBitmap()))
        {
            var buffer = await session.RenderToJpegAsync();
            buffer.AsStream().Position = 0;
            byte[] byteBufferToWrite = new byte[buffer.Length];
            await buffer.AsStream().ReadAsync(byteBufferToWrite, 0, (int)buffer.Length);
            library.SavePicture(DateTime.Now.Ticks.ToString(), byteBufferToWrite);
        }
    }
}

De esta forma, con solo unas pocas líneas de código podemos convertir nuestro WriteableBitmap en un array de bytes, que ya podemos guardar en nuestra librería de imágenes sin ningún problema.

Bonus track: selección de recorte en pantalla

Como bonus, si os descargáis el código del ejemplo, veréis que podéis dibujar un rectángulo azul sobre la imagen solo con arrastrar y soltar sobre la pantalla. Luego las coordenadas del rectángulo (X,Y) y su tamaño, definirán el área de recorte. Para dibujar el rectángulo, tenemos la imagen metida dentro de un ViewBox, junto con un Canvas que contiene un Border con tamaño 0. Manejamos los eventos ManipulationStarted y ManipulationDelta del Canvas para dibujar nuestra área de recorte:

Dibujando el área de recorte
private void InteractionCanvas_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
    Canvas.SetTop(brdCrop, e.ManipulationOrigin.Y);
    Canvas.SetLeft(brdCrop, e.ManipulationOrigin.X);
}

private void InterationCanvas_manipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
    if (e.CumulativeManipulation.Translation.X >= 0)
        brdCrop.Width = e.CumulativeManipulation.Translation.X;
    if (e.CumulativeManipulation.Translation.Y >= 0)
        brdCrop.Height = e.CumulativeManipulation.Translation.Y;
}

Con este sencillo código, en el evento ManipulationStarted posicionamos (X,Y) el borde. En el evento ManipulationDelta, si la traslación acumulada es mayor de 0, la asignamos a la anchura y la altura del mismo. Se podría mejorar mucho, por ejemplo controlando los valores negativos para desplazar el punto superior izquierdo del borde y hacerlo crecer en otra dirección, pero creo que como ejemplo ilustrativo, vale.

Veréis que este código está directamente en code behind, sin hacer uso de la ViewModel… ¿Es que me he vuelto loco? No, simplemente este código es totalmente perteneciente a la vista. Podríamos usar EventToCommand para llamar a un comando, modificar las propiedades X, Y, Width y Height en nuestra ViewModel y enlazarlas al borde… pero no creo que aportase nada en absoluto y me parece que esa parte de lógica es perteneciente a la vista. (Admito discusiones en este aspecto y si queréis, podemos hacer un ejemplo de como sería este mismo código usando totalmente MVVM, dejadlo en los comentarios)

Y… fundido a negro… corten!

Y con esto llegamos al final del segundo artículo de esta serie sobre Nokia Imaging SDK. En el próximo veremos más a fondo los diferentes tipos de filtros y funcionalidades como el undo infinito sobre los filtros aplicados a una imagen. Hasta entonces, os dejo el proyecto de ejemplo que he usado en este artículo.

DISCLAIMER: Os doy el código para que hagáis con el todo lo que queráis, pero las fotos de este artículo son de mi preciosa mujer ™ y esas no os las presto, ni las fotos ni a ella… Por cierto, a ver quien adivina con que dispositivo se han sacado dichas fotos.

Un saludo y Happy Coding!

[Windows Phone 8] Nokia Imaging SDK 1: Introducción

Hola a todos.

Con este artículo comenzamos una serie dedicada al SDK de imágenes de Nokia:

 

 

El pasado Jueves 11 de Julio, Nokia presentó su último terminal hasta la fecha, el Lumia 1020. Centrado alrededor de la calidad de imagen con su increíble cámara de 41mpx, capaz de realizar zoom digital sin perdida de calidad de hasta 4x y con unas opciones de configuración que lo alejan mucho de lo que entendíamos por una buena cámara hasta ahora, situándolo como el smartphone con mejor cámara disponible.

Pero junto a este dispositivo, Nokia realizó el anuncio de un SDK dedicado a la manipulación de imágenes. Este SDK no es exclusivo para terminales Nokia ni para el Lumia 1020. Podemos usarlo en nuestros desarrollos y distribuir nuestra aplicación sin ninguna limitación a cualquier terminal con Windows Phone 8. Este SDK incorpora:

  • 50 filtros y mejoras listos para aplicar a tus fotos.
  • API para realizar corte, redimensionado, rotación o deshacer ilimitado.
  • También incluye la opción de realizar una descodificación parcial de JPEG con la tecnología RAJPEG para trabajar con imágenes de alta resolución sin tener problemas con el consumo de memoria.

Así que si estás desarrollando una app en la que hagas cualquier tipo de trabajo con imágenes, seguro que te vendrá muy bien el Imaging SDK de Nokia. ¿Como lo puedes obtener y usar? Vamos a verlo…

Obteniendo el SDK en nuestro proyecto Windows Phone 8

Para empezar a trabajar con el Imaging SDK de Nokia, debemos crear un proyecto de aplicación Windows Phone 8 y abrir el gestor de paquetes de NuGet, donde escribiremos “Nokia Imaging SDK” y presionaremos el botón Install del paquete:

image

Nos pedirá que aceptemos la licencia y añadirá tres nuevos ensamblados a nuestro proyecto:

  • Nokia.Graphics.Imaging: Incluye la funcionalidad base del SDK, nativa.
  • Nokia.Graphics.Imaging.Managed: Nos facilita el acceso desde .NET a la funcionalidad nativa del SDK.
  • Nokia.InteropServices.WindowsRuntime: Incluye una clase usada internamente por el SDK, no usaremos ningún tipo en de este ensamblado en nuestro código.

En un proyecto manejado de Windows Phone 8 (VB.NET o C#) Necesitamos las tres referencias, tal cual las añade NuGet. Sin embargo, si intentamos ejecutar la aplicación en el emulador, veremos que no compila. Esto se debe a que las librerías del SDK están compiladas de forma nativa para x86 y para ARM. Si queremos ejecutar la aplicación en el emulador, debemos usar la versión x86 (la que referencia NuGet por defecto) y debemos especificar en la configuración del proyecto x86. Si deseamos ejecutar la aplicación en el dispositivo, tendremos que usar las librerías ARM. ¿Esto significa que tenemos que estar cambiando constantemente la versión referenciada? No, podemos hacerlo de forma más automática, para que dependiendo de la configuración establecida en cada momento, se usen unas o otras.

Preparando nuestro proyecto para ejecutarse

Lo primero que necesitaremos hacer es asegurarnos de que nuestro proyecto solo se compilará en las dos plataformas que soportamos: x86 y ARM. Para ello vamos al menú BUILD, a la opción Configuration Manager y desplegamos el combo de Active Solution Platforms que se encuentra arriba a la derecha. En este combo seleccionamos la opción Edit. Se abrirá una nueva pantalla, donde tendremos una lista con las tres plataformas: Any CPU, x86 y ARM.Tenemos que seleccionar Any CPU y eliminarla de la lista. Presionamos aceptar y seleccionamos x86 por defecto como la plataforma de la solución. Si no vamos a usar en ningún momento el emulador, podemos establecer ARM como plataforma por defecto.

En la barra de botones standard, podemos añadir el combo de plataforma al lado del de configuración, así podremos cambiar fácilmente entre ARM y x86. Ahora tenemos que editar el archivo csproj de nuestro proyecto para que las librerías tengan en cuenta la plataforma activa. Para ello lo primero que necesitamos hacer es descargar el proyecto de Visual Studio. Hacemos click derecho sobre el proyecto en el explorador de soluciones y escogemos la opción “Unload Project”.

NOTA: EL PASO A CONTINUACIÓN NO ES NECESARIO DESDE LA VERSIÓN 0.9.2 DEL SDK, DONDE HAN INCLUIDO UN ARCHIVO .TARGETS QUE REALIZA ESTA ACCIÓN POR NOSOTROS.

A continuación, volvemos a hacer botón derecho sobre el proyecto y seleccionamos “Edit xxxx.csproj”. Con esto veremos el archivo XML que compone nuestro proyecto. Buscamos el ItemGroup que contiene las librerías de Nokia:

Librerías Imaging SDK original
<ItemGroup>
  <Reference IncludeNokia.Graphics.Imaging, Version=255.255.255.255, Culture=neutral, processorArchitecture=MSIL«>
    <HintPath>..packagesNokiaImagingSDK.0.9.1libwp8X86Nokia.Graphics.Imaging.winmd</HintPath>
  </Reference>
  <Reference IncludeNokia.Graphics.Imaging.Managed«>
    <HintPath>..packagesNokiaImagingSDK.0.9.1libwp8Nokia.Graphics.Imaging.Managed.dll</HintPath>
  </Reference>
  <Reference IncludeNokia.InteropServices.WindowsRuntime«>
    <HintPath>..packagesNokiaImagingSDK.0.9.1libwp8X86Nokia.InteropServices.WindowsRuntime.winmd</HintPath>
  </Reference>
</ItemGroup>

Como podemos observar, Nokia.Graphics.Imaging.winmd y Nokia.InteropServices.WindowsRuntime.winmd están en un subdirectorio llamado X86. Si consultamos el directorio del paquete de NuGet, veremos que también existe un directorio ARM. Bien, pues como los directorios se llaman igual que nuestras plataformas posibles, vamos a hacer que usen la plataforma activa para esa parte de la ruta:

Librerías Imaging SDK nuevas
<ItemGroup>
  <Reference IncludeNokia.Graphics.Imaging, Version=255.255.255.255, Culture=neutral, processorArchitecture=MSIL«>
    <HintPath>..packagesNokiaImagingSDK.0.9.1libwp8$(Platform)Nokia.Graphics.Imaging.winmd</HintPath>
  </Reference>
  <Reference IncludeNokia.Graphics.Imaging.Managed«>
    <HintPath>..packagesNokiaImagingSDK.0.9.1libwp8Nokia.Graphics.Imaging.Managed.dll</HintPath>
  </Reference>
  <Reference IncludeNokia.InteropServices.WindowsRuntime«>
    <HintPath>..packagesNokiaImagingSDK.0.9.1libwp8$(Platform)Nokia.InteropServices.WindowsRuntime.winmd</HintPath>
  </Reference>
</ItemGroup>

Ahora solo tenemos que guardar el archivo y hacer click derecho sobre el proyecto, seleccionando la opción “Reload Project”. Una vez que el proyecto esté cargado de nuevo, podremos seleccionar la plataforma x86 y ejecutar el emulador sin ningún error o seleccionar ARM y ejecutar en el dispositivo.

Con este simple paso, solo tendremos que seleccionar la plataforma que necesitemos en cada momento y nuestra aplicación funcionará correctamente sin tener que eliminar/añadir constantemente las referencias.

Y hasta aquí llega esta primera introducción al nuevo Imaging SDK de Nokia. En próximos artículos entraremos a trabajar con cada opción que nos ofrece y veremos como integrar cada una de ellas correctamente usando el patrón MVVM.

Para que vayáis haciendo boca, os dejo este proyecto vacío con los componentes bien configurados, para que lo tengáis como base.

Un saludo y Happy Coding!

[Windows Phone 8] Añadir Google analytics a nuestras aplicaciones

Hola a todos!

Hoy quiero enseñaros como añadir Google Analytics a nuestras aplicaciones Windows Phone 8. Un paso importante de la evolución de una aplicación es conocer como es usada por los usuarios. Esto implica saber cuanto tiempo pasa un usuario en la aplicación cada vez que la abre, que navegación realiza, que páginas usa y cuantas veces al día usa nuestra aplicación.

Además, tener una forma sencilla, a parte de la que nos ofrece la propia página de publicación de Windows Phone, de poder registrar y analizar posibles errores y/o excepciones, puede simplificarnos mucho el trabajo de mantenimiento.

Google Analytics nos permite realizar todo esto y más, como definir eventos personalizados, por ejemplo cuando el usuario usa una característica en concreto de nuestra aplicación, cuando llega a cierta puntuación… En definitiva, podemos disponer de una forma de seguir los indicadores que nos interesen sobre nuestra aplicación de forma sencilla.

NOTA: Aunque en este artículo solo hablo de Windows Phone 8, el SDK de Google Analytics está disponible para Windows Store también y su uso es exactamente el mismo, así que no deberías tener problemas en usarlo también en las apps Windows Store.

¿Por donde empezamos? Bien, el uso del SDK es muy sencillo, pero primero…

Cuenta de Google Analytics

Necesitaremos, claro está, tener una cuenta de Google Analytics. Para ello, lo primero es disponer de una cuenta de google, si tienes una cuenta de gmail o google+, esa te servirá. Con ella podrás hacer login en el sitio web de Analytics. Una vez dentro, tendremos que ir a la sección de administración y seleccionar la opción “Crear una nueva cuenta”. Aquí seleccionaremos el tipo “Aplicación” e indicaremos los datos que nos piden: Nombre de la aplicación, categoría, región y zona horaria y un nombre para la cuenta.

image

El proceso nos avisa que, si ya tenemos una cuenta para realizar el seguimiento de una aplicación, podemos reutilizar el ID de seguimiento que ya tenemos. En nuestro caso presionamos el botón “Obtener ID de seguimiento” (azul) que tenemos en la parte inferior de la pantalla y aceptamos las condiciones de uso. A continuación se mostrará una pantalla con nuestro ID de seguimiento con la forma UA-XXXXXXXX-X donde las X serán números.

Ese ID es todo lo que necesitamos de Google Analytics por ahora, podemos abrir Visual Studio 2013 y empezar a trabajar en nuestra aplicación.

Integrar Google Analytics en Windows Phone 8

Vamos a crear un nuevo proyecto de Windows Phone 8. Lo primero que haremos tras tener nuestro proyecto disponible, es abrir el gestor de paquetes de NuGet y buscar el paquete Google Analytics SDK. podemos instalarlo también desde la consola de NuGet con la orden:

Install-Package GoogleAnalyticsSDK

Una vez instalado el paquete, además de una referencia al ensamblado GoogleAnalytics, se añadirá un archivo xml llamado analytics en la raíz del proyecto. Es en este archivo en el que configuraremos los datos de nuestra cuenta de Analytics. Exactamente necesitaremos el ID de seguimiento, el nombre de la aplicación y la versión de la misma:

Analytics.xml
<analytics xmlnshttp://googleanalyticssdk.codeplex.com/ns/easytracker«>
  <trackingId>UA-XXXXXXXX-Y</trackingId>
  <appName>AnalyticsApp</appName>
  <appVersion>1.0.0.0</appVersion>
</analytics>

En el archivo xml tenemos muchas más opciones comentadas, que tienen un valor por defecto, a no ser que las indiquemos nosotros.

En este proyecto de ejemplo, voy a tener botones que simularán acciones en Google Analytics, como la vista de una página, una excepción, un evento… Realmente el trabajo duro ya está hecho, ahora solo nos queda lo más sencillo.

Vamos, por ejemplo, a registrar que el usuario a entrado a una página llamada “MainPage” y luego ha navegado a una página llamada “VideoDetails”. Simplemente necesitamos incluir este código en el evento OnNavigatedTo de cada una de las páginas:

OnNavigatedTo & Analytics
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    GoogleAnalytics.EasyTracker.GetTracker().SendView(«MainPage»);
}

Con este simple código, indicamos a Google Analytics que se ha visitado una página. Simplemente tendremos que cambiar El nombre de cada página que queramos enviar. ¿Y no lo podemos automatizar un poco más, para no tener que acordarnos de poner esto en cada página que hagamos? Bueno, si los nombres de tus páginas (clases) son lo suficientemente descriptivos, podríamos hacer una página base, algo así:

Analytics base page
public class BasePage : PhoneApplicationPage
{
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        string thisPageName = this.GetType().Name;
        GoogleAnalytics.EasyTracker.GetTracker().SendView(thisPageName);

        base.OnNavigatedTo(e);
    }
}

Si hacemos que todas nuestras páginas hereden de BasePage, en vez de PhoneApplicationPage, cada vez que naveguemos a una página se extraerá el nombre de la clase que la compone y se enviará a google analytics. Esto, nos facilita la vida, solo existe un punto en el que realizar cambios en nuestro código de analytics, pero también nos va a exigir que los nombres de nuestras páginas sean más descriptivos de la reaidad. Creedme, he visto proyectos donde las páginas se llamaban Page1.xaml, Page2.xaml … PageN.xaml. Eso no nos va a servir de nada.

Si ejecutamos nuestra aplicación, este código enviará una visita a Google Analytics por cada página en la que entremos. Para ver esta información, solo tendremos que entrar en la cuenta de nuestra aplicación en www.google.es/analytics:

image

Aquí podemos ver los datos de ejecutar la aplicación con el código anterior, usando el emulador. Es curioso que al usar el emulador, se informe como modelo HTC 8X, cuando ni siquiera hemos usado el emulador 720P, que es la resolución del HTC. Solo con esta primera vista, con un resumen de datos, podemos ver la importancia y la potencia de implementar Google Analytics: Modelos de móviles que ejecutan nuestra app, usuarios totales, usuarios nuevos, usuarios por países… Mucha información en nuestras manos para controlar el desarrollo y crecimiento de nuestra aplicación.

Ahora también podemos querer registrar, por ejemplo, cuando se produce una excepción. De esta forma podemos tener información precisa de que ha ocurrido, cuando y a quién. Esto puede ser muy útil a la hora de ofrecer una solución al origen de la excepción. Para trazar una excepción indicaremos dos parámetros: Un mensaje que sea suficientemente descriptivo y un valor que indique si ha sido fatal o continua la ejecución de nuestra aplicación:

Traceo de excepciones
private void SendExceptionExecute()
{
    var exception = new ArgumentOutOfRangeException(«ListVideos»);
    string exceptionMessage = string.Format(«{0}||{1}», exception.Message, exception.StackTrace);
    GoogleAnalytics.EasyTracker.GetTracker().SendException(exceptionMessage, false);
}

Podremos consultar estas excepciones en la página de Google analytics, en la sección de interacciones – Bloqueos y Excepciones:

image

Además de vistas (páginas) y excepciones, podemos controlar transacciones, por ejemplo cuando alguien compra algo mediante IAP, eventos, cosas compartidas a redes sociales, inicio y final de sesión. Incluso crear nuestras propias métricas. En definitiva, podemos controlar a fondo el uso de nuestra aplicación por parte de los usuarios y obtener una información muy valiosa para el éxito de la misma. Si los grandes lo usan, ¿Porqué no lo vas a usar tú?

A continuación os dejo el proyecto de ejemplo que he usado en este artículo. Por supuesto, por motivos de uso, he quitado la cuenta de google analytics usada, así que tendréis que poner la vuestra en su lugar, en el archivo analytics.xml.

Un saludo y Happy Coding!

 

Visual Studio 2013 & Windows 8.1 Tip: Crear un proyecto Windows Store para Windows 8.0

Hola a todos!

WorksOnMyMachine_3

 

Como buen early adopter, desde el mismo día 26 de junio tengo instalada la preview de Visual Studio 2013 y Windows 8.1 en mi Surface Pro. Haciendo pruebas, he visto que, aunque Visual Studio 2013 permite trabajar con proyectos Windows Store de Windows 8, no permite crearlos. Si creamos un nuevo proyecto Windows Store siempre se creará para Windows 8.1 y no tendremos forma “oficial” de cambiar la versión a Windows 8.0. Pero como no me puedo estar quieto y quiero usar Visual Studio 2013 para crear los ejemplos de este blog, he estado buceando en las profundidades de los archivos csproj y appxmanifest para ver que cambios serían necesarios para cambiar un proyecto de Windows 8.1 a Windows 8.0. Aquí tenéis los resultados.

Cambios en el archivo csproj

Para empezar, vamos a cambiar la plataforma a la que apunta nuestro proyecto. Para ello, hacemos click derecho sobre el proyecto en el Solution Explorer y seleccionamos la opción “Unload Project” a continuación  volvemos a hacer click derecho y seleccionamos la opción “Edit XXX.csproj” donde XXX será el nombre de nuestro proyecto. Esto abrirá el archivo csproj en modo texto para dejarnos editar el XML que contiene. En el primer PropertyGroup, debemos buscar dos nodos: TargetPlatformVersion y MinimumVisualStudioVersion. Los valores originales de estas propiedades serán respectivamente: 8.1 y 12.0. Solo tendremos que cambiarlos por 8.0 y 11.0.

Además tendremos que modificar El nodo Project que se encuentra al principio del archivo. En este nodo debemos cambiar el valor del atributo ToolsVersion de 12.0 a 11.0. Por último necesitamos ir al final del archivo y buscar un PropertyGroup que contenga el elemento VisualStudioVersion, establecido a 12.0 y cambiarlo por 11.0, debería quedar de la siguiente forma:

VisualStudioVersion
  1. <PropertyGroup Condition ‘$(VisualStudioVersion)’ == » or ‘$(VisualStudioVersion)’ &lt; ‘11.0’ «>
  2.   <VisualStudioVersion>11.0</VisualStudioVersion>
  3. </PropertyGroup>

Guardar y recargar el proyecto haciendo click derecho sobre él en el Solution explorer y seleccionando la opción “Reload Project”.

Esto debería permitirnos ejecutar la aplicación en Windows 8.0 y cargar el proyecto en Visual Studio 2012. Pero si intentamos compilar el proyecto obtendremos varios errores en el archivo appxmanifest, indicándonos que no reconoce ciertos nodos y atributos…

Cambios en el archivo appxmanifest

Como decía anteriormente, al intentar compilar el proyecto obtendremos un error: “App manifest validation failed. File contains unrecognized XML elements”, indicando exactamente el nodo: /Package/Applications/Application/m2:VisualElement. Si hacemos doble click sobre el error, se abrirá el archivo Package.appxmanifest directamente en modo XML:

Visual Elements en Windows 8.1
  1. <m2:VisualElements
  2.     DisplayNameWin81ToWin80«
  3.     Square150x150LogoAssetsLogo.png«
  4.     Square30x30LogoAssetsSmallLogo.png«
  5.     DescriptionWin81ToWin80«
  6.     ForegroundTextlight«
  7.     BackgroundColor#464646«>
  8.     <m2:SplashScreen ImageAssetsSplashScreen.png» />
  9. </m2:VisualElements>

El primer cambio que debemos hacer, es deshacernos del texto m2: tanto en la apertura y cierre del nodo VisualElements como SplashScreen. A continuación tendremos que cambiar el atributo Square150x150Logo por Logo y Square30x30Logo por SmallLogo. Nuestro Nodo VisualElements debería quedar de la siguiente forma:

Visual Elements en Windows 8.0
  1. <VisualElements
  2.     DisplayNameWin81ToWin80«
  3.     LogoAssetsLogo.png«
  4.     SmallLogoAssetsSmallLogo.png«
  5.     DescriptionWin81ToWin80«
  6.     ForegroundTextlight«
  7.     BackgroundColor#464646«>
  8.     <SplashScreen ImageAssetsSplashScreen.png» />
  9. </VisualElements>

Ahora tenemos que subir un poco más arriba en el archivo Package.appxmanifest hasta encontrar el nodo Prerequisites:

Prerequisites en Windows 8.1
  1. <Prerequisites>
  2.   <OSMinVersion>6.3.0</OSMinVersion>
  3.   <OSMaxVersionTested>6.3.0</OSMaxVersionTested>
  4. </Prerequisites>

Tendremos que modificar el elemento OSMinVersion para que permita la ejecución en Windows 8 (Versión 6.2). Podemos dejar el nodo OSMaxVersionTested a 6.3, indicando que la app se puede ejecutar en Windows 8.1:

Prerequisites en Windows 8.0
  1. <Prerequisites>
  2.   <OSMinVersion>6.2.0</OSMinVersion>
  3.   <OSMaxVersionTested>6.3.0</OSMaxVersionTested>
  4. </Prerequisites>

Si ahora realizamos un rebuild de nuestro proyecto, funcionará correctamente. Incluso podemos abrirlo en Visual Studio 2012 en Windows 8.0 y ejecutarlo como si fuese una aplicación normal y corriente Windows Store para Windows 8.0.

A continuación tenéis un proyecto convertido de esta forma, que se puede abrir en Visual Studio 2012 sobre Windows 8.0 y funciona a la perfección:

Y recordad “Works on my machine”. Un saludo y Happy Coding!

//Build 2013 3 de 3: La conferencia, segundo día

Y llegamos al segundo día de la conferencia. ¿Te perdiste el día de turismo y el primer día de conferencia? Revísalos aquí:

Segundo día

El segundo día del Build empezó con otra Keynote. Por el escenario pasaron grandes como  Steve Guggenheimer, Scott Guthrie, Scott Hanselman o Josh Twist. Empezaron por enseñarnos como han probado azure, con grandes cifras de productos Microsoft que usan azure como su base:

  • 48 millones de suscriptores de XBox Live
  • 50 millones de usuarios Office 365
  • 250 millones de cuentas de Skydrive

Esta Keynote fue mucho más práctica con Scott Hanselman y Josh Twist haciendo demos en el escenario a golpe de Visual Studio 2013. Mientras Hanselman se centró en asp.net y las novedades que vienen con vs2013, Josh Twist nos dio una visita guiada por las novedades de Mobile Services, desde un Mac, y con el emulador de iOS como escenario.

Al finalizar su demo, Josh nos anunció la disponibilidad general de WAMS y los planes de precios. Entre ellos se incluye un plan gratuito sin SLA, que nos permite tener hasta un máximo de 100 dispositivos conectados. Desde luego, parece bastante poco. Microsoft explica que el plan gratuito no está pensado para aplicaciones publicadas, más bien para desarrollar e investigar. Personalmente, creo que esto deja a mucha gente que había apostado por Mobile Services en la estacada, muchas apps gratuitas tendrán que quitar el soporte a Mobile Services, y no sé si esto beneficia a la plataforma.

Tras Mobile Services, se presentó otra nueva característica de Azure: Auto Scale. De forma sencilla nos permitirá definir parámetros de crecimiento para Websites, Cloud services y Virtual Machines.

Tras una hora y media de Azure, servicios, integración…  Steve “Gugg” Guggenheimer, Jefe de evangelistas de Microsoft, subió al escenario para hablarnos de Dispositivos, servicios e integración.

Lo más destacable (para mí) de esta parte fue la presentación del ecosistema de aplicaciones de ACCIONA, que desde Plain Concepts hemos tenido el placer de ayudar a crear. Apps WPF, Windows Store, Servicios… Una gran muestra de como integrar el ecosistema Microsoft en una aplicación REAL! Enhorabuena ACCIONA!!

La verdad es que poder estar en el Build y ver una aplicación en la que has participado y puesto mucho esfuerzo siendo presentada, es una auténtica pasada. Para que luego digan que en España no se pueden hacer grandes cosas.

Se presentaron más apps, de Coca Cola, SAP… y con esto termino la Keynote y nos dispusimos a asistir al resto de sesiones del día… aunque todavía, al menos a Rafa y a Mí, nos quedaba una sorpresa que nos hizo correr de un lado a otro…

Aquí tenéis el enlace para ver la Keynote completa.

Usando Bing para construir apps Windows Store

Esta era una de las sesiones que más ganas tenía de ver, después de la presentación de Bing services en la Keynote del primer día, salí corriendo a ver esta charla. Lamentablemente solo pude ver la mitad, luego os contaré por qué (en parte al menos)…

En esta charla nos enseñarían los nuevos mapas en 2D y 3D, el API Text to Speech, Speech recognition, OCR y el servicio de traducción. La verdad es que el control de mapas nuevo que tenemos a nuestra disposición en Windows 8.1 es una auténtica pasada, tanto en 2D como en 3D. Podéis ver esta sesión aquí. Muy recomendable.

Sesión privada de Nokia & Microsoft

Solo pudimos llegar a ver el uso de los mapas, porque cuando eran las 12:27 recibí un email de Nokia US y Microsoft San Francisco invitándonos a dejarlo todo y salir corriendo para una sesión “privada” en las oficinas de Microsoft SF… a las 13:00!! Bueno, pues allí salimos Rafa y yo corriendo para llegar a las oficinas a tiempo para ver una gran charla sobre… #@@#~@#||@###@#~~ … Pronto os podré contar sobre qué, por ahora solo puedo deciros una cosa: La carrera valió la pena, muchísimo!! y me lleve un pendrive de Nokia como regalo para casa (y eso, para un freak del merchandising como yo… es increible!!)

Cuando acabo la sesión, aprovechamos que estábamos por el centro para comer algo sano… unas buenas hamburguesas!!

Fundamentos de rendimiento en XAML

Después de saltarnos una charla gracias a la sesión de Microsoft y la comida, volvimos a la carga con una nueva sesión de XAML: Fundamentos de rendimiento. La sesión fue presentada por Kiran Kumar, Principal Development Lead en el equipo XAML Windows.

Para empezar, Kiran nos explico su definición de “Responsive”: Rápido, Fluido y Eficiente. Me gustó mucho el análisis de la responsabilidad de los diferentes hilos dentro de una aplicación XAML:

image

Después de esto, nos enseño una demo de optimización del inicio de las aplicaciones. Causas más comunes para que nuestras aplicaciones inicien muy lentas: llamadas a IO de archivos, web requests o demasiada carga de recursos (xamls, dlls…) Me gustó mucho el uso del Windows Performance Analyzer:

image

El resto de la sesión tuvo esta misma línea: respuestas para mejorar el rendimiento ante casos concretos: GridView, animaciones, overlays… Muy buena sin duda. No te la pierdas si desarrollas en cualquiera de las plataformas que usan XAML. Puedes ver la sesión completa aquí.

Attendee party!!

Y después de un día repleto de grandes sesiones, llegó la hora de irnos todos de fiesta!! Y te preguntarás, ¿Donde puedes meter a todos los asistentes al //Build, todos juntos? Pues Microsoft se debió preguntar lo mismo, y nos metió en una nava industrial gigante en el puerto de San Francisco. Una de las mejores fiestas de Microsoft a la que he ido. Realmente bestial!!

Y… Fin!

Con esto llegamos al final del segundo día del Build. Sin duda alguna, una gran conferencia. La experiencia de estar en San Francisco, rodeado de mucha gente que marca tendencia en el ecosistema de Microsoft y viendo las novedades que vienen, es única.

//Build 2013 2 de 3: La conferencia, primer día

Hola a todos!

El lunes os contaba como fue la parte lúdica del viaje que hice al Build. Hoy llega el momento de examinar la conferencia propiamente dicha, que novedades nos trajo Microsoft y como se viven en directo.

Primer día

El miercoles 26 de junio dio comienzo la conferencia. Arranco con una Keynote de Steve Ballmer, acompañado por Julie Larson Green y Antoine LeBlond. Las novedades se centraron alrededor de Windows 8.1 y Visual Studio 2013. WebGL en Internet Explorer 11 y por ende en aplicaciones Windows Store desarrolladas en HTML5/JS, La nueva plataforma de Bing para desarrolladores y las nuevas herramientas de rendimiento para vs2013. Podéis ver la Keynote íntegra aquí.

WP_20130626_007

También anunciaron el primer regalo para los asistentes, una tablet Acer Iconia W3 de 8”. El día empezaba muy bien. Tras una parada para tomar un cafe después de la Keynote, empezamos con las sesiones propiamente dichas. Aunque a lo largo de los tres días de conferencia había 18 sesiones sobre Windows Phone, solo fui a una el último día ya que no se anunciaban novedades con respecto a la plataforma móvil.

Con 14 sesiones paralelas cada hora donde elegir, estaba claro que te perderías algo si o si.

Novedades de WinRT en Windows 8.1

En mi caso comencé con una charla sobre las novedades de WinRT en Windows 8.1, impartida por  Jhon Lam y Neena Kamath que destacaron las 9  novedades más interesantes incluidas en Windows 8.1:

WP_20130626_023

  • HubControl, un control que nos permite diseñar nuestra pantalla con varias secciones, de forma parecida a como podríamos hacer con un GridView pero con más opciones de diseño y sin tener que enlazarlo a una lista.
  • Multiples vistas, nos permite definir como se va a mostrar nuestra página dependiendo de en donde se está mostrando.
  • WebView, este control no es nuevo, pero en Windows 8 tenía un gran problema: Se renderizaba sobre cualquier otro control, ya pusiésemos un popup o lo ocultásemos tras la AppBar, el WebView siempre se dibuja sobre el resto de elementos, lo cual era realmente molesto. Han corregido esto y ahora, además de ofrecernos nuevos eventos de navegación, se dibuja correctamente en el árbol de elementos.
  • Soporte mejorado para dispositivos, como escaners o lectores de tarjetas, tendremos APIs que nos ayudarán a integrar más dispositivos en nuestras aplicaciones.
  • HTTP, soporte mejorado para comunicaciones HTTP con HttpClient.
  • Bluetooth, nuevos SDKs independientes que hacen uso del Bluetooth y nuevas facilidades para acceder a él.
  • Tarjetas de visita y acciones, nos permite mostrar para un contacto, diferentes opciones automáticas a modo de popup como enviar un email o llamar por teléfono.
  • Nueva integración con WAMS (Windows Azure Mobile Services) Directamente desde Visual Studio 2013 podremos realizar la gran parte del trabajo necesario en nuestro backend WAMS.
  • PlayTo XBox, nuevas opciones para reproducir contenido directamente desde nuestras apps (sonido, video, imágenes) a una XBox.

La verdad es que la charla se hizo muy amena, fueron desarrollando todos estos puntos mientras planteaban un escenario donde una startup dedicada a la venta de limonada creaba un punto de venta. Podéis ver el video completo de la sesión aquí.

Novedades en XAML para desarrolladores

Para continuar, asistí a la charla sobre las novedades en XAML para desarrolladores. Impartida por el genial Tim Heuer, program manager en UI Platforms.

WP_20130626_032

Esta charla se dividió en varias secciones. Por un lado ver todos los nuevos controles que tendremos disponibles en Windows 8.1 para nuestras apps XAML:

  • DatePicker
  • TimePicker
  • Distintos tipos de flyouts: ButtonFlyouts, MenuFlyouts o SettingsFlyouts.
  • Inclusión de un nuevo tipo de recurso, llamado ThemeResource.Este tipo de recurso se parece al DynamicResource del que disponíamos en WPF, pero algo más limitado. básicamente se reevalúa al cambiar el tema de la aplicación entre claro y oscuro, permitiendo que nuestros elementos se adapten de forma acorde.
  • Hub control
  • App CommandBar
  • SearchBox
  • MediaPlayer
  • SwapChainPanel, para interactuar entre XAML y DirectX.
  • WebView, con posibilidades mejoradas para renderizar contenido local sin tener que abrirlo del storage, simplemente indicando su ruta local.
  • RenderTargetBitmap, una de las mejoras más esperadas. Solo necesitas indicarle un elemento xaml y automáticamente renderizará ese elemento y todos sus hijos como si de una imagen se tratase. Una forma bestial de obtener capturas de pantalla.

A continuación pasamos a hablar del rendimiento, donde vimos una de las mejores ideas que ha tenido Microsoft en los últimos tiempos. Ya no se distribuirá el XAML con nuestra aplicación Windows Store como se venía haciendo en Windows 8. Todo XAML se compilará a un formato Binario XBF, lo que nos aportará una mejora en el rendimiento de la aplicación.

En cuanto a rendimiento se ha mejorado y por mucho la virtualización de los ListViews y GridViews, sobretodo en la carga inicial, que se ha mejorado en varios segundos (depende por supuesto del caso) con respecto a Windows 8.

También se han realizado grandes mejoras en cuanto a los textos: APIs de alineamiento de texto, PlaceHolderText en los TextBox, Cabecera en los TextBox y otros elementos, CharacterEllipsis (si, por fin!!) o evento de pegar en el textbox… entre otros muchos.

Y para cerrar la charla, que estaba siendo ligerita, imaginaros cuadrar todo esto que os estoy resumiendo, en una hora… llega el momento de ponernos serios y nos explican las novedades en cuanto a Bindings:

  • Acceso a la expresión de un binding mediante BindingExpression
  • TargetNullValue
  • FallBackValue
  • UpdateSourceTrigger
  • Behaviors oficiales

Los que hayáis trabajado con XAML, entenderéis porque más de uno (yo incluido) soltó gritos orgásmicos al ver las novedades de enlace a datos. Cosas como el FallbackValue o BindingExpression eran un “must have” que nos complicaban mucho la vida.

Y muchas cosas más, nos recordó Tim Heuer, que se incluyen en Windows 8.1: Renderizado de PDFs, mejora del FlipView, detección de múltiples DPIs, accesibilidad y así hasta 650 nuevas APIs. Si queréis ver la sesión de Tim Heuer, podéis hacerlo aquí.

Novedades de Visual Studio y Blend para desarrolladores XAML

Voy a ser totalmente sincero, esta charla pintaba muy bien, pero Rafa Serna y yo solo vimos la primera media hora. Acababa a las 18:00 y en ese momento empezaban a repartir las Surface Pro y Acer Iconia, así que pensamos salir a las 17:30 para estar los primeros de la cola… lo malo es que todo el mundo pensó lo mismo y cuando llegamos a la pequeña cola, ya llenaba la mitad del comedor (con capacidad para 15000 personas) del Moscone Center y teníamos delante de nosotros a cerca de 1000 personas. Bueno, a las 18:00 la cola ya salía fuera del comedor, así que no fue tan mala idea jeje.

La charla, impartida por Unni Ravindranathan, se dividió entre las mejoras en Visual Studio 2013 para editar XAML y las mejoras de Blend para XAML.

  • Capacidad de realizar Edit and continue en 64bits
  • Coded UI Testing para Windows Store
  • Nuevas plantillas de proyecto
  • Diagnosticos para la UI y para el consumo de energía
  • Depuración de métodos async
  • Integración en Visual Studio 2013 de Windows Azure Mobile Services
  • INTELLISENSE PARA LOS BINDINGS, esto es simplemente grandioso, por fin, el sistema es capaz de detectar el contexto de datos y darnos intellisense para las propiedades de ese contexto.
  • Soporte a F12 (Ir a definición) EN XAML: Para recursos, tipos o bindings.
  • En Blend tendremos reglas y guías, que nos permitirán ajustar nuestros diseños al pixel de forma sencilla y sin problemas mayores.
  • Por fin vuelven a incluir los Behaviors, con lo que podremos implementar comportamientos personalizados en nuestros controles sin usar code behind y pudiendo reaprovechar el código.
  • Soporte para datos de ejemplo en Blend, que había sido retirado en las apps Windows Store.

Como puedes ver, grandes novedades que hacen que desarrollar apps Windows Store en XAML sea todavía más sencillo. Creo que oigo desde aquí los llantos de los pobres que usan HTML5 y JS mientras intentan alinear correctamente un control… pobrecillos. Puedes ver la sesión aquí.

Fiesta!

Tras la pequeña cola para recoger nuestras surfaces y unas charlas más que interesantes, llego el momento de descansar. Rafa había ido a sesiones orientadas más hacia la web y yo, como podéis ver, me centré en Windows Store XAML, así que ya con nuestros regalos bajo el brazo, intercambiamos opiniones e información sobre las charlas respectivas y nos dirigimos a la calle Jhones a la VIP Party del Build, muy cerca de Scott Hanselman, Marco Argenti, Ignacio Riesgo y muchos otros cargos de Microsoft y Nokia. Allí nos encontramos con todos nuestros amigos: Luis Fraile, José Bonnin, Boris Armentia, Elisa García, Vicente Cartas, Antón Molleda, Iván González Javier Arrativel, Sergio Jiménez, y algunos más que seguro me dejo en el tintero. Comimos algo, bebimos (unas coca colas en mi caso) y después de un rato, con nuestro hotel muy cerca, Rafa y yo salimos disparados a actualizar nuestras surfaces a win8.1, instalar vs2013 y empezar a jugar con ellas. Pero eso ya son secretos de habitación….

WP_20130626_040

Y… Fundido a negro

Así que, el primer día del Build llegó a su fin. Lleno de charlas interesantísimas y muy tentadoras, que hacían que te tirases de los pelos por tener que elegir solo una. Con regalos, fiestas y muy buen rollo sobre todo.

El siguiente día, el jueves 27, también estuvo cargadito de sorpresas y buenas charlas, incluso alguna charla sorpresa que nos hizo salir corriendo para llegar a tiempo… pero eso es otra historia que os contaré en el siguiente artículo!

Un saludo y Happy Coding!

[OT] //Build 2013 1 de 3: Turismo Geek

Hola a todos!

mosconeCenter

La semana pasada, del 26 al 28 de Junio, se celebró en San Francisco el //Build 2013, la conferencia de desarrolladores de Microsoft por excelencia. En esta ocasión y gracias al equipo de producto de Windows Phone y a Plain Concepts, tuve la oportunidad de asistir, así que me lié la manta a la cabeza y junto a Iván Gonzalez y Rafa Serna, me fui a California.

No solo de tecnología vive el hombre, así que aprovechamos el día anterior a empezar la conferencia para hacer algo de turismo Geek. Pero primero lo primero, mi abuela siempre decía que hay que desayunar en condiciones para empezar bien el día:

desayuno

Aprovechando que Sergio y Javier de Acciona estaban por allí, nos alquilamos un pequeño coche y nos fuimos a visitar la región:

mustang

Cuando un geek viaja a San Francisco, además de visitar la propia ciudad, hay ciertos lugares de culto que no puede dejar de ver: Pudimos visitar Facebook, Apple, Google, Nokia, Stanford y por supuesto el lugar que ha creado la mayor explosión de riqueza de la historia: El garaje donde Steve Wozniak y Steve Jobs crearon Apple:

En Apple y Facebook casi no puedes ver nada. Facebook solo permite sacar fotos en el logo de la entrada, que además tenían tapado con el icono de video en instagram… Apple te permite moverte por Infinite Loop y entrar en la company store a gastar dinerito en camisetas y otro merchandising, pero poco más. Google por su parte tiene mucho campus que recorrer y puedes ver los muñecos de Android, el dinosaurio en el jardín y a los googlers jugando al Volley.

Nokia por su parte se portó muy bien, Antoine, lider de comunidades, nos recibió en el cuartel general y nos enseño la primera planta, llena de salas de reuniones, cafetería y su servicio técnico interno. No pudimos subir al resto de pisos porque tenían varios terminales secretos rondando por allí. Cabe destacar que en cada rincón y en cada mesa, encontrabas mensajes apelando a la confidencialidad. Todos en tono distendido, pero recordándote que lo bueno de un lanzamiento es poder sorprender a la gente. Antoine nos regaló algunos goodies de Nokia Developer Champion y nos invitó a comer, unas hamburguesas increíblemente buenas.

El garaje donde se creo Apple es una casa privada así que fuimos con mucho cuidado de no invadir la intimidad de nadie. Como podéis ver en las fotos, un cartel pide por favor que las fotografías se realicen desde fuera de la propiedad, así que con todo el respeto que una vivienda particular requiere, nos sacamos unas cuantas fotos y continuamos la ruta. Salimos de allí pensando como un garaje normal, en un barrio normal, de una ciudad normal, había podido generar lo que hoy conocemos como Apple. La respuesta es clara: no importa el lugar, lo que importa es la gente, las ganas y el empeño. Realmente inspirador.

Después de acabar de visitar todos los lugares geeks de culto, pusimos rumbo de nuevo a San Francisco para visitar uno de los mayores iconos de la ciudad, el Golden gate:

Tras sacar algunas fotos y maravillarnos con la vista del famoso puente ya solo nos quedaba un destino: El registro del Build. La verdades que he sufrido grandes conferencias como el Mobile World Congress, donde miles y miles de personas se tienen que registrar y obtener su badge. El Build ha sido todo un ejemplo de organización y buen hacer en ese sentido. Llegamos al Moscone Center North a las 18:00 y a las 18:05 estábamos registrados y listos para marcharnos. Aunque las colas fueron una constante durante el evento, también fue constante la buena organización que las hizo rápidas y soportables.

Y con nuestro registro hecho, ya solo quedaba una cosa: ir de fiesta. Rafa y yo estábamos invitados a una fiesta privada de Nokia y Microsoft con otros Nokia Champions y MVPs, donde pudimos hablar con la gente, hacer mucho networking y cenar bien. Lamentablemente no hay fotos de esa fiesta, porque después de un día de caña a la cámara de los 920, estaban literalmente secos. Cuando salimos de la fiesta de Nokia y Microsoft, nos esperaba otra más: la fiesta de Xamarin, justo a una manzana de donde estábamos así que allá fuimos, aunque esta vez solo nos quedamos un rato, recogimos un peluche y una camiseta y nos fuimos al hotel a descansar… El día siguiente iba a ser intenso con el comienzo del Build, la keynote, sesiones, regalos y más fiestas…

La mejor de todas las fiestas, en mi opinión, la fiesta de cierre del Build que organizó Microsoft en los muelles de San Francisco, con una nave industrial diáfana como telón de fondo, música, comida, juegos…. impresionante:

WP_20130627_20_28_53_Panorama

En el próximo artículo hablaré de todas las cosas técnicas, sesiones, keynotes, novedades, etc… pero no quería despedirme sin añadir algunas fotos de lo que pudimos comer en San Francisco. Si, lo se, mi esperanza de vida en USA sería de menos de dos semanas… pero que le voy a hacer:

Y por supuesto… los regalos!! (Pensabais que no iba a poneros los dientes largos?)

WP_20130626_038

No os perdáis la segunda parte, por que lo bueno, todavía está por llegar!!

Un saludo y Happy Coding!

P.D.: Este es el primer artículo que escribo íntegramente desde la Surface Pro, he decidido intentar usarla como mi PC principal para el blog y desarrollo personal. Ya os iré contando. Por ahora, decir que el Type Cover es una caña y muy cómodo para escribir en cuanto te acostumbras un poco