Extendiendo el código generado en Windows Phone App Studio

Introducción

Previamente ya habíamos hablado de Windows Phone App Studio, nueva herramienta online creada por Microsoft que permite crear aplicaciones de calidad para Windows Phone 8 en cuestión de minutos.

App Studio

App Studio

Entre sus principales características hay muchas destacables:

  • Permite crear aplicaciones Windows Phone sin tener conocimientos de desarollo.
  • Las Aplicaciones se generan en código nativo.
  • Permite instalar directamente la Aplicación sin requerir cuentas extras de ningun tipo.
  • Permite compartir la Aplicación creada con amigos.

Sin embargo, la característica principal del sistema, es que puedes descargar el código fuente de la Aplicación. Esto permite extender el código fuente añadiendo nuevas características. En esta entrada vamos a analizar la estructura y técnicas utilizadas en el código generado asi como aprener como extenderlo con facilidad.

¿Te apuntas?

Echemos un vistazo al código…

Una vez generamos nuestra Aplicación desde Windows Phone App Studio veremos una pantalla similar a la siguiente:

Código Fuente

Código Fuente

Desde este apartado podemos:

  • Instalar nuestra Aplicación en un dispositivo para probarla de manera fácil leyendo un simple código QR.
  • Compartir vía email nuestra Aplicación con amigos.
  • Descargar el paquete de publicación (el XAP ya empaquetado listo para publicar).
  • Y por último, podemos descargar el código fuente!

Descargamos el código fuente de nuestra Aplicación:

El código fuente viene empaquetado en un zip

El código fuente viene empaquetado en un zip

Descomprimimos y abrimos la solución (Solution.sln) en Visual Studio.

NOTA: El proyecto es una solución para Windows Phone 8 que requiere Visual Studio 2012.

Estructura

Estructura

De un primer vistazo a la estructura de la solución podemos ver que la solución esta organizada en diferentes proyectos:

  • WP8App: Este proyecto es la Aplicación Windows Phone 8 en si. Implementa el patrón MVVM junto a otras técnicas y buenas prácticas (Ioc, servicios, etc) de los que hablaremos con calma más adelante.
  • Entities: Entidades utilizadas en la Aplicación. Las entidades implementan una iterfaz BindableBase que es una implementación de la interfaz INotifyPropertyChanged.
  • Repositories: En este proyecto tenemos disponibles todos repositorios de información utilizados por la Aplicación.

Esta separación de responsabilidades en proyectos independientes nos permite extender con mayor facilidad cada una de las partes implicadas asi como la creación de test unitarios que se encargen de asegurar la calidad y funcionamiento de todo.

Profundizamos en la estructura del proyecto Windows Phone:

WP8App

WP8App

Lo primero que llama la atención a simple vista es la implementación del patrón MVVM en el proyecto. Model-View-ViewModel (MVVM) es un patrón de diseño de aplicaciones que permite desacoplar el código de interfaz de usuario del código que no sea de interfaz de usuario.

El patrón MVVM se compone de tres partes fundamentales:

  • La Vista (View): Define las vistas de la aplicación, es decir, conjunto de controles, layout, estilos, etc. Se nutre del vista-modelo utilizando su propiedad DataContext. Los controles se configuran mediante propiedades expuestas por el vista-modelo e interactuan mediante el uso de comandos. Todas las vistas están situadas dentro de la carpeta View.
  • El Vista-Modelo (ViewModel): Conjunto de clases que encapsulan la lógica de presentación. Implementa propiedades y comandos a los que se asociará la vista. Controla la interacción de la vista con el modelo. Todos los viewmodels están organizados dentro de la carpeta ViewModel.
  • El Modelo (Model): Conjunto de clases que encapsulan los datos de la aplicación junto a su lógica de negocio. Validan el modelo de los datos aplicando reglas de negocio. El modelo suele implementar las interfaces INotifyPropertyChanged y INotifyCollectionChanged para notificar cambios en propiedades y colecciones. No deben referenciar a la vista ni al vista-modelo. En nuestra solución, tenemos los modelos dentro del proyecto Entities (recordar que implementan la interfaz) .

A vista de pájaro ya hemos analizado la estructura del proyecto, sin embargo, creo que merece la pena que pronfundizemos más.

Con el objetivo en mente se poder extender y reutilizar el código en la medida de lo posible, se evita añadir código específico de la plataforma en los viewmodels. No podemos utilizar directamente APIs de Windows Phone en nuestros viewmodels.

¿Porque?

Hay varios motivos para ello. Por ejemplo, si queremos portar la Aplicación a Windows 8 utilizaremos una Portable Library. Los viewmodels son candidatos perfectos para migrar a la clase portable pero no podemos hacerlo con código específico de la plataforma.

¿Cómo lo conseguimos?

Las operaciones que necesitemos en nuestra aplicación que requieran acceder a las APIs de Windows Phone las implementaremos en servicios. Podemos encontrar los servicios en la carpeta Services del proyecto.

Dependiendo de los extras y otro tipo de configuraciones aplicadas en el portal durante el proceso de creación de la Aplicación, podemos contar con los siguientes servicios:

  • DialogService. Lo utilizamos para mostrar notificaciones en nuestra aplicación mediante Messagebox.
  • LiveTileService. El nombre deja pocas dudas. Lo utilizamos para la gestión de tiles en la aplicación, crear y eliminar tiles secundarios.
  • NavigationService. Utilizamos el servicio NavigationService para realizar la navegación entre páginas.
  • ReminderService. Nos permite crear recordatorios.
  • ShareService. Nos permite compartir información (Lanzador EmailComposeTask).
  • LockScreenService. Nos permite modificar la imagen utilizada en la LockScreen.
  • SpeechService. Nos permite utilizar TTS en nuestra Aplicación.
  • WebBrowserService. Abre una URL en el navegador (Lanzador WebBrowserTask).

Los viewmodels implementan los servicios gracias al uso de Ioc (Inversion of Control) por DI (Dependency Injection). Se crea un contenedor donde registramos todos los servicios que vamos a utilizar junto a los viewmodels que utilizarán las vistas y que accederán a los servicios utilizando interfaces.

Para ello, se utiliza Unity v2.1, el contenedor IoC de Patterns & Practices. Contamos con un service locator (ViewModelLocator) que utilizará el contenedor creado. Está instanciado en App.xaml y se utiliza para que cada vista pueda acceder a la instancia de su viewmodel correspondiente cada vez que lo necesite. Los viewmodels a su vez  accederán a los servicios utilizando interfaces.

Llegados a este punto y tras analizar la estructura y técnicas utilizadas en el código generado de nuestra aplicación podemos deducir que:

  • El código generado implementa el patrón MVVM y utiliza conceptos y buenas prácticas como Ioc, servicios o la abstracción de implementaciones gracias a interfaces creando un código de calidad, además facilmente extensible.
  • El código viene en líneas generables perfectamente preparado para implementar test con facilidad o utilizar Portable Library y migrar nuestra aplicación a otras plataformas.
  • Para enriquecer nuestras vistas se utilizan algunas de las herramientas más conocidas en el entorno de desarrollo Windows Phone como el Toolkit o MyToolkit. Para  facilitar la gestión de dichas librerías se incluyen paquetes NuGet.

Asi que, analizada la estructura del código generado, ¿que tal si lo extendemos?

Extendiendo el código

Manos a la obra. Vamos a extender el código de la Aplicación generada. Para probar las múltiples opciones a realizar, vamos a:

  • Modificar uno de los servicios ya existentes para modificar la implementación del mismo.
  • Añadir un nuevo servicio que añada nueva funcionalidad a al Aplicación.

Comenzamos modificando uno de los servicios existentes. Nos centramos por ejemplo en el servicio DialogService  que utilizamos para mostrar notificaciones en nuestra aplicación mediante Messagebox:

public class DialogService : IDialogService
{
     public void Show(string message)
     {
          MessageBox.Show(message);
     }

     public void Show(string message, string caption)
     {
          MessageBox.Show(message, caption, MessageBoxButton.OK);
     }
}

Contamos con las librerías del Windows Phone Toolkit incluidas en el proyecto. Por lo tanto, podemos extender el servicio utilizando un control más versátil como el CustomMessageBox perteneciente al Toolkit. Para ello, en la misma clase, añadimos la referencia necesaria para poder utilizar el control:

using Microsoft.Phone.Controls;

Reemplazamos la lógica de cada método:

public void Show(string message)
{
     CustomMessageBox messageBox = new CustomMessageBox()
     {
          Message = message
     };

     messageBox.Show();
}

public void Show(string message, string caption)
{
     CustomMessageBox messageBox = new CustomMessageBox()
     {
          Caption = caption,
          Message = message
     };

     messageBox.Show();
}

Fácil, ¿verdad?. Por supuesto, podemos añadir más métodos al servicio (recordar en dicho caso incluirlas en la interfaz) permitiendo confgurar el botón derecho, el botón izquierdo, el contenido del mensaje (en este control tenemos muchas posibilidades como por ejemplo incluir hasta un Pivot como contenido), etc.

De acuerdo, hemos modificado algo bastante simple. ¿Que pasa si deseamos añadir nueva funcionalidad a la ya existente?. No dista mucho de lo ya realizado. Vamos a añadir un nuevo servicio. Una acción bastante común en Aplicaciones Windows Phone que acceden a información alojada en un servidor suele ser cachear la información. Para ello, una buena opción es utilizar el Isolated Storage.

Como el acceso al Isolated Storage es una funcionalidad específica de la plataforma… si, efectivamente, va a los servicios. Creamos entonces un servicio llamado StorageService.

Creamos la interfaz que define al servicio:

public interface IStorageService
{
     T Load<T>(string fileName);
     bool Save<T>(string fileName, T data);
}

Como podéis ver muy sencilla. Tendrá un método Load que pasado un  nombre de achivo devolverá la información almacenada y otro método Save que tendrá como parámetros el nombre del archivo junto a la información a almacenar.

Implementamos la interfaz:

public class StorageService : IStorageService
{

}

Creamos la clase que implementa la interfaz:

public T Load<T>(string fileName)
{
     using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
     {
          if (!myIsolatedStorage.FileExists(fileName))
               return default(T);

          using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile(fileName, FileMode.Open))
          {
               var xml = new XmlSerializer(typeof(T));
               T data = (T)xml.Deserialize(stream);
               return data;
          }
     }
}

public bool Save<T>(string fileName, T data)
{
     try
     {
          using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
          {
               using (IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(fileName))
               {
                    var xml = new XmlSerializer(typeof(T));
                    xml.Serialize(fileStream, data);
               }
          }

          return true;
     }
     catch
     {
          return false;
     }
}

El siguiente paso necesario será el registrar este servicio en nuestro contenedor de Ioc:

_currentContainer.RegisterType<IStorageService, StorageService>();

Por último, podemos utilizar nuestro servicio en un viewmodel por ejemplo muy facilmente:

private IStorageService _storageService;

En el contructor instanciamos los servicios:

public TheTeam_AlbumViewModel(IDialogService dialogService, INavigationService navigationService,
ILockScreenService lockScreenService, ITheGuysCollection theGuysCollection,
IawardsCollection awardsCollection, IvideosDataSource videosDataSource,
IblogDataSource blogDataSource, IStorageService storageService)
{
     _dialogService = dialogService;
     _navigationService = navigationService;
     _lockScreenService = lockScreenService;
     _theGuysCollection = theGuysCollection;
     _awardsCollection = awardsCollection;
     _videosDataSource = videosDataSource;
     _blogDataSource = blogDataSource;
     _storageService = storageService;
}

Y lo podemos utilizar por ejemplo, al obtener una colección de elementos:

_storageService.Save<ObservableCollection<RssSearchResult>>("Blog_NewsListControlCollection", Blog_NewsListControlCollection);

De esta forma podemos almacenar en el almacenamiento aislado la información del servidor. Si el usuario vuelve inmediatamente a ver la misma información pdríamos recueperar la existente en lugar de volver a realizar la petición al servidor.

Podéis echarle un vistazo al código generado (asi como las extensiones realizadas) a continuación:

En definitiva, el tener acceso al código nativo nos permite extender el código a nuestras propias necesidades.

Conclusiones

El código generado implementa el patrón MVVM y utiliza conceptos y buenas prácticas como Ioc, servicios o la abstracción de implementaciones gracias a interfaces creando un código de calidad que como hemos podido verificar es facilmente extensible.

En las plantillas de Visual Studio para Windows Phone se está extendiendo el uso del patrón MVVM junto a otras buenas prácticas. Que el código generado por Windows Phone App Studio haga uso de todas las buenas prácticas y recomendaciones en el desarrollo Windows Phone es un punto positivo que permite no solo ayudar a cualquier usuario a crear su Aplicación para Windows Phone sino contribuir también en el aprendizaje en el desarrollo de la plataforma mostrando los beneficios de estas técnicas desde el principio.

Keep Pushing!

Más información

10 pensamientos en “Extendiendo el código generado en Windows Phone App Studio

  1. Una pregunta….
    Una vez generada la App con esta herramienta, he entendido que se puede cambiar/agregar código extra para completar la aplicación desde por ejemplo Visual Studio 2012, no es así???. Entiendo que si, pero … como poder instalar esta App modificada en mi móvil o poder compartir esta aplicación con otros sin pasar por la Store???

    • Sin pasar por la Store no es posible, solo si pasas a otro desarrollado que tenga cuenta en la store. Que confirme otra persona, antes era así…

      • Me encanta que haya cooperación en los comentarios. Muchas gracias!
        Ya conteste también a Jesus, echa un vistazo a la respuesta y si tienes alguna duda ya sabes😉

    • Hola Jesus,

      Efectivamente una vez generada una Aplicación con Windows Phone App Studio puedes descargar el código fuente y modificarlo.
      La Aplicación generada por Windows phone App Studio puedes instalarla en tu teléfono directamente sin tener que publicar en la Store con tan solo instalarte el certificado de App Studio (con tan solo leer un código QR!).
      Esa misma Aplicación puedes compartirla con tus amigos que podrían probar la Aplicación de la misma forma (instalando certificado de App Studio) sin la necesidad de pasar por la Store.

      Si descargas el código fuente y lo modificas, para distribuirla necesitas pasar por la Windows Phone Store. La única opción alternativa que tienes es utilizar la distribucion empresarial.
      Te puede interesar el siguiente artículo donde hablamos de la distribución empresarial: https://javiersuarezruiz.wordpress.com/2013/04/29/windows-phone-8-distribucion-empresarial/

      De todas formas, ahora es buen momento para lanzar tus Aplicaciones en la Store ya que hay oferta: https://javiersuarezruiz.wordpress.com/2013/07/01/oferta-windows-phone-dev-center/

      Espero haber podido resolver tus dudas😉

      Un saludo!

      • Gracias por tu pronta respuesta ….
        Soy seguidor tuyo, vamos de tu Blog …. jajajaja!!!!!, desde hace tiempo y me parecen interesantísimos la mayoría de tus artículos.
        Siguiendo con este tema, el de publicar aplicaciones en la Store de Microsoft, el ‘problema’ que tengo es que me apetece ‘liar’ con mi nuevo Lumia 920, es decir, quiero hacer mis programitas caseros e ir probando cositas sin tener que pasar por las manos de Microsoft, no existe alternativa a esto????? ….

      • Hola Jesús,

        Encantado que sigas el blog🙂. Espero que los artículos te vayan resultando interesantes. Me temo que no hay opción alternativa. Hace un tiempo era posible realizar tus pruebas sin cuenta de desarrollador liberando el teléfono con ChevronWP7 a un precio muy económico. Actualmente lo más económico es usar la cuenta de desarrollador que tiene un coste anual. Sin embargo, el precio actual de la cuenta de desarrollo es muy atractivo: https://javiersuarezruiz.wordpress.com/2013/07/01/oferta-windows-phone-dev-center/
        Y seguro que le sacas provecho!. Si podemos ser de ayuda, aqui estamos😉

        Un saludo.

  2. Javier, que buena noticia para los desarrolladores novatos en la plataforma WP

    Ayer he tenido que renovar mi cuenta para Windows Store y al parecer bajaran los precios… Pague 37 euros en lugar de los 99 dolares iniciales.

    • Hola Javier…. excelente noticia la de poder unlock tu dispositivo y debuggear tus Apps directamente en él … Lo has probado??? … Esperando un buen tutorial testeado por alguien de confianza.
      Saludos

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s