[Windows Phone 8.1] MVVM en apps universales.

Hola a todos!

Una de las grandes novedades, como ya vimos anteriormente, en la nueva versión de Windows Phone 8.1 son las aplicaciones universales. Este nuevo tipo de proyecto nos promete ser capaces de compartir la gran mayoría de código entre una versión Windows Store y otra Windows Phone de la misma aplicación. ¿Pero realmente es así? Antes de empezar a repasar nuevas APIs, XAML y otras cosas, creo que es importante ver como podemos usar MVVM en nuestras aplicaciones universales para compartir gran parte del código.

Implementando MVVM en proyectos universales

Realmente la implementación de MVVM no cambia en absoluto, con respecto a la que podríamos hacer en Windows Phone 8.0 o Windows Store. Lo único que cambia es el proyecto donde colocamos nuestros archivos.

Mientras que anteriormente implementábamos MVVM en el propio proyecto de la aplicación o una PCL, en las apps universales usaremos el proyecto Shared para almacenar nuestros archivos. El objetivo es llegar a tener solo el XAML de las páginas en cada proyecto de plataforma y que toda la lógica de la aplicación esté centralizada en el proyecto Shared. ¿Es esto posible? Si en la mayoría de los casos. Siempre nos encontraremos con casos en que las APIs de Phone y Store no son exactamente iguales, incluso donde su valor de retorno no es el mismo. En estos casos tendremos dos opciones: Crear una ViewModel específica para cada proyecto o usar bloques condicionales de compilación. ¿Cual usar en cada caso? Pues dependerá un poco de nuestras necesidades particulares en cada momento y de lo que necesitemos hacer. Si es poco el código particular de cada plataforma y mucho el código compartido, quizás usar un bloque condicional nos ayude a compartir código y no tener que reescribirlo todo. Sin embargo, si el código particular es la mayoría de la ViewModel, quizás sea mejor crear una por cada plataforma.

Vamos a comenzar por las bases. En todo proyecto XAML con MVVM, me gusta crear dos clases base: PageBase y ViewModelBase.

PageBase

PageBase la usaré como clase base de todas mis páginas. Esto me permite varias cosas:

  • Definir comportamientos comunes a todas las páginas, como detección de internet.
  • Definición de transiciones comunes.
  • En conjunto con la ViewModelBase, “rutear” los metodos de navegación hacia las ViewModels.
  • Establecer en la ViewModelBase el Frame activo de cada página, de forma que sea más facilmente accesible.

Con esta funcionalidad, la clase PageBase tendría este aspecto:

PageBase
public class PageBase : Page
{
    private ViewModelBase vm;

    public PageBase()
    {
    }

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

        vm = (ViewModelBase)this.DataContext;
        vm.SetAppFrame(this.Frame);
        vm.OnNavigatedTo(e);
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);
        vm.OnNavigatedFrom(e);
    }

    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
        base.OnNavigatingFrom(e);
        vm.OnNavigatingFrom(e);
    }
}

Aquí podemos observar una de las ventajas de Windows Phone 8.1 y las aplicaciones universales. Ya no tenemos un objeto PhoneApplicationPage. Ahora todas las páginas, tanto de Windows Phone como Windows Store, heredan del objeto Page. Esto permite que de igual forma, nuestra página base pueda ser compartida entre las dos plataformas.

Podéis ver que el código no es nada de otro mundo, controlamos los métodos de navegación y en el método OnNavigateTo obtenemos la ViewModel asignada a la página y establecemos el Frame activo en la misma. Por último en todos los métodos de navegación invocamos un método que se llama igual en la ViewModelBase. De esta forma no necesitamos usar code behind para controlar la navegación de nuestras páginas.

ViewModelBase

Nuestra ViewModelBase actuará como la clase base de las cuales heredarán todas nuestras ViewModels, lo que nos permitirá darles una funcionalidad básica y homogénea a todas:

  • Acceso al objeto Frame de la página asociada.
  • Acceso a los eventos de navegación para sobre escribirlos.
  • Notificación de cambios.
  • Notificación de carga a la UI.

El código de la ViewModelBase, sería parecido a este:

ViewModelBase
public abstract class ViewModelBase : INotifyPropertyChanged
{
    private Frame appFrame;
    private bool isBusy;

    public ViewModelBase()
    {
    }

    public Frame AppFrame
    {
        get { return appFrame; }
    }

    public bool IsBusy
    {
        get { return isBusy; }
        set
        {
            isBusy = value;
            RaisePropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public abstract Task OnNavigatedFrom(NavigationEventArgs args);

    public abstract Task OnNavigatingFrom(NavigatingCancelEventArgs args);

    public abstract Task OnNavigatedTo(NavigationEventArgs args);

    public void RaisePropertyChanged([CallerMemberName]string propertyName = "")
    {
        var Handler = PropertyChanged;
        if (Handler != null)
            Handler(this, new PropertyChangedEventArgs(propertyName));
    }

    internal void SetAppFrame(Frame viewFrame)
    {
        appFrame = viewFrame;
    }
}

Hemos creado tres métodos abstractos: OnNavigatedFrom, OnNavigatingFrom y OnNavigatedTo que implementaremos en nuestras ViewModels para poder ejecutar código durante la navegación. Esto es muy útil cuando queremos recibir un parámetro de otra página, pero también al cargar datos. Si realizamos carga de datos en el constructor, podemos ralentizar la carga de la página. Sin embargo usando el método OnNavigatedTo, realizamos la carga una vez que la página está activa, no antes.

Ahora ya podemos empezar a crear nuestras páginas y ViewModels, usando las clases base que hemos definido.

Páginas

En cada página, tendremos que incluir el namespace de nuestra página base y cambiar su tipo, tanto en XAML como en C#:

 

MainPage.xaml
<base:PageBase
    x:Class="Wp81MVVM.MainPage"
    xmlns:base="using:Wp81MVVM.Base"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Wp81MVVM"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    </Grid>
</base:PageBase>

 

 

MainPage.xaml.cs
namespace Wp81MVVM
{
    using Wp81MVVM.Base;

    public sealed partial class MainPage : PageBase
    {
        public MainPage()
        {
            this.InitializeComponent();
        }
    }
}

 

Ahora solo tenemos que definir una ViewModel para esta página, implementando la ViewModelBase y sus métodos abstractos de navegación:

ViewModel
public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {

    }

    public override Task OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
    {
        return null;
    }

    public override Task OnNavigatedFrom(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
    {
        return null;
    }

    public override Task OnNavigatingFrom(Windows.UI.Xaml.Navigation.NavigatingCancelEventArgs args)
    {
        return null;
    }
}

Ya solo nos queda unir nuestra página y nuestra ViewModel, de la forma que más nos guste: usando IoC, asignándola directamente en el constructor de la página… En este caso voy a usar Unity para resolver nuestra ViewModel y servicios. Para ello, lo primero que necesitaremos es añadir una referencia en nuestro proyecto universal a Unity. En este tipo de proyectos esto significa añadir la referencia a cada proyecto de plataforma (Phone y Store). Vamos a comenzar por el proyecto Store. Solo tenemos que hacer click derecho sobre el nodo “References” del proyecto y seleccionar la opción “Manage NuGet packages”, buscar “Unity” y presionar el botón instalar:

image

Ahora deberíamos repetir lo mismo con el proyecto Phone, pero el resultado será el siguiente:

image

El problema aquí es que, en la mayoría de los casos, todavía no se han actualizado los paquetes de NuGet para soportar los tipos de proyecto “WindowsPhoneApp, version=8.1”. ¿Quiere decir esto que no podemos usar Unity? Ni mucho menos. Lo unico que quiere decir es que no podemos instalarlo desde NuGet. Como Windows Phone 8.1 y Windows Store comparten ahora todo el core de desarrollo, “en teoría” podríamos usar el mismo ensamblado que en Windows Store. Solo tenemos que hacer click con el botón derecho sobre “References” en el proyecto Windows Phone y seleccionar “Add Reference”, presionar el botón “Browse” e ir a la carpeta de packages donde se ha descargado Unity para Windows Store previamente, seleccionando la carpeta NetCore45, que es la usada en Windows Store, seleccionamos la dll dentro de esa carpeta y presionamos “add” y “ok” y listo, ya tendremos Unity funcionando en nuestra aplicación Windows Phone 8.1.

Ahora en nuestro proyecto Shared, en la carpeta Base de ViewModels, vamos a añadir una nueva clase llamada ViewModelLocator, que haga uso de Unity para registrar y resolver nuestras ViewModels, exponiéndolas mediante propiedades públicas:

ViewModelLocator
public class ViewModelLocator
{
    IUnityContainer container;

    public ViewModelLocator()
    {
        container = new UnityContainer();

        container.RegisterType<MainViewModel>();
    }

    public MainViewModel MainViewModel
    {
        get { return container.Resolve<MainViewModel>(); }
    }
}

Como podemos ver, desde nuestro proyecto Shared podemos acceder a cualquier ensamblado referenciado en nuestros proyectos de plataforma, haciendo muy sencillo escribir código compartido. Ya solo nos queda añadir nuestro ViewModelLocator como una referencia en el archivo App.xaml, que también se encuentra compartido en el proyecto Shared:

Shared App.xaml
<Application
    x:Class="Wp81MVVM.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Wp81MVVM"
    xmlns:VMBase="using:Wp81MVVM.Base">

    <Application.Resources>
        <VMBase:ViewModelLocator x:Key="Locator"/>
    </Application.Resources>
</Application>

Y ya lo podemos usar en las páginas de ambas plataformas. De la misma forma que haríamos en un proyecto de Phone o Store tradicional:

 

MainPage.xaml Windows Store
<base:PageBase
    x:Class="Wp81MVVM.MainPage"
    xmlns:base="using:Wp81MVVM.Base"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Wp81MVVM"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    DataContext="{Binding MainViewModel, Source={StaticResource Locator}}">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    </Grid>
</base:PageBase>

 

 

 

Mainpage.xaml Windows Phone
<base:PageBase
    x:Class="Wp81MVVM.MainPage"
    xmlns:base="using:Wp81MVVM.Base"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Wp81MVVM"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    DataContext="{Binding MainViewModel, Source={StaticResource Locator}}">

    <Grid>

    </Grid>
</base:PageBase>

 

En este punto, puede parecer que tener una sola página es mejor y compartirla en el proyecto Shared. Si, podríamos hacerlo sin ninguna dificultad. Pero en la mayoría de los casos, haría que en Phone o Store, la UX fuese horrible. En mi caso soy un firme defensor de hacer una interface de usuario para cada plataforma, aprovechándonos de sus puntos fuertes. Sin embargo, si que es posible que nos encontremos compartiendo pequeños trozos de interface en forma de controles de usuario y en muchos casos usando las diferentes páginas solo para modificar la distribución de la información en pantalla para aprovechar mejor el área de trabajo de cada plataforma. Esto da para un próximo artículo.

Conclusión

Esto es todo por hoy, como hemos podido ver es muy fácil compartir código con los proyectos universales, sin necesidad de hacks ni cosas extrañas (seguro que en algún momento nos hacen falta jeje) y nos permite construir apps para la plataforma Windows en conjunto. Como siempre, podéis descargar todo el código de ejemplo aquí para jugar con él y usarlo como punto de partida para vuestras apps.

Sería un buen arranque para una app que queráis presentar en el Hackathon //Publish del 16 de Mayo en Madrid, Barcelona o Palma de Mayorca. Premios, asistencia para el diseño de tu app, y mentores para ayudarte a crear el próximo hit!

Un saludo y Happy Coding!

 

[Eventos] Después del //Build/ llega //Learn/ y //Publish/

Hola a todos!

Solo hace unos días que termino el //Build/ 2014. Este año los seguidores de Windows Phone tuvimos grandes novedades y anuncios con la presentación de Windows Phone 8.1. Desde Microsoft Corp. y la comunidad de MVPs de Windows Phone, queremos ayudarte a seguir el ritmo de las novedades y crear grandes aplicaciones usando las nuevas ventajas que ofrece la plataforma Windows con esta última revisión.

Para ello, se han creado dos eventos que tendrán lugar en Abril y Mayo: //Learn/ y //Publish/

//Learn/

Este evento online está organizado directamente por los MVPs de Windows Phone. Durante 6 horas, tendremos webcast sobre diferentes temáticas de Windows Phone 8.1: aplicaciones universales, diseño, nuevas APIs, notificaciones… Lo mejor de todo, es que no solo será en Inglés. Dispondremos de una track principal en inglés y tracks paralelas en Chino, Ruso, Portugués, Frances y Español!!

En la Track en Español, Sorey García, Roberto Alvarado, Jose Luis Latorre, Ivan Toledo y un servidor estaremos dando todo el contenido. Las sesiones que tendremos serán las siguientes (Puede variar alguna todavía):

  • Introducción a Windows Phone 8.1
  • Empezando a construir apps Windows XAML
  • Controles de layout y transiciones de páginas
  • Adaptando tu UI a diferentes pantallas
  • Ciclo de vida de apps WinRT XAML
  • Tiles, badges, notificaciones y el Action center
  • Tareas en background
  • Windows XAML para desarrolladores Silverlight

El evento se celebrará el 24 de Abril, se pueden registrar aquí. Al ser un evento internacional los horarios han tenido que ser consensuados y España no sale demasiado bien parada. El evento en España empezará alrededor de la 1 de la mañana del día 25… pero no os preocupéis, el material será grabado y al día siguiente, o tan pronto tenga los enlaces, los pondré aquí.

//Publish/

Cerca de un mes después del evento //Learn/ tendremos un nuevo evento, esta vez presencial. Se trata de un hackathon organizado entre Microsoft y la comunidad MVP. En él ayudaremos a los asistentes a crear apps para Windows 8.1 y Windows Phone 8.1, tendremos mentores, premios, dispositivos para probar vuestras apps y os invitaremos a comer.

En España tenemos la suerte de tener tres sedes: Barcelona, organizada por Microsoft y Madrid y Palma de Mallorca, organizadas por la comunidad MVP. En mi caso estaré en Madrid, junto con Javier Suarez y Santiago Porras para ayudaros a crear apps increíbles y publicarlas. El evento en Madrid se llevará a cabo en las oficinas de Microsoft el día 16 de mayo.

En breve tendremos más información, según vayamos avanzando con la organización y actualizaré este post con todas las novedades. Por ahora podéis registraros en cualquiera de las tres sedes aquí.

Estos eventos son grandes oportunidades para actualizar vuestros conocimientos o introduciros en la plataforma Windows, así que no perdáis esta oportunidad. Nos vemos en breve.

Un saludo y Happy Coding!

[Windows Phone 8.1] Opciones para desarrollar

Hola a todos!

En el artículo anterior, hablamos sobre las novedades de Windows Phone 8.1 en cuanto a las herramientas que tenemos disponibles. Hoy vamos a hablar sobre las nuevas opciones y frameworks que tenemos disponibles para crear nuestras aplicaciones.

Bien, esta es una de las cosas que mas enrolladas están. Windows Phone 8.1 trae consigo nuevas formas de hacer las cosas, pero Microsoft no ha querido dejar a nadie en la cuneta, con lo que es totalmente compatible con el código que ya teníamos para Windows Phone 8.0.

En primer lugar tenemos que tener en cuenta que el motor de ejecución de apps ha cambiado en Windows Phone 8.1. Se ha abandonado el motor basado en Silverlight y se ha creado todo un nuevo motor de ejecución basado en WinRT y Windows Store. Pero sobre este motor, se ha trabajado para poder ejecutar las aplicaciones de Windows phone 8.0 sin necesidad de realizar ningún cambio ni adaptarlas. Automáticamente todas son compatibles. Con esto, podemos desarrollar de las siguientes formas:

  • Silverlight para Windows Phone 8.0: Podemos crear una app de Windows Phone 8.0 y se ejecutará perfectamente en terminales 8.0 y 8.1. Pero no tendremos acceso a las nuevas APIs de Windows Phone 8.1.
  • Silverlight para Windows Phone 8.1: Esta nueva versión nos permite migrar una app Windows Phone 8.0 de forma muy rápida (con una opción de menú) y además acceder a las nuevas APIs de Windows Phone 8.1.
  • Windows XAML: Es la gran novedad de Windows Phone 8.1, básicamente es el mismo sistema usado en las apps Windows Store XAML. 100% WinRT y mismo XAML para la interface de usuario. Es el que más cambia con respecto a la anterior versión del sistema. Con Windows XAML podremos crear proyectos universales, de los que hablaremos más adelante, que nos permitirán desarrollar para Windows Phone y Windows Store de forma muy sencilla.
  • WinJS: Para todos los aficionados a HTML5, JS y CSS… ahora podréis desarrollar apps Windows Phone nativas de la misma forma que ya se hacía en Windows Store usando HTML5 y JS. Con WinJS también podréis realizar proyectos universales. Cabe mencionar que, aunque usemos la denominación WinJS, en realidad estamos hablando de HTML5 y JS nativo, con lo que podrás usar librerías como JQuery, Angular, Knockout… WinJS es solo necesario para acceder a funcionalidades del sistema.

El nuevo camino planteado por Microsoft es Windows XAML / WinJS. Silverlight para Windows Phone 8.1 ha sido pensado para escenarios muy concretos. En particular la mayor fortaleza de Silverlight es permitirte migrar tus desarrollos de Windows Phone 8.0 a 8.1 y conseguir acceso a las nuevas APIs sin tener que reescribir toda la aplicación o gran parte de ella.

De echo, las aplicaciones de correo, alarmas, calendario, etc… que vienen en el sistema están escritas con este mismo framework Windows XAML. Con lo que nos podemos hacer una idea de su potencia dandole un vistazo a las mismas. Se ha reescrito el motor de ejecución de aplicaciones para Windows XAML y se ha creado una superficie compatible con Silverlight que permite la ejecución de las nuevas aplicaciones de Silverlight 8.1 en el motor de Windows XAML. De esta forma es como las apps  de Silverlight 8.1 pueden acceder a las nuevas APIs de Windows XAML.

image

Como podemos ver, nuestras apps de Windows Phone 8 se seguirán ejecutando sobre el mismo motor, por lo que no tendremos problemas de compatibilidad. Las apps Silverlight 8.1 se ejecutarán sobre una superficie de compatibilidad sobre el motor de ejecución Windows XAML, por eso tienen acceso a todas las nuevas APIs (nuestras apps wp8 no podrán acceder a las nuevas APIs ni usando reflection siquiera). Las nuevas aplicaciones Windows XAML se ejecutan directamente sobre su nuevo motor.

Pero cada sistema tiene sus pros y sus contras. Windows XAML es una nueva manera de desarrollar traída directamente de las aplicaciones Windows Store e introduce muchos cambios. Así, echaremos en falta los ya tan típicos Launchers y Choosers de Windows Phone, que no existen en Windows XAML y algunas cosas más. ¿Como decidimos entre uno u otro para nuestros desarrollos? Aquí intento dejaros una lista de cosas a valorar. La más importante no obstante es recordar que Silverlight para Windows Phone 8.1 existe como ayuda en la transición a la nueva versión del sistema. La opción de continuidad en el futuro es Windows XAML. No incluimos Silverlight para Windows Phone 8 en este apartado, porque no tienes que hacer nada, por defecto tu aplicación funcionará en Windows Phone 8.1.

  • Silverlight para Windows Phone 8.1:
    • Parto de una aplicación para Windows Phone 8.0.
    • No estoy interesado en hacer una versión para Windows Store.
    • Quiero poder tener acceso a las nuevas APIs de Windows Phone 8.1.
    • Necesito hacer uso de Launchers y Choosers en mi aplicación.
    • Mi aplicación usa como característica importante el acceso a la pantalla de bloqueo.
  • Windows XAML:
    • Parto de una aplicación Windows Store.
    • No parto de una aplicación Windows Store o Windows Phone, empiezo desde 0.
    • Tengo una aplicación para Windows Phone 8.0 pero no hago uso de Launchers y Choosers o la pantalla de bloqueo.
    • Quiero poder tener un proyecto único para mi aplicación Phone y Store, de forma que sea muy sencillo mantener ambas aplicaciones.
  • WinJS:
    • Tengo una aplicación WinJS para Windows Store.

Como podemos ver, para cada uno la situación puede ser distinta y el camino a escoger también. Me gusta que Microsoft haya tenido en cuenta el ofrecer una vía rápida de migración de Windows Phone 8.0 a 8.1, mediante Silverlight. Pero debemos tener en cuenta que se trata de eso, una vía de migración. En mi opinión, si vamos a desarrollar una aplicación nueva deberíamos decantarnos por Windows Xaml / WinJS (según nuestra preferencia de lenguaje) y plantearnos seriamente usar los nuevos tipos de proyectos “Universales” que nos permiten desarrollar para Store y Phone al mismo tiempo. Pero, como ya mencionamos antes, Windows XAML trae consigo muchas APIs nuevas y otras muchas que han desaparecido. ¿Qué APIs vamos a perder en comparación con Silverlight y que alternativas tenemos? Vamos a intentar ponerlas en común:

API Silverlight API Windows XAML Notas
PhotoChooserTask y CameraCaptureTask FileOpenPicker Cuando al FileOpenPicker le añadimos un filtro de archivo de imágenes, muestra un botón para acceder a la cámara, además de permitirnos seleccionar una o varias imágenes del teléfono.
Maps/Call/Mail/Marketplace LaunchUri Muchos Launchers y Choosers se pueden cambiar por Uris estandard.
IconicTile / CycleTile, FlipTile Windows 8.1 tiles Ahora los tiles en Windows Phone 8.1 son los mismos que en Windows Store, por lo que los tres tipos de 8.0 desaparecen, podemos elegir entre cerca de 60 plantillas.
Scheduled Background agent Background Task Las tareas en background pasan a ser las usadas en Windows Store.
MPNS WNS Las notificaciones push dejan de usar el sistema Microsoft Push Notification Service para acoger el Windows Notification Service, de Windows Store.
Share Tasks Share Contract En Windows Phone 8.1 tenemos el mismo contrato de compartir que ya teníamos en Windows Store.
Panorama control Hub control El control panorama desaparece y es sustituido por el control Hub de Windows Store, se mantiene el control Pivot.
LongListSelector GridView/ListView/SemanticZoom Se cambia el control LongListSelector por los Grid/ListView con SemanticZoom.

También hay APIs que desaparecen sin alternativa:

  • Lockscreen, en Windows XAML no tendremos acceso a las APIs para establecer nuestra aplicación como proveedor de la imagen de la pantalla de bloqueo.
  • FMRadio, en Windows XAML no tendremos acceso al API de radio FM.
  • Globalization, se usará el sistema de globalización de Windows Store, por lo que este namespace entero desaparece.
  • Voip, no existe en Windows XAML.
  • Alarm/PeriodicTask/ScheduledAction, no existe en Windows XAML.
  • RadialGradientBrush, no existe en Windows XAML.

Tendremos que tener estas listas en cuenta. Si nuestra aplicación necesita alguna de estas APIs, deberemos usar Silverlight para Windows Phone 8.1.

Pero no todo son pérdidas. También tendremos muchas nuevas APIs que nos brindarán mucha más potencia para nuestros desarrollos:

  • Acceso a la galería de imágenes/videos/documentos y música. Mediante el uso de FileOpenPicker podremos acceder a todos los documentos y archivos multimedia de nuestro dispositivo sin restricciones!
  • APIs criptográficas, para poder leer y trabajar con PKIs, certificados  X509 y soporte de métodos criptográficos estandard.
  • Nueva ApplicationBar, extraida directamente de Windows 8.1, enlazable a datos y con muchas nuevas funcionalidades.
  • Nuevos controles: FlipView, GridView, ListView, SemanticZoom, Menu flyouts, RichTextBox, Hub…
  • Nuevo API MediaPlayer para reproducción en background de audio.
  • Namespace Windows.Media.Editing para ayudarnos a editar video directamente en nuestra aplicación.
  • Nuevas funcionalidades de captura de la pantalla de nuestra aplicación para poder grabar videos de la misma usando el namespace Windows.Media.Capture.
  • Transferencias en background mejoradas.
  • Nuevos tiles.
  • Capacidades de Geofencing, que nos permitirán disparar ejecución de código en segundo plano basado en posicionamiento.
  • NFC: mejor soporte de TAGS, TAGS de solo lectura, escribir TAGS sin formato.
  • Control WebView mejorado (el mismo que en Windows Store).
  • Se suprime el IsolatedStorage completamente para dar paso a la api de Storage de Windows Store.
  • Roaming de settings.
  • Contrato de compartir.
  • Soporte de lectura/escritura en tarjetas SD.
  • Nuevas APIs de notificaciones y Action Center.
  • Integración de DirectX y XAML.
  • WebAuthenticationBroker.

Como podemos ver, muchas y variadas novedades. No obstante una de las novedades, en cuanto a desarrollo, que más resonará es la convergencia de la plataforma. Ya lo hemos mencionado en este artículo varias veces. Con Windows XAML tendremos a nuestra disposición nuevos proyectos que nos permitirán crear aplicaciones para Windows Store y Windows Phone. Lo veremos en el siguiente artículo.

Un saludo y Happy coding!

[Windows Phone 8.1] Presentado en el /Build 2014 el SDK de Windows Phone 8.1

Hola a todos

Hoy durante la keynote del /Build Microsoft ha presentado al mundo la nueva versión de su sistema operativo móvil: Windows Phone 8.1. Esta entrega del sistema cuenta con muchas novedades, pedidas por usuarios y desarrolladores desde hace tiempo. En muchos aspectos estas novedades vienen a cerrar huecos dejados por Windows Phone 8 en cuanto a usabilidad.

En sitios web como The Verge, Engadget, XatakaWindows o WinPhoneMetro encontraremos un gran detalle de todas las novedades dirigidas a los usuarios. Lo que nos interesa en este blog es hablar de las novedades para los desarrolladores. En este sentido hay muchas, algunas más complejas que otras, novedades.

En este primer artículo, vamos a dar un repaso a las herramientas, requisitos y novedades en Visual Studio 2013 que incorpora el SDK de Windows Phone 8.1.

Existen diferentes versiones del SDK publicado hoy, dependiendo de la versión de Visual Studio 2013 que uses:

Herramientas

El SDK de Windows Phone 8.1 hace uso de Visual Studio 2013 como entorno de desarrollo. Tiene los siguientes requisitos para instalarlo:

  • Windows 8.1 Pro o superior
  • HyperV
  • Soporte de hardware para SLAT
  • 4Gb RAM (8Gb recomendados para los emuladores más grandes)

Y ¿Qué incluye el SDK? Al igual que el SDK de Windows Phone 8.0 tendremos una serie de herramientas/accesorios instaladas con el SDK:

  • Windows Phone Application Deployment 8.1: Sirve para, a partir de un paquete compilado, poder instalar una app en un emulador o dispositivo físico.
  • Windows Phone Developer Registration 8.1: Para poder registrar nuestro dispositivo para desarrollo. Si tenemos cuenta de desarrollador, podremos registrar hasta 3 dispositivos. Si no tenemos cuenta de desarrollador, con nuestro LiveID podremos registrar un dispositivo.

Además, como es tradicional, encontraremos Microsoft Blend para trabajar en nuestra interface de usuario. Si no disponemos de ninguna versión comercial de Visual Studio 2013, el SDK nos instalará una versión Express para que podamos trabajar sin ningún problema.

Y por supuesto, el plato fuerte, los emuladores. En esta última versión del SDK se incluyen 6 emuladores. En Windows Phone 8 los emuladores se diferenciaban por la resolución que usaban simplemente, pero existía una gran carencia: El tamaño de pantalla. En muchas ocasiones la resolución no es tan determinante como el tamaño de la pantalla en uso. Por ejemplo, si tengo un dispositivo 1080P con una pantalla de 4.5”, la interface será la misma que otro dispositivo de 720P con el mismo tamaño de pantalla. Pero un dispositivo con WXGA (768x1280) de 6” tendrá una interface diferente. Esto se debe a que lo que realmente importa más es el tamaño físico de pantalla, el área de pantalla que el usuario tiene para interactuar. Muchos hemos dado la vara a Microsoft para que tuviese esto en cuenta en los emuladores y, finalmente, así fue. De esta forma, encontramos emuladores divididos por resolución y por tamaño de pantalla:

Nombre Resolución Pantalla Memoria
Emulator 8.1 WVGA 4 inch 512MB WVGA (480x800) 4 pulgadas 512Mb
Emulator 8.1 WVGA 4 inch WVGA (480x800) 4 pulgadas 1024Mb
Emulator 8.1 WXGA 4 inch WXGA (768x1280) 4 pulgadas 1024Mb
Emulator 8.1 720p 4.7 inch 720P (720x1280) 4.7 pulgadas 1024Mb
Emulator 8.1 1080P 5.5 inch 1080P (1080x1920) 5.5 pulgadas 1024Mb
Emulator 8.1 1080P 6 inch 1080P (1080x1920) 6 pulgadas 2048Mb

Como podemos ver, tenemos casi cualquier combinación de dispositivo que podamos encontrar en el mundo real. Esto nos va a facilitar la tarea de adaptar nuestra app a diferentes resoluciones y tamaños de pantalla sin tener que comprar 1001 dispositivos.

Estos emuladores además incluyen nuevas herramientas extendidas que nos ayudarán en nuestro desarrollo:

  • Un simulador de red mejorado.
  • Un simulador de notificaciones.
  • Herramientas para simular geofencing.
  • Mapeo de la tarjeta SD del emulador a un directorio local de nuestro PC.
  • Creación de Checkpoints del emulador, para poder guardar su estado y recuperarlo en otro momento.
  • Configuración de los sensores presentes en el emulador.

image

Una nueva herramienta que incorpora Windows Phone 8.1 es “Developer Power Tools”, que encontraremos en el submenú “Windows Phone 8.1” del menú “TOOLS” de Visual Studio.

Esta herramienta tiene tres pestañas: Application verifier, Performance monitor y Performance recorder.

Application verifier nos permite listar todas las aplicaciones desplegadas en el dispositivo y marcar una serie de tests y comprobaciones tales como memory leaks, manejadores, bloqueos… al presionar el botón “Apply” se ejecutarán las comprobaciones y se marcará el estado de la aplicación.

image

Performance monitor nos permite ver en tiempo real el consumo de recursos del sistema en general o en particular en nuestra aplicación. Uso de CPU, memoria, operaciones de entrada y salida, todo con información bastante detallada. Además nos permite guardar un

image

Por último la pestaña Performance recorder nos permite guardar un log ETL de la actividad de nuestra aplicación, consumo de memoria o CPU, XAML, fallos de audio o video, actividad de GPU y muchos más parámetros.

image

Luego podremos abrir este log con la aplicación Windows Performance Analyzer, donde podremos ver en detalle cada una de las propiedades que hayamos marcado para monitorización:

image

Además, ahora dispondremos de la herramienta Performance and diagnostics para nuestras aplicaciones Windows XAML (Tanto Phone como Store) para poder realizar análisis más exhaustivos de nuestras aplicaciones:

image

Uso de CPU, Memoria, consumo de energía o respuesta de la UI XAML/HTML, así como varias herramientas de testing de rendimiento de Javascript.

Las plantillas de desarrollo de Visual Studio también han sufrido muchos cambios, tantos que les vamos a dedicar un artículo completo. Pero primero repasaremos los nuevos frameworks y opciones de desarrollo que tendremos disponibles, en el próximo artículo. Mientras tanto, puedes ir descargando el SDK de Windows Phone 8.1 aquí. Juega con él un poco y nos vemos en breve con más novedades.

Un saludo y Happy Coding!

[Windows Phone 8.1] Las nuevas aplicaciones universales

Hola a todos!

En el primer artículo de esta serie sobre Windows Phone 8.1 hablamos de las nuevas herramientas, en el segundo hablamos sobre los nuevos modelos de desarrollo. En esta ocasión toca hablar sobre una de las mayores novedades: Las aplicaciones universales. Comencemos!

Después de ver las nuevas herramientas, APIs y tipos de desarrollo, vamos a examinar las nuevas plantillas que tenemos a nuestra disposición. En este sentido también se han producido muchos cambios.

image_thumb16

Como podemos ver en la captura anterior, se han reorganizado las plantillas de proyecto de Windows Store, creando una nueva categoría “Store” que engloba tres subcategorías:

  • Universal Apps. Los nuevos tipos de aplicaciones universales que nos permiten desarrollar apps para Windows Store y Windows Phone 8.1
  • Windows Apps. Aquí encontraremos las plantillas que ya existían para Windows Store.
  • Windows Phone Apps. Aquí tendremos las plantillas de Windows XAML para Windows Phone 8.1.

Además, seguimos teniendo la categoría Wndows Phone, donde tendremos las plantillas para trabajar con Silverlight para Windows Phone (8.0 y 8.1).

La mayor novedad en este sentido viene en las plantillas universales. ¿Qué es una aplicación universal? Este concepto de “universal” nos indica que podremos crear un proyecto en el que facilmente podremos compartir XAML, código y recursos entre una aplicación Windows Store y una aplicación Windows Phone 8.1. Básicamente se crea un proyecto “Universal” que internamente contendrá tres sub proyectos:

  • Windows, con todo lo específico de Windows Store.
  • Windows Phone, con todo lo específico de Windows Phone.
  • Shared, con todo el código que queramos compartir entre ambas plataformas.

image_thumb19

Con esta organización será muy sencillo compartir código entre ambos sistemas. Por defecto, el app.xaml (y app,xaml.cs) yo se incluye en el proyecto Shared, por lo que es compartido para ambas plataformas. Imágenes comunes, controles que queramos reaprovechar (si, también podemos compartir XAML), Converters, ViewModels, Servicios de acceso al hardware, Diccionarios de recursos, incluso los archivos RESW con idiomas, pueden ser colocados en el proyecto shared.

image_thumb5

Luego, simplemente tendremos que colocar en cada proyecto particular las páginas de la aplicación. ¿Podríamos compartir las páginas también? Bueno, técnicamente si. Pero no funcionaría a nivel de experiencia de usuario. Los tamaños de pantalla entre una aplicación Store y Phone son muy diferentes. Algo tan básico como la orientación, que en Phone es vertical mientras normalmente en Store es horizontal, hace que usar la misma página para ambas sea muy complicado. De esta forma, en nuestros proyectos Phone y Store, acabaríamos teniendo las páginas que componen la aplicación y quizás alguna pieza de código que no queramos compartir por ser exclusiva de la plataforma:

image_thumb8[1]

Lo mejor es que, desde el proyecto Shared tendremos acceso a cualquier objeto creado en los proyectos específicos y viceversa. Desde cualquiera de los proyectos de Phone o Store tendremos total acceso al código del proyecto Shared. De esta forma podremos compartir la gran mayoría de código. Siempre encontraremos ciertas cosas que difieren entre las plataformas o funcionalidades que están solo en una de ellas.

Por poner un ejemplo, podemos hablar del FileOpenPicker. En Windows Store usamos los métodos PickSingleFileAsync o PickMultipleFilesAsync. Estos métodos devuelven, respectivamente, un StorageFile o una lista de StorageFile. Al invocarlos, nuestra aplicación sigue en ejecución mientras sobre ella se carga la interface del selector. El problema en Windows Phone viene dado por los dispositivos de baja memoria. En la mayoría de los casos resultaba imposible mantener abierta la aplicación mientras se cargaba la interface del picker. La solución llego por crear dos nuevos métodos llamados PickSingleFileAndContinue y PickMultipleFilesAndContinue. Fijaros  que estos métodos no son asíncronos. No devuelven nada. Cuando los invocamos, nuestra aplicación se suspende y se lanza la aplicación del selector. El usuario selecciona un archivo, presiona atrás o cancela y en ese momento se restaura nuestra aplicación, enviando en los argumentos del evento Activated el resultado de la operación. Debemos ser nosotros los encargados de enviar el archivo a la página/viewmodel correcta y gestionar el estado de la misma. ¿Como podemos compartir este código? Pues de dos formas distintas:

  • Podemos crear un servicio, cuya interface esté en el proyecto Shared y tenga una implementación distinta para cada plataforma.
  • Podemos usar bloques condicionales de compilación. Por defecto el proyecto universal define el símbolo WINDOWS_APP en el proyecto Windows Store y WINDOWS_PHONE_APP en el proyecto Windows Phone.

En próximos artículos hablaremos a fondo de los pickers disponibles y como usarlos. De la misma forma ocurre con algunas cosas más como las transiciones entre páginas. Por lo que, aunque podremos compartir un 80 o 90% del código todavía tendremos algunas cosas para las que tendremos que usar alguno de los puntos anteriores. Pero otras estarán totalmente unificadas: El sistema de navegación, el XAML y los controles, localización… y muchas cosas más.

Otra novedad para los proyectos universales, es que ahora dispondremos de Portable Class Libraries con soporte completo WinRT. Hasta el momento en una PCL solo podíamos usar código .NET. Con el nuevo SDK, tendremos como target Windows Store (Windows 8.1) y Windows Store (Windows Phone 8.1). Si seleccionamos estos dos frameworks solamente, la librería nos permitirá tener código WinRT, incluso XAML dentro de ella.

Y con esto llegamos al fin de este artículo. En el próximo empezaremos a ver código de verdad, con algunos ejemplos de las novedades que incluye Windows Phone 8.1.

Un saludo y Happy Coding!

[Windows Phone 8 ] Tip: Memoria y trabajo con imágenes.

Hola a todos!

En las plataformas móviles como Windows Phone 8 o Windows Store, nuestras aplicaciones tienen unas restricciones claras en el uso de memoria, a diferencia de los sistemas de escritorio que podían ocupar toda la memoria disponible en el sistema.

Hay muchas formas de controlar la memoria que usamos en nuestra aplicación. Aplicar bloques using, usar Dispose correctamente… Pero cuando trabajamos con imágenes, con objetos WriteableBitmap, BitmapImage o BitmapSource, descubriremos que nada de esto sirve.

Por norma general, si desarrollamos bien nuestro código, iremos aumentando el uso de la memoria hasta que llegue un punto en el que, debido a la presión que estamos ejerciendo sobre ella, el recolector de basura (GC, Garbage Collector) entre en escena y libere la memoria no usada.

El problema es que los objetos WriteableBitmap, BitmapImage o BitmapSource en Windows Phone 8 y Windows Store, realmente ocupan muy poca memoria manejada, apenas unos cuantos Kb. Realmente el peso de la memoria es nativo, no manejado en el objeto, ya que la imagen está almacenada en memoria nativa. Por esta razón, el Garbage Collector no es presionado a lanzarse, su memoria manejada no crece peligrosamente. Sin embargo el sistema operativo tiene en cuenta tanto la memoria nativa como la manejada para calcular nuestra cuota de uso.

Una práctica que muchos desarrolladores suelen llevar a cabo llegado este punto, es forzar la recolección de memoria invocando manualmente al Garbage Collector. Esto está totalmente desaconsejado, puesto que en primer lugar va a ralentizar nuestra app muchísimo durante la recolección, pero además puede tener efectos secundarios en la ejecución de nuestra app. Lo mejor, es que existe una forma de evitar esto: hacer que el GC se entere de la memoria que realmente estamos usando.

Existen dos métodos en la clase GC, que son dos grandes desconocidos: AddMemoryPressure y RemoveMemoryPressure. Estos dos métodos nos permiten informar al runtime de grandes bloques de memoria nativa que está siendo usada o que está dejando de ser usada, respectivamente, de forma que el runtime pueda tener en cuenta esta memoria para programar los ciclos de ejecución del recolector de basura. Ambos reciben un solo parámetro, de tipo long, que indica los bytes que estamos añadiendo a la memoria.

De esta forma, cuando por ejemplo carguemos una imagen en memoria y la añadamos a una lista, debemos indicar al sistema el peso que estamos añadiendo en la memoria usando AddMemoryPressure:

AddMemoryPressure
void task_Completed(object sender, PhotoResult e)
{
    WriteableBitmap bmp = new WriteableBitmap(100, 100);
    bmp.SetSource(e.ChosenPhoto);
    listImages.Items.Add(bmp);
    GC.AddMemoryPressure(40000000);
}

De la misma forma, cuando eliminemos o dejemos de usar esa imagen, podemos informar al runtime de que la hemos liberado:

RemoveMemoryPressure
private void RemoveImage()
{
    listImages.Items.RemoveAt(0);
    GC.RemoveMemoryPressure(40000000);
}

Y Voila! Permitimos que sea el sistema el que se ocupe de organizar las recolecciones de memoria y mantener la misma siempre saneada. Sin tener que forzarlas por nuestra parte ni sufrir la lentitud y efectos secundarios de ello.

Un pequeño tip, que espero que os ayude en vuestros desarrollos si trabajáis con muchas imágenes dinámicas o editando imágenes grandes.

Más información: AddMemoryPressure y RemoveMemoryPressure

Un saludo y Happy Coding!

 

[WPSUG] Hangout: Almacenamiento en la nube

Hola a todos!

Logo-256_png-160x0

En WPSUG volvemos a la carga con un nuevo hangout. En esta ocasión hablaremos sobre sistemas de almacenamiento en la nube que podemos integrar en nuestras aplicaciones. Estaremos acompañados por los sospechosos habituales:

  • Roberto Luis Bisbe, hablando sobre Dropbox y Box.
  • Quique Martínez, hablando sobre Azure Storage.
  • Javier Suarez, hablando sobre OneDrive.
  • Pedro Hurtado, hablando sobre Google Drive.
  • Santiago Porras, para comentar la jugada.
  • Un Servidor para atraerlos a todos y atarlos en las tinieblas…. digo en el hangout.

Realizar copias de seguridad, ofrecer a nuestros usuarios la posibilidad de cargar o guardar datos en nuestras apps y miles de situaciones más, requieren el uso de servicios externos de almacenamiento. ¿Como conectamos con ellos? ¿Qué podemos y que no podemos alojar en estos servicios? ¿Como de seguros son? ¿Que tan fácil o difícil es usarlos? Ven al hangout para encontrar respuesta a todas estas y más preguntas!

El Hangout tendrá lugar el miercoles 26 de Marzo, a las 19:00 horas (GMT+1). Podrás seguirnos directamente en esta URL: https://www.youtube.com/watch?v=2PyBLPvePEs

Espero veros a todos allí.

Un saludo y Happy Coding!

[Windows Phone 8] Preparar y administrar una Beta

Hola a todos!

El artículo de hoy no tiene un gran contenido técnico. En su lugar, quiero hablaros de la importancia de usar la distribución beta antes de lanzar nuestra aplicación al gran público, como crearla, distribuirla y administrarla para que nos ofrezca valor, sin que se nos escape de las manos.

Empecemos por ver que nos ofrece la distribución beta en Windows Phone. En primer lugar, nos facilita distribuir nuestra aplicación a un grupo de gente que la quiera probar y que pueda aportarnos feedback, descubrir fallos y ayudarnos a arreglarlos. Podríamos hacer esto mismo simplemente enviando el archivo XAP compilado por correo, pero eso exigiría que cada una de las personas que la vayan a probar tengan el SDK y un teléfono desbloqueado para desarrollo. Lo más importante en este punto es que quienes vayan a probar la beta, no tienen porqué ser desarrolladores. De echo sería muy bueno que no fuesen desarrolladores, para tener opiniones de alguien que no esté “contaminado” por la tecnología. Además, tenemos que simplificar el acceso a la beta, al distribuirla por la tienda de apps, se puede instalar directamente en el dispositivo sin necesidad de hacer nada más que click en un enlace.

Cuando vayamos a publicar nuestra aplicación, solo tendremos que seleccionar la opción “Beta” en “Distribution channels”, dentro del desplegable “More options”. Al seleccionar esta opción se habilitará una caja de texto donde deberemos introducir los LiveIDs de los participantes de la beta:

image

Aquí podemos encontrarnos con la primera dificultad. La distribución Beta nos permite tener hasta 10.000 LiveIDs añadidos, ¿Como gestionamos todo esto? Hay mil formas. Desde algo tan simple como un archivo de texto o un excel, hasta sistemas que nos aporten más funcionalidad. Precisamente, yo creo que esta segunda opción es la mejor, usar un sistema que nos permita tener más funcionalidad. En la gran mayoría de casos, los LiveIDs son también los correos electrónicos de esas personas, y nuestra principal vía de comunicación con ellos. Por cada versión beta, podemos comunicarles que ya está disponible, que incluye, que bugs son conocidos para que no pierdan su tiempo con ellos y darles cualquier indicación que sea necesario. Para gestionar todo esto, yo he escogido una herramienta muy usada, llamada MailChimp:

image

MailChimp es una herramienta para crear campañas de correo, manteniendo listas de distribución. Nos ofrece funcionalidad para crear formularios de registro, listas de personas suscritas, crear campañas de correo (enviar correos electrónicos a las listas), programar el envío de una campaña para una fecha/hora concreta e incluso estadísticas de quien ha abierto un correo de una campaña, quien ha hecho click en un enlace de esa campaña… Además podemos exportar la lista de personas suscritas a un archivo csv, que nos será muy útil para añadir los correos a la distribución beta. En Definitiva tenemos una forma de gestionar todas las comunicaciones con nuestros suscriptores, de permitir que nueva gente se suscriba a nuestras betas (porque, ¿Para que mantenerla privada? Cuanta más gente la pruebe, mejor!) o si ya no le interesa, se des suscriba cuando quiera.

Es realmente de usar y totalmente gratis. Una vez registrados, lo primero que tendremos que hacer es crear una lista:

image

Dentro de las opciones de la lista, encontraremos una llamada “Sign up forms” que nos permitirá crear y personalizar el formulario de suscripción, para adaptarlo al aspecto de nuestra aplicación e incorporar los campos que necesitemos pedir al usuario:

image

Solo alguna recomendación aquí:

  • Mantén el formulario lo más simple posible, no pidas datos que no vas a necesitar. Pidiendo muchos datos puedes acabar con el interés del usuario.
  • Personalízalo un poco. No te digo que inviertas 5 días en crear un formulario impresionante, pero un par de horas, para darle un aspecto que recuerde a tu app, si. Queda más profesional, y vas introduciendo al usuario a tu visión, a lo que se va a encontrar en la app.
  • Por lo menos, incluye dos idiomas: Inglés y Español. Así te aseguras que la gente que llegue a la página, podrá entender de que va. Puedes hacerlo poniendo ambos idiomas en la misma página o mediante traducciones. Como más gustes.

Una vez terminado el formulario, en la parte superior encontrarás una URL corta que da acceso a él. Cógela y lánzala al mundo: Twitter, Facebook, correo… cualquier medio es valido para llegar a la gente. pon la url y tu mensaje en inglés y español, es interesante salir de “la tierra” y tener usuarios de la beta por todo el globo, ofreciéndote su visión particular sobre la app.

Otro punto interesante es tener una cuenta de correo nueva para la aplicación, en mi caso photolabapp@outlook.com, cuando creemos una campaña de MailChimp nueva, usaremos esa misma cuenta como remitente y pediremos a los usuarios que envíen su feedback a ella. De esta forma separamos el feedback de nuestros otros correos personales o profesionales y mantenemos cierto orden en las comunicaciones.

Y por último nos queda gestionar el feedback recibido. Principalmente recibiremos dos tipos de elementos: bugs, que tendremos que ir corrigiendo, y mejoras, que implementaremos o no. Es muy recomendable que tengamos la mente abierta a las sugerencias de nuestros usuarios. En muchos casos pueden proponer cosas que no se nos habían ocurrido pero que realmente mejoran la app muchísimo. Es importante priorizar y llevar un control de estos bugs y mejoras. ¿Como? Pues como más cómodo te resulte, pero si partimos de la base de que usas TFS Online (www.visualstudio.com) para gestionar tu código, puedes crear iteraciones, una por beta por ejemplo, e introduciendo en ella el feedback de los usuarios. Así al final, cuando vayas a enviar la siguiente beta, podrás adjuntar un resumen de las mejoras y correcciones introducidas y de lo que tienes pendiente:

image

Y Voila, solo queda repetir una y otra vez hasta que el feedback sea mínimo, los bugs estén corregidos… y estemos listos para sacar nuestra app al gran público. ¿Y cuanto es eso? Pues en el caso de PHOTOLab, realicé 5 versiones beta. Lancé la primera tan pronto como el core de la app estaba listo para ser probado. Por último, en mi tierra dicen eso de “Es de bien nacidos, ser agradecidos”, por lo que yo personalmente recomiendo agregar una sección de gracias en el acerca de de tu app, para agradecer a toda la gente que te ha dado feedback y ha invertido tiempo probando tu app desinteresadamente:

unnamed

Que así por lo menos vean que aprecias su ayuda. Seguro que la próxima vez que les pidas que te ayuden con una revisión, estarán encantados de hacerlo.

Y con esto terminamos este artículo. Aun no habiendo tocado ningún tema técnico, de código, creo que es muy importante saber, primero, que las betas existen y que podemos usarlas. Y segundo, que manejarlas adecuadamente y hacer caso a nuestros usuarios, puede reportarnos muchos beneficios y ahorrarnos muchos problemas y perdidas de tiempo.

El próximo artículo, si tendrá código, lo prometo. :-)

Un saludo y Happy Coding!

[Windows Phone 8] Monetizar nuestra app: In App Purchase

Hola a todos!

euros

Hoy quiero hablaros de como monetizar vuestras apps usando In App Purchase (IAP). Sorprendentemente, IAP es un método de monetización que se puede encontrar en juegos pero que no se usa en apps tanto como debería.

Básicamente, IAP nos permite incorporar pagos dentro de nuestra aplicación, ya sea esta gratuita o tenga coste inicial. Existen dos tipos de “bienes” que podemos adquirir usando IAP: Consumibles y Perpetuos:

  • Los bienes consumibles son aquellos que podemos adquirir y una vez usados, desaparecen. Por ejemplo, monedas o un power up.
  • Los diebes perpetuos son aquellos que una vez adquiridos, nunca desaparecen. Por ejemplo, un pack de funcionalidades extra.

Implementar IAP en nuestra aplicación es muy sencillo y nos ofrece muchas ventajas. Con IAP hacemos que nuestra app sea de modelo “freemium”, es decir, gratuita y con pagos por contenidos o funcionalidades extra. Hay que ser muy cuidadoso con este aspecto, buscando equilibrio entre el cobro de partes de nuestra aplicación y su funcionamiento básico. En todo momento, debería ser posible usar la aplicación sin problemas sin pagar. Siendo estos micro pagos una forma de añadir funcionalidades nuevas.

Otra forma de usar IAP es para eliminar publicidad. Hoy en día es muy complicado que una app media genere beneficios mediante publicidad. En muchos casos, molestamos al usuario con publicidad, y no ganamos apenas más que unos céntimos al día. Al final, estamos “regalando” el espacio de anuncio y molestando a nuestro usuario y solo el anunciante se beneficia de ello. Un truco muy usado es incluir sobre la publicidad un botón de eliminar, normalmente una X, que quite la publicidad de la app mediante un IAP, de 0.99€ normalmente. De esta forma, si al usuario le molesta la publicidad o quiere recompensarnos directamente por nuestro trabajo, solo tiene que pagar este IAP y ambos ganan, desarrollador y usuario. Si no le molesta o no quiere pagar por quitar la publicidad, nos producirá los beneficios normales de la misma. En combinación, siempre vamos a ganar más dinero, conseguir generar 0.99€ con publicidad no es tarea fácil.

Creo que esta última opción es la más útil para una aplicación que no sea un juego. Es en la que me quiero centrar en este artículo. Las APIs para trabajar con IAP se encuentran en el namespace Windows.ApplicationModel.Store, en la clase CurrentApp. En esta clase encontraremos un método llamado RequestProductPurchaseAsync, que nos permitirá lanzar la pantalla de compra de un elemento IAP y la clase LicenseInformation que contiene un diccionario llamado ProductLicenses con el estado de todos los productos que podemos comprar en nuestra aplicación. Por ejemplo, imaginemos que tenemos un item IAP llamado REMOVEADS. El código para lanzar la pantalla de compra del mismo sería este:

Comprar un item IAP
public async Task PurchaseRemoveAds()
{
    try
    {
        await CurrentApp.RequestProductPurchaseAsync("REMOVEADS", false);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Muy sencillo. El primer parámetro es el Id del artículo que deseamos comprar y el segundo indica si se debe devolver un ticket de compra que podamos mostrar al usuario. Fijaros que tenemos el método envuelto en un bloque try/catch. Esto es debido a que, si el usuario cancela la compra o esta no se puede realizar por algún motivo, el método RequestProductPurchaseAsync devolverá una excepción con un valor HRESULT H_FAIL. (Para otro día dejamos el tema de Microsoft y los errores descriptivos).

Para comprobar si un item concreto, por ejemplo REMOVEADS, ha sido comprado por el usuario, podemos usar el siguiente código:

Comprobar compra
public bool AdsRemoved()
{
    var product = CurrentApp.LicenseInformation.ProductLicenses["REMOVEADS"];
    if (product != null && product.IsActive)
        return true;

    return false;
}

Y listo, podemos usar el método AdsRemoved para saber cuando mostrar u ocultar los anuncios en la aplicación. La propiedad IsActive devolverá true si el item se ha comprado y false de lo contrario.

Ahora, ¿Como podemos probar nuestro código antes de publicar la aplicación? Existen dos formas principalmente: Usando la publicación en beta o haciendo un mock de In App Purchase. Yo personalmente prefiero la primera, la publicación en beta, porque pruebo el proceso real al 100% (menos en la parte de cobrar, los IAP en beta tienen coste 0 siempre).

Si queréis leer a fondo sobre como realizar un Mock del IAP para pruebas, podéis leer más aquí. El problema del mock, es que al final te quedas con la duda de si realmente todo va a ir bien una vez subas tu app a la tienda. Por lo que acabas probando una distribución beta, así que, ¿Porqué no hacerlo desde el principio?

DISCLAIMER: El Mock puede ser una buena solución en escenarios complejos, donde por ejemplo tengas que probar lógica asociada a las compras, los items sean consumibles que caducan, etc… Pero creo que para un escenario como este, no son necesarios.

Así que vamos allá, una vez que tengas todo tu código en su sitio y lo hayas probado, verás que siempre que intentas hacer una compra, esta falla. Es normal, ya que el proceso va a los servidores de Microsoft a buscar los items asociados con tu aplicación y no encuentra ninguno. Así que lo primero que tienes que hacer es publicar tu aplicación en modo beta. El proceso de publicación es el mismo que para una aplicación normal, salvo que en el primer paso, App Info, en la sección More options debemos seleccionar Beta. Al hacerlo se habilitará el cuadro de texto que tiene debajo, donde debemos indicar, separados por punto y coma, los liveIDs de los participantes de la beta. Normalmente para probar los IAP, en primer lugar usaremos solo nuestro LiveID, para asegurarnos que todo va bien. El resto del proceso es totalmente igual. Una vez que hayamos publicado nuestra aplicación en beta, podemos añadirle productos. En nuestro caso se llamará REMOVEADS. Para ello pulsamos sobre la aplicación en el Dashboard y vamos a la última pestaña: Products, donde encontraremos un enlace Add in-app product.

image

Debemos seguir varios pasos, al igual que en la publicación de la aplicación y al terminar el producto pasará a certificarse. Si, los productos de IAP también pasan su propia certificación. Pero en nuestro caso, al estar trabajando sobre una beta, no tardará más de unos minutos. Es muy importante asegurarnos de que introducimos el mismo ID de producto que usamos en el código o no funcionará.

image

Ten en cuenta que puedes definir varios idiomas para cada producto, siendo recomendable que traduzcas el nombre y la descripción a los mismos idiomas que soportes en la app. Así mismo necesitarás un icono de 300x300 píxeles para el producto.

Y listo, una vez que la beta esté publicada, podremos instalarla en nuestro dispositivo y, si hemos hecho todo bien, deberíamos poder comprar el producto sin ningún problema.

Lo que más me gusta de este proceso, es que es rapidísimo, en unos 15 minutos todo está publicado y podemos probarlo en vivo y en directo. Además estamos probando el proceso real, puesto que lo único que cambiará cuando publiquemos es que no usaremos una beta y podremos poner un precio al producto.

Importante: Una vez que hayas terminado de probar y te dispongas a publicar tu aplicación de forma definitiva, recuerda eliminar el producto creado de la beta, pues aunque los productos se definen por aplicación, su ID debe ser único. Debido a esto tienes que eliminar el producto beta para poder crear el final.

Espero que esto os pueda ayudar a monetizar vuestras aplicaciones. Animaros a incluir IAP en ellas, porque al final todo se trata de ofrecer al usuario formas de pagar por nuestro trabajo, ya sea mediante anuncios o mediante compras. Además, con este sistema vuestra app sigue siendo gratuita, por lo que más usuarios se la descargarán.

Un saludo y happy Coding!

[HANGOUT WPSUG] Azure Mobile Services y Microsoft AppInsights

Logo-256_png-160x0

Hola a todos!

Hoy tenemos a dos grandes de la comunidad invitados al hangout mensual de WPSUG.

Hablo de Quique Martinez (Windows Azure MVP) y Rafael Serna (Nokia Developer Champion).

Como podréis adivinar, el hangout de hoy estará dedicado a la nube. En concreto, Rafa nos hablará de Azure Mobile Services y Quique de Microsoft Application Insights, una nueva tecnología, actualmente en preview, para monitorizar nuestras aplicaciones móviles (Windows Store y Windows Phone) y nuestros servicios.

¿Cuando?

Hoy jueves 20 a las 19:00 (GMT+1)

¿Donde?

En YouTube, en la siguiente dirección: http://www.youtube.com/watch?v=ut3Ykb3mQD0

Os esperamos!!

Recordad también que podéis acceder a nuestro canal de YouTube para poder ver los videos de los hangouts anteriores.

Un saludo y Happy Coding!!

[Windows 8.1] Listas paginadas

Hola a todos!

Hoy vamos a cambiar un poco de temática, para hablar de paginación en apps Windows Store para Windows 8.1.

En Windows Phone 8, usamos la capacidad del LongListSelector para detectar el final de la lista y poder lanzar la carga de más elementos. En Windows Store no disponemos de LongListSelector. En su lugar usamos un control GridView o ListView. Estos controles no tienen la capacidad de detectar la compresión final para cargar más elementos. En su lugar, realizan la carga de más páginas automáticamente usando la interface ISupportIncrementalLoading.

Esta interface debe estar implementada en la colección que enlazamos al GridView o ListView. Por defecto no existe ninguna colección que la implemente por lo que tendremos que crearnos la nuestra propia. Para ello podemos partir de una ObservableCollection. ISupportIncrementalLoading implementa una propiedad de solo lectura llamada HasMoreItems y un método llamado LoadMoreItemsAsync:

ISupportIncrementalLoading
public class PaginatedCollection<T> : ObservableCollection<T>, ISupportIncrementalLoading
{

    public bool HasMoreItems
    {
        get { throw new NotImplementedException(); }
    }

    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        throw new NotImplementedException();
    }
}

Normalmente necesitaremos usar este tipo de colección con más de un tipo de dato y la carga de más páginas, en el método LoadMoreItemsAsync, también variará. Para solventar esto podemos usar una táctica parecida a la empleada en el DelegateCommand en MVVM. Vamos a añadir un constructor que se encargue de recibir dos Func<T>: Uno para saber si debemos cargar más elementos y otro para cargarlos:

PaginatedCollection ctor
Func<uint, IEnumerable<T>> getMoreItems;
Func<bool> getHasMoreItems;

public PaginatedCollection(Func<uint, IEnumerable<T>> _getMoreItems, Func<bool> _getHasMoreItems)
{
    getMoreItems = _getMoreItems;
    getHasMoreItems = _getHasMoreItems;
}

Ahora simplemente, la propiedad HasMoreItems llamará a getHasMoreItems:

HasMoreItems
public bool HasMoreItems
{
    get
    {
        return getHasMoreItems();
    }
}

En el método LoadMoreItemsAsync, tendremos que trabajar un poco más. Básicamente debemos realizar los siguientes pasos:

  1. Llamar a getMoreItems
  2. Insertar los elementos nuevos en la colección base
  3. Devolver un nuevo LoadMoreItemsResult con el conteo de elementos recibidos.

Pero existen ciertas peculiaridades. El método LoadMoreItemsAsync devuelve un tipo IAsyncOperation<LoadMoreItemsResul>. Tendremos que ejecutar nuestro código en una Task para luego convertirlo a IAsyncOperation. Pero al ejecutar el código en una Task, si intentamos añadir elementos a la colección base obtendremos una excepción cross thread. Para evitar esta excepción, antes de modificar el método LoadMoreItemsAsync, vamos a añadir una propiedad pública y estática a nuestra clase App, para poder exponer el Frame de la aplicación y acceder fácilmente al Dispatcher que contiene, de forma que podamos usar el hilo principal de UI para añadir elementos a la colección. ¿Porqué? Pues por que la base de nuestra colección es una ObservableCollection, que notifica a la UI cada vez que su contenido cambia (al añadir o eliminar un elemento) y esta notificación debe producirse desde el hilo principal de interface de usuario:

Static RootFrame
sealed partial class App : Application
{
    public static Frame RootFrame { get; set; }

Una vez hecho esto, ya podemos escribir el código del método LoadMoreItemsAsync:

LoadMoreItemsAsync
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
    return Task.Run<LoadMoreItemsResult>(async () =>
    {
        var newItems = getMoreItems(count);

        await App.RootFrame.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
        () =>
        {
            foreach (var item in newItems)
                base.Add(item);
        });


        return new LoadMoreItemsResult() { Count = (uint)newItems.Count() };
    }).AsAsyncOperation<LoadMoreItemsResult>();
}

En este código, lo primero que hacemos es devolver una ejecución de una Task, como una AsyncOperation de LoadMoreItemsResult. Internamente dentro de esta Task, llamamos al Func<uint, IEnumerable<T>> que recibimos en el constructor, getMoreItems, pasándole el conteo de elementos que nos pide la interface de usuario. Esto puede ser muy útil si nuestra petición de nuevos datos permite indicar cuantos elementos obtener.

Una vez que recibimos los elementos, usamos el método RunAsync del dispatcher incluido en el RootFrame para, mediante un foreach, añadir cada elemento devuelto a la colección base. Por último la tarea devuelve un nuevo LoadMoreItemsResult, con el número de elementos devueltos.

Ya tenemos el código de nuestra clase PaginatedCollection<T> terminado. Ahora llega el momento de usarla en una ViewModel. En primer lugar creamos una variable privada y una propiedad pública, como con cualquier otra lista:

Public property use
private PaginatedCollection<string> collection;
public PaginatedCollection<string> Collection
{
    get { return collection; }
    set
    {
        collection = value;
        RaisePropertyChanged();
    }
}

A continuación vamos a escribir dos métodos privados, uno para devolver true/false y otro para obtener nuevos elementos. Deben coincidir con la firma que hemos declarado en la colección: Func<bool> y Func<uint, IEnumerable<T>> respectivamente:

HasMoreItems & GetMoreItems
private bool HasMoreItem()
{
    if (elementCount > 100)
        return false;

    return true;
}

private IEnumerable<string> GetMoreItems(uint count)
{
    IList<string> list = new List<string>();

    for (int i = 0; i < count; i++)
    {
        list.Add(string.Format("string number {0}", i));
    }
    elementCount += count;

    return list;
}

En este ejemplo, para no complicarlo, no estamos llamando a ningún servicio, simplemente cada vez que se nos piden datos, creamos nuevas strings. Exactamente el número que nos pide la lista. mientras ese número esté por debajo de 100, seguimos devolviendo true en nuestro método boolean. Por último, en nuestro constructor, inicializamos la nueva colección:

Collection constructor
public MainViewModel()
{
    collection = new PaginatedCollection<string>(GetMoreItems, HasMoreItem);
}

Y ahora solo nos queda el XAML. Para este ejemplo usaremos un GridView. También podríamos usar un ListView, que soporta paginación.

GridView XAML
<GridView ItemsSource="{Binding Collection}"
            IncrementalLoadingThreshold="1"
            IncrementalLoadingTrigger="Edge">
    <GridView.ItemTemplate>
        <DataTemplate>
            <Grid Margin="24" Width="350">
                <TextBlock Text="{Binding}" FontSize="36"/>
            </Grid>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

Como podemos ver no existe nada especial en esta declaración del GridView, salvo dos propiedades: IncrementalLoadingThreshold e IncrementalLoadingTrigger. Por defecto IncrementalLoadingTrigger tiene el valor Edge, la he indicado explícitamente para mostrarla, pero no es necesario hacerlo. IncrementalLoadingThreshold es muy importante sin embargo. Indica el número de páginas pendientes de ver antes de pedir nuevas. Cuidado, el número de páginas. Si introducimos un valor de 1, la petición de nuevos datos no se realizará hasta que el usuario no llegue casi al final de la lista. si introducimos 10, dejaremos mucho espacio entre el final y el usuario. Debemos calibrar esta propiedad bien, para equilibrar la respuesta al usuario con el uso de recursos.

Y ya tenemos terminado nuestro código. Si ejecutamos, veremos que funciona perfectamente. Ahora, una pregunta para nota. ¿Donde se realiza la carga inicial de datos? En ningún momento hemos llamado para obtener datos inicialmente. Esta es una de las ventajas del sistema de paginación. No tenemos que realizar la carga inicial. Cuando el control se enlaza, ve que tiene 0 elementos y como está dentro del Threshold indicado, pide datos a la lista inmediatamente. Con lo que nos hemos ahorrado tener que inicializarla nosotros mismos.

Con esto llegamos al final de este artículo. Espero que os haya gustado y sea útil. Como siempre, aquí tenéis el código de ejemplo en funcionamiento para que podáis jugar con él y tenerlo de referencia.

Un saludo y Happy Coding!!

[Windows Phone 8] Ejecución de código en segundo plano (III y Fin)

Hola a todos! Vamos a por el tercer artículo sobre ejecución de código en Background.

Volvemos a la carga, tras ver como realizar geolocalización en background y como ejecutar tareas programadas en background. En esta ocasión vamos a descubrir como reproducir música independientemente de nuestra app, de forma que si el usuario la cierra, la música siga reproduciéndose. Podemos ver ejemplos de apps que usan reproducción de audio en segundo plano, tales como Nokia MixRadio, P|Cast, Spotify y muchas otras.

Existen dos tipos de agentes de audio diferentes: El agente de reproducción de audio y el agente de streaming de audio. Su uso es exactamente el mismo. Su principal diferencia es la forma en la que entregan el audio al sistema. El agente de audio simplemente obtiene una Uri (local o remota) y la pasa al sistema de reproducción. El agente de streaming de audio debe implementar su propia clase de decodificación de audio (MediaStreamSource) encargada de decodificar el audio y pasárselo al sistema. Esto último nos permite una gran libertad a la hora de trabajar con audio, pero requiere un esfuerzo y conocimientos sobre audio y codecs extra, pues seremos los encargados de su creación de principio a fin.

En general, todo audio que se reproduce en Windows Phone, sigue la siguiente estructura:

image

En el gráfico anterior podemos separar tres partes, representadas por colores.

Las cajas grises indican partes del sistema. Entre ellas encontramos el reproductor en background del sistema, la cola de multimedia de Zune (si, Zune sigue vivo en lo más profundo de vuestros Windows Phone, aunque desde Microsoft se esfuercen en borrar su nombre de la historia…) y el control de volumen universal.

Las cajas naranjas indican las partes que debemos implementar para crear una aplicación capaz de reproducir audio en background. Simplemente tenemos la aplicación en si misma y el agente de audio.

Por último, las cajas verdes simbolizan el código que tendremos que añadir para usar un agente de streaming de audio.

Como podemos ver en el gráfico, la parte común entre ambos sistemas es que siempre tenemos que crear un agente de audio, por lo que nos centraremos en él en este artículo. Si quieres información más profunda sobre el streaming de audio, empieza tu viaje por la madriguera de conejo aquí. Suerte con la pastilla roja.

Después de haber visto las tareas programadas, esto os va a “sonar” mucho. De echo, la mecánica es la misma. tendremos un proyecto para la reproducción en background, un agente, que se integrará con nuestra aplicación y con los controles de audio del sistema. De esta forma, desde nuestra app podremos indicarle que reproducir y cuando empezar, parar o cambiar de una canción a otra. Pero al mismo tiempo, el usuario podrá abandonar nuestro programa y usar los controles de audio (reproducir, pausar, adelante y atrás) integrados en el sistema para gestionar el audio. Cada vez que el usuario realice una acción en estos controles, se invocará un método OnUserAction en nuestro agente. De la misma forma, cada vez que el estado de reproducción cambie, se invocará un método OnPlayStateChanged, por ejemplo cuando acabe una canción, para que podamos reproducir la siguiente.

Como la ejecución es bajo demanda, es decir, es el usuario o el audio quienes marcan cuando se ejecutarán estos métodos, no tenemos intervalos prefijados como en el agente de tareas programadas. Pero eso no nos libra de tener restricciones:

  • Memoria: tendremos un límite de consumo. Hasta Windows Phone 8 GDR3, este límite es de 20Mb. Con GDR3 el límite sube a los 25Mb. Es importante tener en cuenta también que, con un agente en streaming, compartiremos esa memoria con el agente de audio. no tendremos 20/25Mb para cada uno.
  • Tiempo: Aunque la ejecución se realiza bajo demanda, tendremos que llamar a NotifyComplete o Abort antes de pasar 30 segundos o se cerrará el agente.

Ahora que ya conocemos toda la teoría necesaria, vamos a ver un ejemplo práctico de reproducción de audio en segundo plano. Lo primero que vamos a hacer es crear una nueva solución, con un proyecto Blank Application y un proyecto “Windows Phone Audio Playback agent”. Por defecto nos creará una clase llamada AudioAgent.cs que hereda de AudioPlayerAgent y sobre escribe una serie de métodos:

  • OnPlayStateChanged
  • OnUserAction
  • OnError

Por defecto veremos que el método OnUserAction ya tiene una lógica básica implementada, con un Switch() case que se encarga de parar, reproducir, saltar canción, rebobinar, avanzar…

OnUserAction
protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)
{
    switch (action)
    {
        case UserAction.Play:
            if (player.PlayerState != PlayState.Playing)
            {
                player.Play();
            }
            break;
        case UserAction.Stop:
            player.Stop();
            break;
        case UserAction.Pause:
            player.Pause();
            break;
        case UserAction.FastForward:
            player.FastForward();
            break;
        case UserAction.Rewind:
            player.Rewind();
            break;
        case UserAction.Seek:
            player.Position = (TimeSpan)param;
            break;
        case UserAction.SkipNext:
            player.Track = GetNextTrack();
            break;
        case UserAction.SkipPrevious:
            AudioTrack previousTrack = GetPreviousTrack();
            if (previousTrack != null)
            {
                player.Track = previousTrack;
            }
            break;
    }

    NotifyComplete();
}

También tiene dos métodos ya creados: GetPreviousTrack y GetNextTrack. Estos métodos son llamados desde OnUserAction y OnPlayStateChanged. Para hacer un reproductor básico, solo deberíamos incluir código en estos dos métodos finales para obtener la canción anterior y siguiente respectivamente.

Lo primero que vamos a hacer en la clase AudioAgent es crearnos una lista estática de AudioTracks, para este ejemplo voy a usar la url de los MP3 del podcast WPControla que hice con Rafa Serna hace un tiempo:

AudioTrack list
private static IList<AudioTrack> tracks = new List<AudioTrack>
{
    new AudioTrack
    {
        Source = new Uri("http://audios.wpcontrola.com/capitulo1.mp3"),
        Title = "WPControla 1",
        Artist = "Rafa y Yeray",
        Album = "WPControla greatest hits"
    },
    new AudioTrack
    {
        Source = new Uri("http://audios.wpcontrola.com/capitulo2.mp3"),
        Title = "Captulo 2",
        Artist = "Rafa y Yeray",
        Album = "WPControla greatest hits"
    },

};

Por supuesto en una aplicación real tendrías un servicio que fuese el encargado de devolverte la lista de canciones, no las tendrías codificadas en el agente de audio. Pero lo que si es recomendable es que tengas una lista estática, pues así esta no se crearía y destruiría con las diferentes invocaciones del control del sistema.

También necesitaremos un entero que nos permita seguir el índice de la lista que se está reproduciendo en cada momento.

Una vez que tenemos nuestra lista creada, vamos a añadir el código necesario a los métodos GetPreviousTrack y GetNextTrack:

GetPreviousTrack/GetNextTrack
private AudioTrack GetNextTrack()
{
    if (++currentTrackNumber >= tracks.Count)
    {
        currentTrackNumber = 0;
    }

    return tracks[currentTrackNumber];
}

private AudioTrack GetPreviousTrack()
{
    if (--currentTrackNumber < 0)
    {
        currentTrackNumber = tracks.Count - 1;
    }

    return tracks[currentTrackNumber];
}

Simplemente nos movemos por la lista, devolviendo la track que corresponda en cada caso. Por último para terminar con el código de nuestro agente, solo nos queda controlar la acción Play en el método OnUserAction. Si la track del reproductor no está establecida, la establecemos nosotros:

Acción Play
case UserAction.Play:
    if (player.PlayerState != PlayState.Playing)
    {
        if (player.Track == null)
            player.Track = tracks[currentTrackNumber];
        player.Play();
    }
    break;

Y ahora ya podemos ir a nuestra aplicación. Este ejemplo es muy simple. Tendremos un botón “play” con el que comenzar la reproducción de nuestros tracks en segundo plano. Para ello usaremos la clase BackgroundAudioPlayer, que contiene la instancia global del reproductor del sistema:

PlayAudio command execution
private void PlayAudioExecute()
{
    if (BackgroundAudioPlayer.Instance.PlayerState != PlayState.Playing)
        BackgroundAudioPlayer.Instance.Play();
    else
        BackgroundAudioPlayer.Instance.Pause();
}

Y Voila! Ya tenemos nuestro reproductor del Podcast de WPControla integrado con el sistema!

Si ejecutamos la aplicación y presionamos el botón “play”, empezaremos a escuchar el capítulo 1 de WPControla. Podemos volver a la pantalla de inicio del sistema y presionar la tecla de volumen para ver que se muestra la información de cada track y responde a nuestras ordenes.

NOTA: Para que todo funcione, pruébalo en un dispositivo real, en los emuladores tiene un comportamiento errático que lo hace fallar a veces.

Y con esto llegamos al final de esta serie dedicada a la ejecución de código en segundo plano. Como siempre, aquí tienes el código listo para descarga, de forma que tengas un punto de partida, con MVVM y bien colocado.

Un saludo y Happy Coding!!

P.D.: Si quieres escuchar todos los capítulos de WPControla, puedes hacerlo aquí!

[WPSUG] Materiales de Nokia MixRadio API

Hola a todos!

El pasado jueves 30 de enero de 2014 tuvimos un nuevo hangout de WPSUG, en esta ocasión sobre APIs de música que podemos integrar en nuestras aplicaciones Windows Phone y Windows Store.

Javier Suarez nos habló de XBox music y yo me centré en Nokia MixRadio. A continuación tenéis el enlace al vídeo del Hangout en nuestro canal de YouTube, las slides que usé sobre Nokia MixRadio y el ejemplo completo que enseñé. Espero que os sea de utilidad.

Video de Youtube WPSUG: APIs de Música

Slides de mi parte sobre Nokia MixRadio en SlideShare:

Y por último, el código fuente del ejemplo, que podéis descargar aquí.

Un saludo y Happy Coding!!

[Windows Phone 8] Ejecución de código en segundo plano (II)

Hola a todos!

Vuelvo a la carga con el segundo artículo de la serie sobre código en segundo plano:

En esta ocasión nos toca hablar de las tareas programadas en segundo plano. En Windows Phone 8 podemos crear un tipo especial de proyecto llamado “Windows Phone Scheduled Task Agent”, este proyecto se podrá ejecutar cuando nuestra aplicación no esté activa, ejecutando código. Lo más importante es que comparte espacio de aplicación con nuestra app, por lo que podremos compartir archivos entre ambos proyectos de forma muy sencilla. Además, dispondremos de dos formas de registrar nuestro agente: Como una tarea intensiva o periódica. Su ejecución es la misma, pero contarán con diferentes limitaciones.

Pero no todo es precioso. Antes de ver como usar este tipo de proyecto, repasemos sus limitaciones:

Limitación Intensivo Periódico
Memoria (Sistema 1Gb) Máximo 20Mb hasta GDR2/ 25Mb en GDR3  Máximo 20Mb hasta GDR2/ 25Mb en GDR3
Memoria (Sistema 512Mb) Máximo 11Mb Máximo 11Mb
APIs Algunas APIs no están soportadas Algunas APIs no están soportadas
Caducidad Cada 2 semanas Cada 2 semanas
Desactivación por fallos Tras 2 fallos Tras 2 fallos
Periodo entre ejecuciones   30 minutos
Duración de ejecución 10 minutos 25 segundos
Batería Solo se ejecutan con +90% de batería.
Dispositivo conectado a red eléctrica.
Solo se paran si el dispositivo entra en ahorro de batería.
Conexión Solo pueden usar WiFi  
LockScreen Solo se ejecutan bajo lockscreen  
Límite de agentes por dispositivo   Varía por configuración, pero por encima de 6

Como podemos ver, esto no es como si nuestra aplicación estuviese en segundo plano constantemente. Existen muchas restricciones y debemos ser muy conscientes de ellas. La realidad nos dice que hay muy pocas aplicaciones que usen agentes intensivos. Casi siempre usaremos agentes periódicos. Tareas como actualizar el Live tile, descargar datos de un servicio web o comprobar datos, pueden ser realizadas sin problemas por este tipo de agentes.

Vamos al turrón! Empezamos a ensuciarnos las manos, creando un nuevo proyecto Windows Phone 8 normal. Con este proyecto se creará una solución, a la que añadiremos un proyecto del tipo “Windows Phone Scheduled Task Agent”, que encontraremos al final de la lista de proyectos de Windows Phone 8:

image

Una recomendación, no llaméis a vuestro proyecto ScheduledTask, ya que hay un tipo de dato que es precisamente ScheduledTask y tendréis que resolver conflictos de nombres. Llamadlo de alguna otra forma descriptiva.

Una vez que hemos creado el proyecto, por defecto nos añade una clase llamada ScheduledAgent, que hereda a su vez de la clase ScheduledTaskAgent. Esta clase base nos da métodos que sobre escribir para trabajar con nuestro agente. Por defecto se crea un constructor estático, que se suscribe al evento UnhandledException de la aplicación, y un método OnInvoke.

El método OnInvoke será el que se encargue de ejecutar nuestro código en background. Por defecto en este método vemos que se llama al método NotifyComplete. Este método notifica al sistema que hemos terminado el trabajo y no necesitamos seguir en ejecución. Si no lo llamamos, aunque se termine el método OnInvoke, el sistema no sabrá que hemos finalizado y matará el proceso pasado el tiempo máximo de ejecución.

Ahora vamos a añadir algo de código a nuestro agente, para este ejemplo vamos a actualizar el Live tile de la aplicación con una imagen y textos:

OnInvoke
protected override void OnInvoke(ScheduledTask task)
{
    var appTile = ShellTile.ActiveTiles.First();
    FlipTileData data = new FlipTileData();
    data.BackgroundImage = new Uri("http://...png", UriKind.Absolute);
    data.Title = "custom title";
    data.BackContent = "setting from background agent";
    appTile.Update(data);

    NotifyComplete();
}

A continuación, necesitamos que nuestra aplicación se encargue de registrar este agente. Cada aplicación solo puede tener un proyecto de ejecución en segundo plano. Debido a esta limitación, el sistema usará el ensamblado referenciado en nuestra aplicación como agente, por lo que lo primero que necesitamos hacer es añadir una referencia al agente en nuestra aplicación:

image

Una vez hecho esto, solo nos queda notificar al sistema que tenemos una tarea (periódica o intensiva) y que deseamos registrarla, indicando su nombre, descripción y fecha de caducidad. Como hemos dicho anteriormente, la fecha máxima de caducidad es de 2 semanas:

Background agent registration
private void RegisterBackgroundAgent()
{
    PeriodicTask task = (PeriodicTask)ScheduledActionService.Find("periodic");
    if (task == null)
    {
        task = new PeriodicTask("periodic");
        task.Description = "Periodic task to update app tile.";
        task.ExpirationTime = DateTime.Now.AddHours(1);
        ScheduledActionService.Add(task);
    }

#if DEBUG
    ScheduledActionService.LaunchForTest("periodic", new TimeSpan(0, 0, 30));
#endif
}

Si analizamos el código, podemos encontrar varias partes:

  • En primer lugar usamos la clase ScheduledActionService para buscar una tarea que se llame igual que la nuestra (periodic es un nombre descriptivo para una demo, pero no para una aplicación real, recuerdalo!)
  • Si no existe, la creamos. Aquí tenemos que indicar su nombre, que debe ser único, una descripción y un tiempo de caducidad. Por último añadimos nuestra nueva tarea periódica al ScheduledActionService. El registro de una tarea intensiva es exactamente el mismo, usando la clase ResourceIntensiveTask en lugar de PeriodicTask.
  • Por último, estaría bien poder probar nuestro agente sin tener que esperar media hora delante del emulador. para ello disponemos de un método LaunchForTest dentro de la clase ScheduledActionService. A este método le pasamos el nombre de la tarea que queremos probar y un TimeSpan con el tiempo que queremos que tarde en lanzarla. Si os fijáis, he envuelto esta llamada dentro de una condición de compilación, de forma que solo se ejecute en modo DEBUG. Esto es así porque el método LaunchForTest no puede ser usado en una app publicada, haría que nuestra aplicación fallase la certificación.

Por último, tenemos que ejecutar este código. Yo personalmente suelo ejecutarlo al iniciar la aplicación, al final del método InitializePhoneApplication. El Registro de un agente en background es muy rápido y no afectará al rendimiento, además es un código que no se ejecutará siempre, pues la mayor pate del tiempo la tarea ya estará registrada. En este sentido es importante darle al usuario el control sobre la activación, añadiendo una página de settings donde pueda activar o desactivar el agente.

InitializePhoneApplication
private void InitializePhoneApplication()
{
    if (phoneApplicationInitialized)
        return;

    // Create the frame but don't set it as RootVisual yet; this allows the splash
    // screen to remain active until the application is ready to render.
    RootFrame = new PhoneApplicationFrame();
    RootFrame.Navigated += CompleteInitializePhoneApplication;

    // Handle navigation failures
    RootFrame.NavigationFailed += RootFrame_NavigationFailed;

    // Handle reset requests for clearing the backstack
    RootFrame.Navigated += CheckForResetNavigation;

    // Ensure we don't initialize again
    phoneApplicationInitialized = true;

    RegisterBackgroundAgent();
}

Y listo, si ejecutamos el ejemplo, anclamos la aplicación al inicio y esperamos unos segundos (los que hayamos indicado, 30 en este caso) veremos que nuestro tile se actualiza:

image

Y con esto terminamos la segunda entrega de esta serie. Aquí os dejo el código fuente de este ejemplo, para que lo podáis usar como referencia. En el próximo artículo hablaremos sobre reproducción de música en background.

Un saludo y Happy Coding!

[Windows Phone 8] Ejecución de código en segundo plano (I).

Hola a todos!

Hoy quiero dedicar unas líneas a hablar de la ejecución en segundo plano en Windows Phone 8. ¿Qué son? ¿Como se usan? ¿Qué restricciones tienen?

En Windows Phone 8 disponemos de cuatro opciones para ejecutar código en background:

Geolocalización en background

La primera, geolocalización en background, permite indicar al sistema que necesitamos continuar siguiendo la posición del dispositivo en toda circunstancia. Nuestra aplicación queda “viva” y seguimos recibiendo eventos de posición aunque el usuario haya cambiado a otra app. Pero no es tan bonito como parece, existen ciertas restricciones que pueden hacer que la aplicación se desactive:

  • Si el usuario no la ha usado en menos de 4 horas.
  • Si paramos de seguir la posición.
  • Si se activa el modo de ahorro de batería.
  • Si la memoria del dispositivo es baja.
  • Si otra aplicación empieza a ejecutarse en background.
  • Si el usuario desactiva los servicios de localización.

Algunas de estas situaciones podemos intentar evitarlas, por ejemplo reduciendo el consumo de la aplicación al mínimo con el objetivo de no llenar la memoria del dispositivo. Otras, lamentablemente, están fuera de nuestro control.

Para que nuestra aplicación continúe ejecutándose en background, debemos primero indicarlo al sistema. Esto lo llevaremos acabo en el archivo .xml, en el nodo DefaultTask. Tenemos que añadir el nodo BackgroundExecution:

Background execution
<DefaultTask  Name ="_default" NavigationPage="MainPage.xaml">
  <BackgroundExecution>
    <ExecutionType Name="LocationTracking"/>
  </BackgroundExecution>
</DefaultTask>

A continuación, solo tendremos que desarrollar nuestro código normal y corriente para seguir la posición cuando esta cambie:

GpsService
Geolocator locator = new Geolocator();

public event EventHandler<PositionChangedEventArgs> PositionChanged;

public void StartTrackingLocation()
{
    locator.DesiredAccuracy = PositionAccuracy.High;
    locator.MovementThreshold = 20;
    locator.PositionChanged += locator_PositionChanged;
}

private void locator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
    var tmpHandle = PositionChanged;
    if (tmpHandle != null)
    {
        App.RootFrame.Dispatcher.BeginInvoke(delegate
        {
            tmpHandle(this, args);
        });
    }
}

Y Voila!

Ahora, en nuestro ViewModel vamos a añadir código para que reciba las posiciones y las añada a una lista:

ViewModel principal
public class VMMainPage : VMBase
{
    private IGpsService gpsService;
    private ObservableCollection<string> positions = new ObservableCollection<string>();

    public VMMainPage(IGpsService gpsService)
    {
        this.gpsService = gpsService;
        this.gpsService.PositionChanged += gpsService_PositionChanged;
        this.gpsService.StartTrackingLocation();
    }

    void gpsService_PositionChanged(object sender, Windows.Devices.Geolocation.PositionChangedEventArgs e)
    {
        Positions.Add(string.Format("{0} / {1}", e.Position.Coordinate.Latitude, e.Position.Coordinate.Longitude));
    }

    public ObservableCollection<string> Positions
    {
        get { return positions; }
        set
        {
            positions = value;
            RaisePropertyChanged();
        }
    }
}

No olvides añadir la capability ID_CAP_LOCATION a tu app y ya podrás ejecutarla. Si usas el emulador, podrás ver como al añadir puntos al mapa del simulador GPS, aparecen en una lista en pantalla. Si pruebas a volver al menú inicio, poner un punto de parada en el evento PositionChanged y añadir un nuevo punto, verás como la llamada llega, aunque la aplicación no esté en primer plano.

image

Así de sencillo, podéis hacer una app que siga al dispositivo aun estando en background. Como siempre, aquí podéis descargar el código de ejemplo de la aplicación para que tengáis una guía de como hacer lo que os cuento. Por supuesto, con MVVM, IoC y servicios, “Rico, Rico” jeje.

Espero que este pequeño post os ayude.

Un saludo y Happy Coding!

[Windows Phone 8] Resumen de artículos sobre Windows Phone 8

Para empezar este año 2014 en el blog, creo que es una buena idea hacer un repaso por todos los temas de los que ya hemos hablado acerca de la plataforma. Al final, tras un año de artículos, he escrito sobre muchos temas diferentes que pueden quedar algo perdidos en el blog. Empecemos!

APIs de voz en Windows Phone 8:

En este artículo explico como hacer uso de las APIs de voz: Comandos, Text to Speech y Speech to Text. Todo con un divertido ejemplo!

http://geeks.ms/blogs/jyeray/archive/2012/11/15/windows-phone-8-apis-de-trabajo-con-voz.aspx

Mapas en Windows Phone 8:

En dos artículos, repasamos el nuevo control de mapas de Windows Phone 8, el cálculo de rutas, la geo codificación y la geo codificación inversa.

http://geeks.ms/blogs/jyeray/archive/2012/12/27/nuevo-control-de-mapas-y-calculo-de-rutas-en-windows-phone-8.aspx

http://geeks.ms/blogs/jyeray/archive/2012/12/31/geocodificaci-243-n-y-geocodificaci-243-n-inversa-en-windows-phone-8.aspx

Contactos:

Explico como crear, leer y actualizar contactos en la agenda del dispositivo, creando nuestro propio almacén de contactos.

http://geeks.ms/blogs/jyeray/archive/2013/01/05/windows-phone-8-gesti-243-n-de-contactos.aspx

Asociación de archivos y protocolos:

Una de las novedades estrella de Windows Phone 8, poder asociar protocolos y extensiones de archivo a nuestra aplicación. Con ello conseguimos que cuando un usuario tenga un tipo de archivo concreto o un esquema de protocolo, se lance nuestra aplicación.

http://geeks.ms/blogs/jyeray/archive/2013/01/16/windows-phone-8-asociaci-243-n-de-archivos-y-protocolos.aspx

Fast App Resume:

FAR nos permite conservar siempre una sola instancia de nuestra aplicación abierta, de forma que aunque el usuario pulse sobre el tile de inicio de la aplicación, recuperemos la instancia creada en vez de abrir una nueva.

http://geeks.ms/blogs/jyeray/archive/2013/01/28/windows-phone-8-tip-fast-app-resume.aspx

Compartir código entre Windows Phone 7.X y Windows Phone 8:

Una de las grandes preocupaciones de este pasado año, tener que mantener varias versiones distintas de nuestras apps. En este artículo hablo de los trucos y consejos para escribir código que pueda ser compartido fácilmente.

http://geeks.ms/blogs/jyeray/archive/2013/02/07/windows-phone-8-compartiendo-codigo-en-windows-phone-7-y-windows-phone-8.aspx

Probar nuestras aplicaciones en dispositivos remotos:

Con el incremento del número de dispositivos disponibles en el mercado, probar nuestros desarrollos en todos ellos es una tarea imposible. Nokia pone a nuestra disposición un servicio para acceder a todos sus modelos de dispositivos de forma remota y gratuita.

http://geeks.ms/blogs/jyeray/archive/2013/03/05/windows-phone-8-probando-nuestras-aplicaciones-en-dispositivos-f-237-sicos-remotos.aspx

Interactuando con la pantalla de bloqueo:

Otra de las nuevas APIs que encontramos en Windows Phone 8. Esta nos ofrece la capacidad de poner un contador en la pantalla de bloqueo o incluso de ser proveedores de imágenes para la misma.

http://geeks.ms/blogs/jyeray/archive/2013/03/13/windows-phone-8-interactuando-con-la-pantalla-de-bloqueo.aspx

API Here Places:

No es estrictamente solo para Windows Phone, pero en el artículo explicamos como interactuar con un API REST de forma asíncrona desde Windows Phone 8 y como consumir su contenido. En este caso usando el API Places de Here.

http://geeks.ms/blogs/jyeray/archive/2013/03/27/windows-phone-8-here-places-api.aspx

Evitar problemas al publicar nuestra app para Windows Phone 7 y Windows Phone 8 simultáneamente:

Existen ciertas cosas que debemos tener en cuenta para publicar dos XAP distintos de nuestra aplicación para soportar Windows Phone 7.X y Windows Phone 8. En este artículo explico que hay que saber y como enfrentarnos a lo posibles problemas.

http://geeks.ms/blogs/jyeray/archive/2013/05/14/windows-phone-tip-problemas-al-publicar-para-windows-phone-7-y-para-windows-phone-8.aspx

Validación de datos en Windows Phone 8 y Windows 8:

Un proyecto que podéis obtener en NuGet y que, con el simple uso de un Behavior, nos permite validar los datos de nuestra aplicación de forma sencilla. Además con ejemplos para Windows Phone 8 y Windows 8.

http://geeks.ms/blogs/jyeray/archive/2013/06/16/xaml-tip-validaci-243-n-de-datos-en-windows-phone-8-y-windows-8.aspx

Google Analytics en nuestra aplicación Windows Phone 8:

El primer paso para mejorar es conocer que debemos mejorar. Añadiendo Google Analytics a nuestra aplicación podremos tener una imagen clara del uso que los usuarios hacen de la misma.

http://geeks.ms/blogs/jyeray/archive/2013/07/15/windows-phone-8-a-241-adir-google-analytics-a-nuestras-aplicaciones.aspx

Conseguir reviews para tus aplicaciones:

En este artículo explico como presentar al usuario la opción de valorar nuestra aplicación de forma sencilla y rápida, de forma que consigamos más reviews y valoraciones.

http://geeks.ms/blogs/jyeray/archive/2013/09/19/conseguir-reviews-de-tus-apps-en-windows-phone-8-y-windows-8-x.aspx

Novedades de Windows Phone 8 Update 3 para desarrolladores:

En Octubre se liberó el update 3 d Windows Phone 8 y en esta ocasión nos ofrecía novedades también a los desarrolladores. Sonidos configurables para nuestras notificaciones, nueva resolución…

http://geeks.ms/blogs/jyeray/archive/2013/10/15/windows-phone-8-gdr3-preview-novedades-para-desarrolladores.aspx

Multilingual App Toolkit:

En muchas ocasiones he hablado de lo importante que es tener nuestra aplicación localizada en varios idiomas, para conseguir muchas más descargas, para esto Multilingual App Toolkit nos va a ayudar a hacer el trabajo más sencillo.

http://geeks.ms/blogs/jyeray/archive/2013/11/02/windows-phone-8-multilingual-app-toolkit.aspx

Cimbalino toolkit:

En dos artículos os presentaba este fantástico toolkit para Windows Phone 8. ApplicationBar con soporte para enlace a datos, multitud de servicios y behaviors… Un montón de herramientas para hacernos la vida mucho más fácil.

http://geeks.ms/blogs/jyeray/archive/2013/10/27/windows-phone-8-cimbalino-toolkit-applicationbar-y-servicios.aspx

http://geeks.ms/blogs/jyeray/archive/2013/11/14/windows-phone-8-cimbalino-toolkit-trabajando-con-xaml.aspx

La verdad es que he tocado muchos temas distintos sobre Windows Phone 8 durante este último año y en ocasiones uno se queda sin ideas sobre que escribir o que genera más dudas en la plataforma… Así que tiro la pelota a vuestro tejado. He compartido un libro de excel en mi Skydrive al que podéis entrar y contarme que es lo que os gustaría ver en mi blog. De entre todas las propuestas, sacaré los próximos artículos que veréis publicados:

http://sdrv.ms/1lZTbqh

Espero que todo esto os sea de Utilidad. Un saludo y Happy Coding!!

[OFFTOPIC] Resumen de un gran 2013

Llega el penúltimo día del año y es hora de hacer recuento. 2013 ha sido para mi, sin duda, un gran año. Además, viniendo de un 2012 fantástico, no podía ser menos.

Comencé el año publicando un nuevo libro, con la inestimable ayuda de Rafa Serna, Ibon Landa y José Manuel Alarcón, sobre Windows Phone 8 y Windows 8. Un trabajo de meses y meses que desembocó en 550 páginas de conocimiento arcano sobre la, por aquél entonces, nueva versión de Windows Phone y las aplicaciones Windows Store.

Desarrollo-Windows-8-350

También ha ido el año de los viajes. Desde hace mucho tiempo mi ilusión había sido poder hacerme un viajecito a Estados Unidos. Por una razón u otra, nunca pude hacerlo… hasta este año. En 2013 no pude ir una vez, si no tres, a USA.

En febrero pude asistir a mi primer MVP Summit, en Seattle, WA. Además pude compartir la experiencia con mi preciosa mujer, que se quedó enamorada de la ciudad:

seattle 1

La foto anterior está tomada desde el restaurante del Space Needle por la noche, donde fuimos a cenar el día de San Valentín. Una experiencia increíble.

En Junio pude volver de nuevo, esta vez a San Francisco, CA, para el Build 2013. Pero como no solo de trabajo vive el hombre, junto a Javier Arratibel, Sergio y Rafa Serna, nos hicimos un tour por Sillicon Valley, acabando en el garaje donde nació Apple:

WP_20130625_030

Y por último en Noviembre, segundo MVP Summit del año… este 2013 ha ido especial. Microsoft cambió las fechas del Summit de Febrero a Noviembre y nos tocó volver (no por que quisiésemos eh?)

WP_20131109_15_13_37_Pro

La verdad es que Seattle es un sitio único, este último viaje pude estar dos semanas y aprovechar para conocer mucho mejor toda la ciudad y visitar a algunos amigos que están por esos lares.

Otro punto importante de este 2013 lo he vivido profesionalmente. Tras 3 años en Plain Concepts, una empresa genial llena de gente muy muy buena técnica y personalmente, donde dejé muchos amigos, cambié para enfocarme un poco más en Windows Phone. Icinetic me ofreció una oportunidad que no podía rechazar y desde Octubre estoy trabajando codo con codo con Javier Suarez, Pedro Molina, Rafael Agudo y Jonathan Cáceres entre otros. Un magnífico equipo con el que estoy disfrutando mucho y haciendo cosas realmente divertidas.

Además de escribir 43 artículos sobre Windows Phone en el blog y hacer cerca de 12 eventos, llegando al final de este 2013, junto a Rafa, Santi y Javier he montado WPSUG: El primer grupo hispano de usuarios de Windows Phone y hemos realizado el primer hangout de los muchos que traerá 2014.

Logo-512

Y esto ha sido mi 2013 a grandes rasgos. Mucha diversión, objetivos cumplidos y mucho trabajo por delante. Para 2014 ya estoy trabajando en nuevas sorpresas para la comunidad, mucho material por escribir y cosas que os sorprenderán sin duda… pero no puedo decir nada más por ahora.  Solo desearos Feliz año nuevo y que el 2014 sea, por lo menos, tan bueno como este 2013 que se acaba.

Un saludo y Happy Coding!

Publicado por Josué Yeray Julián Ferreiro con no comments
Archivado en: ,,

[COMUNIDAD] WPSUG: Windows Phone Spanish User Group

Hola a todos!

Desde hace algún tiempo vengo trabajando con Javier Suarez Ruiz, Rafael Serna y Santiago Porras en la creación de una nueva comunidad de Windows Phone. Hoy por fin ve la luz públicamente. Estoy hablando de WPSUG: Grupo de usuarios hispanos de Windows Phone.

Logo-512

Desde principios de año, junto con Oscar Gutiérrez, había creado una comunidad Google+ para desarrolladores. Ha tenido muy buena acogida, con más de 420 miembros. En ella cualquiera puede colgar artículos, preguntas, materiales… Pero queríamos darle un nuevo empujón. Aprovechando la tecnología de Hangouts de Google y su integración con G+, hemos decidido poner en marcha este grupo de usuarios, añadiendo a todo lo anterior la realización de webcasts periódicos sobre desarrollo, incluso organizar algún evento presencial que nos permita conocernos.

Los principios de esta comunidad son muy sencillos:

  • Todos colaboramos: Cualquier persona puede unirse a la comunidad, subir contenido, materiales y preguntar o contestar dudas.
  • No solo de desarrollo vive el hombre: Si tienes una noticia sobre Windows Phone interesante, adelante, aunque no sea de desarrollo será bienvenida.
  • Queremos aprender: Nadie es perfecto y nadie sabe todo, así que nos encantaría que la gente se animase a participar en los hangouts.

¿Como hacemos todo esto? Bueno, hemos abierto canales de YouTube, cuentas de Twitter, una lista de correo y nuestra web principal, basada en Google+:

Además, para comenzar con buen pie, el 30 de este mes realizaremos un primer hangout de presentación, en el que estaremos Javier, Rafa, Santy y yo dándole un repaso al 2013 y comentando que esperamos del 2014. Puedes apuntarte para seguirnos aquí:

https://plus.google.com/events/c40eihnjuice0fo7kvavml6aqg0?authkey=CIOqqr_chvXXcA

Espero que os guste la idea y que nos acompañéis en esta aventura que comenzamos.

Un saludo y Happy Coding!

[MATERIALES] Webcast Toolkits: Cimbalino y Multilingual App Toolkit

Hola a todos!

El pasado viernes 13 de Diciembre estuve en otro webcast de las Christmas Windows Phone Sessions, en esta ocasión sobre Cimbalino toolkit y Multilingual App Toolkit. Estos dos toolkits nos ahorran mucho trabajo en nuestro desarrollo del día a día y tienen grandes ventajas. En este blog tengo algunos artículos sobre ellos, que podéis consultar en busca de ejemplos y más explicaciones:

Multilingual App Toolkit

Cimbalino Toolkit (1/2)

Cimbalino Toolkit (2/2)

Y aquí os dejo los materiales del evento, la presentación en SlideShare:

Y el enlace al vídeo del webcast, para que podáis verlo de nuevo:

https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032572342&Culture=es-ES&community=0

Un saludo y Happy Coding!

[MATERIALES] Webcast Efectos alucinantes con Nokia Imaging SDK 1.0

Hola a todos!

El pasado viernes 13 de Diciembre estuve en otro webcast de las Christmas Windows Phone Sessions, en esta ocasión sobre Nokia Imaging SDK 1.0. Esta versión final del kit de efectos y trabajos con imágenes de Nokia ha traído muchos cambios, nuevos filtros y una arquitectura totalmente renovada. En el webcast pudimos dar un repaso por estos puntos, ver algunos efectos en acción y el nuevo modelo de deshacer infinito.

Y aquí os dejo los materiales del evento, para que tengáis alguna referencia a la hora de empezar a trabajar con este SDK de los Finlandeses.

En primer lugar, las slides del webcast:

También el ejemplo que usé para enseñaros código, y así podéis tener un punto de partida:

Y por último pero no menos importante, el enlace al video grabado del webcast:

https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032572324&Culture=es-ES&community=0

Espero que disfrutéis tanto como yo haciendo este webcast.

Un saludo y Happy Coding!

Más artículos Página siguiente >