Generation Apps – Día 22 – Implementar agentes de segundo plano en tu aplicación

Los agentes de segundo plano y las tareas programadas realizan tareas en segundo plano, aun si la aplicación de primer plano no esta abierta. Los diferentes tipos de tareas programadas están diseñadas para los diferentes tipos de situaciones de proceso de segundo plano y por eso tienen diferentes comportamientos y restricciones. Aprende como implementar una aplicación que usa una tarea programada para registrar un agente de segundo plano. También entenderás la programación, duración y limitaciones de las tareas programadas.

Creando una aplicación que usa Tareas Programadas

Para crear una aplicación que usa tareas programadas, debes seguir los siguientes pasos:

  1. En Visual Studio, crea un nuevo proyecto Aplicación Windows Phone. Esta plantilla se encuentra en la categoría de Silverlight para Windows pone

  2. Ahora, agrega un proyecto de tipo Tarea Programada a tu solución. Del menú Archivo, selecciona Agregar -> Nuevo Proyecto. En la ventana de dialogo de Agregar Nuevo proyecto, selecciona Agente de Tareas Programadas Windows Phone. Deja el nombre por defecto, ScheduledTaskAgent1, y da clic a OK.

  3. En tu proyecto de primario, debes agregar una referencia hacia el proyecto tipo Agente. En el explorador de soluciones, realiza un clic derecho sobre el proyecto principal, y da clic a «Agregar Referencia…» y en la ventana de dialogo de Agregar Referencias, selecciona la pestana de Proyectos. Selecciona el proyecto tipo Agente, ScheduledTaskAgent1, y da clic a OK.

  4. En el explorador de soluciones, da doble clic a ScheduledAgent.cs del proyecto ScheduledTaskAgent1 para abrir el archivo. Veras que este archivo contiene la definición de una clase ScheduledAgent, el cual hereda la clase base ScheduledTaskAgent. Para este ejemplo, agrega la siguiente directiva para el namespace Shell y Sistema al tope del archivo.

    using Microsoft.Phone.Scheduler;
    using Microsoft.Phone.Shell;
    using System;
  5. Hay un método implementado en la clase, OnInvoke(ScheduledTask). Este método es invocado por el sistema operativo cuando la Tarea Programada es ejecutada. Aquí es donde deberías implementar el código que desees que se ejecute cuando el agente de segundo plano se ejecute. Cada aplicacion puede tener un solo ScheduledTaskAgent registrado a la vez, pero puedes programar este agente como un tipo de agente recurso-intensivo y periódico. Si tu aplicación usa ambas tareas ResourceIntensiveTask y PeriodicTask, puedes verificar que tipo de objetoScheduledTask que es pasado al método OnInvoke para determinar cual tarea el agente esta siendo invocado y ramificar tu ejecución de código como desees. Si utilizas un solo tipo de agente, no necesitaras revisar el tipo de objeto ScheduledTask. En este ejemplo, el agente ejecuta un objeto ShellToast desde OnInvoke, indicando el tipo de rarea programada para al agente que fue llamado. Este Toast te mostrara cual agente se esta ejecutando. Sin embargo, no se mostrara mientras que la aplicación se encuentre en modo foreground. Cuando el código de la tarea programada se haya completado, deberás invocar NotifyComplete()para informarle al sistema operativo que ya no necesitas seguir ejecutándolo. Esto permite al sistema operativo lograr gestionar otros agentes programados.

    protected override void OnInvoke(ScheduledTask task)
    {
      //TODO: Add code to perform your task in background
      string toastMessage = "";
    
      // If your application uses both PeriodicTask and ResourceIntensiveTask
      // you can branch your application code here. Otherwise, you don't need to.
      if (task is PeriodicTask)
      {
        // Execute periodic task actions here.
        toastMessage = "Periodic task running.";
      }
      else
      {
        // Execute resource-intensive task actions here.
        toastMessage = "Resource-intensive task running.";
      }
    
      // Launch a toast to show that the agent is running.
      // The toast will not be shown if the foreground application is running.
      ShellToast toast = new ShellToast();
      toast.Title = "Background Agent Sample";
      toast.Content = toastMessage;
      toast.Show();
    
      // If debugging is enabled, launch the agent again in one minute.
    #if DEBUG_AGENT
      ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));
    #endif
    
      // Call NotifyComplete to let the system know the agent is done working.
      NotifyComplete();
    }
  6. Ahora en los siguientes pasos, la aplicación de primer plano es modificada para permitir a los usuarios para habilitar y deshabilitar los agentes periódicos y recurso-intensivos. Primero abre el archivo MainPage.xamly pega el siguiente código XAML dentro del Grid «ContentPanel»

    Este código agrega dos conjuntos de controles, uno para cada tipo de agente. La mayoría de los controles son text blocks que estarán enlazados con los objetos ScheduledTask que representan los agentes de segundo plano, permitiéndote observar las propiedades de estos objetos. Además, un check box es agregado por cada tipo de agente que muestra y permite que el usuario habilite o deshabilite el estado de cada agente. Manejadores de eventos Checked y Unchecked, los cuales son utilizados para apagar y prender los agentes.

  7. En MainPage.xaml.cs, agrega la siguiente directiva en el tope de la pagina:

    using Microsoft.Phone.Scheduler;
  8. Crea dos variables que representaran cada tipo de agente. Estos serán objetos que estarán enlazados a la interfaz de usuario. El servicio de acción programada identifica únicamente tareas programadas por su propiedad Name (Nombre). Crea dos variables conteniendo los nombres que se usaran para los agentes.  Crea una variable booleana para usar como determinar si algún agente de segundo plano haya sido deshabilitado por el usuario final. Agrega las siguiente líneas de código dentro de la definición de la clase:

    public partial class MainPage : PhoneApplicationPage
    {
      PeriodicTask periodicTask;
      ResourceIntensiveTask resourceIntensiveTask;
    
      string periodicTaskName = "PeriodicAgent";
      string resourceIntensiveTaskName = "ResourceIntensiveAgent";
      public bool agentsAreEnabled = true;
  9. Ahora, implementa un método helper llamado StartPeriodicAgent. Este método primero usa un método Find(String) para obtener la referencia de la tarea periódica con el nombre especificado. Si el objeto de tarea programada no es null, entonces podrás invocar Remove(String) para excluir el registro del sistema. No puedes actualizar agentes directamente. Deberás remover y luego agregar. Luego, crea un nuevo objeto PeriodicTask y asignar su nombre en el constructor.

    Ahora establece la propiedad Descripción. Esta propiedad es requerida para agentes periódicos y es usado para describir el agente al usuario en la pagina de configuración de tareas de segundo plano en el dispositivo. Luego, invoca Add(ScheduledAction) para registrar el agente periódico  en el sistema. Una excepción InvalidaOperationException  es lanzado cuando Add es invocado si el usuario ha deshabilitado agentes de segundo plano por la aplicación, por ende es importante utilizar un bloque try. Si la llamada es exitosa, establece el contexto de datos del elemento de la interfaz de usuario asociada y mostrar las propiedades del objeto al usuario. Si la llamada lanza una excepción, verifica el mensaje de la excepción. Si el mensaje dice «BNS Error: The action is disabled», entonces deberías alertar al usuario que los agentes de segundo plano están deshabilitados.El método LaunchForTest(String, TimeSpan) es incluido para ejecutar el agente un minuto después que este método es invocado.  Antes de la llamada anterior a este método, se coloca un bloque #If para permitir que la aplicación se intercambie fácilmente entre modos de depuración y producción. Para habilitar este método, incluye la siguiente línea al tope de MainPage.xaml.cs:

    #define DEBUG_AGENT

    Ahora pega el siguiente método en la definición de la clase MainPage

    private void StartPeriodicAgent()
    {
      // Variable for tracking enabled status of background agents for this app.
      agentsAreEnabled = true;
    
      // Obtain a reference to the period task, if one exists
      periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;
    
      // If the task already exists and background agents are enabled for the
      // application, you must remove the task and then add it again to update 
      // the schedule
      if (periodicTask != null)
      {
        RemoveAgent(periodicTaskName);
      }
    
      periodicTask = new PeriodicTask(periodicTaskName);
    
      // The description is required for periodic agents. This is the string that the user
      // will see in the background services Settings page on the device.
      periodicTask.Description = "This demonstrates a periodic task.";
    
      // Place the call to Add in a try block in case the user has disabled agents.
      try
      {
        ScheduledActionService.Add(periodicTask);
        PeriodicStackPanel.DataContext = periodicTask;
    
        // If debugging is enabled, use LaunchForTest to launch the agent in one minute.
    #if(DEBUG_AGENT)
        ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(60));
    #endif
      }
      catch (InvalidOperationException exception)
      {
        if (exception.Message.Contains("BNS Error: The action is disabled"))
        {
          MessageBox.Show("Background agents for this application have been disabled by the user.");
          agentsAreEnabled = false;
          PeriodicCheckBox.IsChecked = false;
        }
    
        if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
        {
          // No user action required. The system prompts the user when the hard limit of periodic tasks has been reached.
    
        }
        PeriodicCheckBox.IsChecked = false;
      }
      catch (SchedulerServiceException)
      {
        // No user action required.
        PeriodicCheckBox.IsChecked = false;
      }
    }

    NOTA: Agentes de segundo plano no son soportados en dispositivos de 256-MB de memoria RAM. Al intentar  trabajar con agentes en estos dispositivos arrojaran una excepción InvalidaOperationException. En lugar de manejar esta excepción en un bloque catch, tu aplicación debería verificar si se esta ejecutando en un dispositivo 256-MB antes de agregar un agente.

  10. Ahora implementaremos el método helper para la tarea tipo recurso-intensivo. Este método es idéntico al método para el agente periódico a excepción que este utiliza la clase ResoucerIntensiveTaskpara programar el agente y otro nombre es utilizado.

    private void StartResourceIntensiveAgent()
    {
      // Variable for tracking enabled status of background agents for this app.
      agentsAreEnabled = true;
    
      resourceIntensiveTask = ScheduledActionService.Find(resourceIntensiveTaskName) as ResourceIntensiveTask;
    
      // If the task already exists and background agents are enabled for the
      // application, you must remove the task and then add it again to update 
      // the schedule.
      if (resourceIntensiveTask != null)
      {
        RemoveAgent(resourceIntensiveTaskName);
      }
    
      resourceIntensiveTask = new ResourceIntensiveTask(resourceIntensiveTaskName);
    
      // The description is required for periodic agents. This is the string that the user
      // will see in the background services Settings page on the device.
      resourceIntensiveTask.Description = "This demonstrates a resource-intensive task.";
    
      // Place the call to Add in a try block in case the user has disabled agents.
      try
      {
        ScheduledActionService.Add(resourceIntensiveTask);
        ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;
    
        // If debugging is enabled, use LaunchForTest to launch the agent in one minute.
    #if(DEBUG_AGENT)
        ScheduledActionService.LaunchForTest(resourceIntensiveTaskName, TimeSpan.FromSeconds(60));
    #endif
      }
      catch (InvalidOperationException exception)
      {
        if (exception.Message.Contains("BNS Error: The action is disabled"))
        {
          MessageBox.Show("Background agents for this application have been disabled by the user.");
          agentsAreEnabled = false;
    
        }
        ResourceIntensiveCheckBox.IsChecked = false;
      }
      catch (SchedulerServiceException)
      {
        // No user action required.
        ResourceIntensiveCheckBox.IsChecked = false;
      }
    }
  11. Agrega una variable booleana a la clase, ignoreCheckBoxEvents. Esta variable será utilizada para habilitar o deshabilitar los eventos de CheckBox al inicializar la pagina.

    bool ignoreCheckBoxEvents = false;
  12. Ahora, agrega manejadores de eventos Checked y Unchecked para los controles CheckBox. Estos manejadores invocan los métodos Start y Stop previamente implementados, para ejecutar y detener los agentes. Si ignoreCheckBoxEvents esta en verdadero, los manejadores de eventos serán retornados sin realizar ninguna función.

    private void PeriodicCheckBox_Checked(object sender, RoutedEventArgs e)
    {
      if (ignoreCheckBoxEvents) 
        return;
      StartPeriodicAgent();
    }
    private void PeriodicCheckBox_Unchecked(object sender, RoutedEventArgs e)
    {
      if (ignoreCheckBoxEvents)
       return;
      RemoveAgent(periodicTaskName);
    }
    private void ResourceIntensiveCheckBox_Checked(object sender, RoutedEventArgs e)
    {
      if (ignoreCheckBoxEvents)
        return;
      StartResourceIntensiveAgent();
    }
    private void ResourceIntensiveCheckBox_Unchecked(object sender, RoutedEventArgs e)
    {
      if (ignoreCheckBoxEvents)
        return;
      RemoveAgent(resourceIntensiveTaskName);
    }
  13. El método RemoveAgent simplemente invoca Remove(String) dentro de un bloque Try para evitar que alguna excepción altere el comportamiento de la aplicación.

    private void RemoveAgent(string name)
    {
      try
      {
        ScheduledActionService.Remove(name);
      }
      catch (Exception)
      {
      }
    }
  14. El paso final es hacer override el método OnNavigatedTo(NavigationEventArgs) de la clase PhoneApplicationPage. Este método es invocado cada vez que el usuario navega a esta pagina. Ahora debes asignar la variable booleana ignoreCheckBoxEvents

    a verdadero para que los manejadores de eventos de los CheckBox estén esencialmente deshabilitados. Luego, usa el método Find(string) para verificar por agentes tipo periódico o recurso-intensivo registrados en el sistema y actualizar los controles CheckBox para reflejar el estado actual de la aplicación. Finalmente, asigna el valor de la variable ignoreCheckBoxEventsa falso.

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
      ignoreCheckBoxEvents = true;
    
      periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;
    
      if (periodicTask != null)
      {
        PeriodicStackPanel.DataContext = periodicTask;
      }
    
      resourceIntensiveTask = ScheduledActionService.Find(resourceIntensiveTaskName) as ResourceIntensiveTask;
      if (resourceIntensiveTask != null)
      {
        ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;
      }
    
      ignoreCheckBoxEvents = false;
    }

Fuente:
How to: Implement Background Agents for Windows Phone

Generation Apps – Día 21 – Acceder a la secuencia de imágenes de la cámara

Tu puedes crear una aplicación de cámara usando el API de la cámara para captura fotografías. En la lección del día de hoy te mostrare como desplegar el viewfinder de la cámara, disparar la cámara programáticamente, y salvar una fotografía tomada a la librería multimedia y en el almacenamiento aislado. Una vez que comprendas como crear una aplicación relacionada con la cámara, fácilmente estarás encaminado a implementar el flash y enfoque, cambiando la resolución de captura, y usando el botón físico de capturar imágenes.

Creando la interfaz de usuario de la cámara

En esta sección, crearemos una interfaz de usuario para la cámara que consiste en la región Viewfinder para desplegar las imágenes capturadas, y un botón disparador para capturar una imagen.

Creación del proyecto

  1. En Visual Studio 2010 Express para Windows Phone, crea un nuevo proyecto dando clic en Archivo –> Nuevo Proyecto

  2. En la ventana de nuevo proyecto. Expande las plantillas de Visual C#, y selecciona la plantilla Silverlight For Windows Phone

  3. Selecciona la plantilla Windows Phone Application. Coloca el nombre que desees para tu proyecto.

  4. Dale clic a OK. La pantalla de una Nueva aplicación para Windows Phone es desplegada

  5. Al momento de escoger la versión del S.O., asegúrate escoger la versión Windows Phone 7.1
  6. Da clic en OK. El nuevo proyecto es creado, y el archivo MainPage.xaml es abierto en el diseñado de Visual Studio

  7. Del menú de Proyecto, selecciona Add Reference. En la pestana de .NET, escoge Microsoft.XNA.Framework y luego da clic a OK.

  8. En MainPage.xaml, actualiza el elemento phone:PhoneApplicationPage con el siguiente código:

    SupportedOrientations="Landscape" Orientation="LandscapeLeft"
        shell:SystemTray.IsVisible="False"

    Esto configura la pagina para soportar la orientación horizontal y esconder la bandeja del sistema.

  9. Ahora en MainPage.xaml, reemplaza el Grid nombrado LayoutRootcon el siguiente código:

    <!--LayoutRoot is the root grid where all page content is placed-->
        <Grid x:Name="LayoutRoot" Background="Transparent">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="640" />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
    
            <Canvas x:Name="viewfinderCanvas" Width="640" Height="480" 
                       HorizontalAlignment="Left" >
    
                <!--Camera viewfinder -->
                <Canvas.Background>
                    <VideoBrush x:Name="viewfinderBrush" />
                </Canvas.Background>
             </Canvas>
    
            <!--Button StackPanel to the right of viewfinder>-->
            <StackPanel Grid.Column="1" >
                <Button x:Name="ShutterButton" Content="SH" 
                 Click="ShutterButton_Click" FontSize="26" 
                 FontWeight="ExtraBold" Height="75" />
            </StackPanel>
    
            <!--Used for debugging >-->
            <TextBlock Height="40" HorizontalAlignment="Left" Margin="8,428,0,0" 
             Name="txtDebug" VerticalAlignment="Top" Width="626" FontSize="24" 
             FontWeight="ExtraBold" />
        </Grid>

    Este código crea una región Viewfinder de 640 x 480 pixeles con un control StackPanel que contiene un botón disparador. Ahora Implementaremos el evento ShutterButtonClick en los siguientes pasos.

  10. Dirígete al código C# MainPage.xaml.cs y agrega las siguientes directivas en la parte superior de la pagina:

    // Directives
    using Microsoft.Devices;
    using System.IO;
    using System.IO.IsolatedStorage;
    using Microsoft.Xna.Framework.Media;
  11. Ahora en la clase MainPage, declara los siguientes atributos arriba del constructor:

    // Variables
    private int savedCounter = 0;
    PhotoCamera cam;
    MediaLibrary library = new MediaLibrary();
  12. Para crear la aplicación de cámara, la capacidad de la cámara tiene que ser declarado en el archivo de manifesto del aplicación. Abre el archivo WMAppManifest.xmly confirma el siguiente elemento se encuentra presente:

    <Capability Name="ID_CAP_ISV_CAMERA"/>
  13. (Opcional) Si quieres que tu aplicación utilice cámara frontal, adicionalmente se debe agregar la siguiente capacidad en los elementos Capabilities en el archivo de manifesto de la aplicación:

    <Capability Name="ID_HW_FRONTCAMERA"/>

Implementando Viewfinder y eventos de la cámara

Para implementar el viewfinder, deberás establecer la fuente ViewfinderBrush en la cámara del Windows Phone. Además de esto implementaremos varios eventos relacionados de la cámara como la inicialización, captura completada, y disponibilidad de imagen.

Para implementar los eventos de cámara

  1. En MainPage.xaml.cs, agrega el siguiente código a la clase MainPage:

    //Code for initialization, capture completed, image availability events; also setting the source for the viewfinder.
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
       // Check to see if the camera is available on the device.
       if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true) ||
          (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) == true))
       {
          // Initialize the camera, when available.
          if (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing))
          {
             // Use front-facing camera if available.
             cam = new Microsoft.Devices.PhotoCamera(CameraType.FrontFacing);
          }
          else
          {
             // Otherwise, use standard camera on back of device.
             cam = new Microsoft.Devices.PhotoCamera(CameraType.Primary);
          }
    
          // Event is fired when the PhotoCamera object has been initialized.
          cam.Initialized += new EventHandler<Microsoft.Devices.CameraOperationCompletedEventArgs>(cam_Initialized);
    
          // Event is fired when the capture sequence is complete.
          cam.CaptureCompleted += new EventHandler<CameraOperationCompletedEventArgs>(cam_CaptureCompleted);
    
          // Event is fired when the capture sequence is complete and an image is available.
          cam.CaptureImageAvailable += new EventHandler<Microsoft.Devices.ContentReadyEventArgs>(cam_CaptureImageAvailable);
    
          // Event is fired when the capture sequence is complete and a thumbnail image is available.
          cam.CaptureThumbnailAvailable += new EventHandler<ContentReadyEventArgs>(cam_CaptureThumbnailAvailable);
    
          //Set the VideoBrush source to the camera.
          viewfinderBrush.SetSource(cam);
       }
       else
       {
          // The camera is not supported on the device.
          this.Dispatcher.BeginInvoke(delegate()
          {
          // Write message.
          txtDebug.Text = "A Camera is not available on this device.";
          });
    
          // Disable UI.
          ShutterButton.IsEnabled = false;
       }
    }
    protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
    {
       if (cam != null)
       {
          // Dispose camera to minimize power consumption and to expedite shutdown.
          cam.Dispose();
    
          // Release memory, ensure garbage collection.
          cam.Initialized -= cam_Initialized;
          cam.CaptureCompleted -= cam_CaptureCompleted;
          cam.CaptureImageAvailable -= cam_CaptureImageAvailable;
          cam.CaptureThumbnailAvailable -= cam_CaptureThumbnailAvailable;
       }
    }
  2. En MainPage.xaml.cs, agrega el siguiente código a la clase MainPage:
    // Update the UI if initialization succeeds.
    void cam_Initialized(object sender, Microsoft.Devices.CameraOperationCompletedEventArgs e)
    {
       if (e.Succeeded)
       {
          this.Dispatcher.BeginInvoke(delegate()
          {
             // Write message.
             txtDebug.Text = "Camera initialized.";
          });
       }
    }

    Este código utiliza el evento de la cámara Initialize, y actualiza el TextBlock nombrado txtDebug. El método BeginInvoke es requerido para actualiza el estado porque la interfaz de la aplicación se ejecuta en otro hilo de proceso diferente.

  3. En MainPage.xaml.cs, agrega el siguiente código a la clase MainPage:
    // Ensure that the viewfinder is upright in LandscapeRight.
    protected override void OnOrientationChanged(OrientationChangedEventArgs e)
    {
         if (cam != null)
         {
              // LandscapeRight rotation when camera is on back of device.
              int landscapeRightRotation = 180;
    
              // Change LandscapeRight rotation for front-facing camera.
              if (cam.CameraType == CameraType.FrontFacing) landscapeRightRotation = -180;
    
              // Rotate video brush from camera.
              if (e.Orientation == PageOrientation.LandscapeRight)
              {
                   // Rotate for LandscapeRight orientation.
                   viewfinderBrush.RelativeTransform = new CompositeTransform() 
                   { CenterX = 0.5, CenterY = 0.5, Rotation = landscapeRightRotation };
              }
              else
              {
                   // Rotate for standard landscape orientation.
                   viewfinderBrush.RelativeTransform = new CompositeTransform() 
                   { CenterX = 0.5, CenterY = 0.5, Rotation = 0 };
              }
         }
    
         base.OnOrientationChanged(e);
    }

    Este código asegura que el viewfinder, viewFinderBrush esta orientado de la manera correcta en la manera en que el usuario este sosteniendo el Windows Phone. Si la cámara frontal esta siendo utilizada, el brush correspondiente debe ser rotada a la dirección opuesta como si se encontrara en la parte trasera del dispositivo.

  4. En MainPage.xaml.cs, agrega el siguiente código a la clase MainPage:

    private void ShutterButton_Click(object sender, RoutedEventArgs e)
    {    if (cam != null)    {       try       {          // Start image capture.          cam.CaptureImage();       }       catch (Exception ex)       {          this.Dispatcher.BeginInvoke(delegate()             {             // Cannot capture an image until the previous capture has completed.             txtDebug.Text = ex.Message;             });       }    }
    }
    void cam_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e)
    {    // Increments the savedCounter variable used for generating JPEG file names.    savedCounter++;
    }

    Este código implementa los eventos del botón disparador y captura completada. El botón disparador es el elemento que agregamos en el código XAML para capturar fotografías con la cámara. El evento de captura completada es utilizado en este proyecto para incrementar la variable contador savedCounter. Es utilizado para la siguiente sección para nombrar las imágenes JPEG guardadas.

Guardando fotografías a la galería multimedia

Para una aplicación de cámara para Windows Phone 7.1, dos imágenes son capturadas cuando una foto es tomada. Una es la imagen con la resolución máxima, y la segunda es una imagen thumbnail usados para mostrar una versión mas reducida para mostrar en la galería de imágenes. Esta sección explica como guardar la imagen con resolución máxima en la librería multimedia del dispositivo. También aprenderá como salvar una imagen con resolución máxima y la imagen thumbnail en el almacenamiento aislado.

Para guardar la imagen en la librería multimedia y almacenamiento aislado

  1. En MainPage.xaml.cs, agrega el siguiente código a la clase MainPage:

    // Informs when full resolution picture has been taken, saves to local media library and isolated storage.
    void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
    {
       string fileName = savedCounter + ".jpg";
    
       try
       {   // Write message to the UI thread.
          Deployment.Current.Dispatcher.BeginInvoke(delegate()
          {
          txtDebug.Text = "Captured image available, saving picture.";
          });
    
          // Save picture to the library camera roll.
          library.SavePictureToCameraRoll(fileName, e.ImageStream);
    
          // Write message to the UI thread.
          Deployment.Current.Dispatcher.BeginInvoke(delegate()
          {
          txtDebug.Text = "Picture has been saved to camera roll.";
          });
    
          // Set the position of the stream back to start
          e.ImageStream.Seek(0, SeekOrigin.Begin);
    
          // Save picture as JPEG to isolated storage.
          using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
          {
             using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
             {
                // Initialize the buffer for 4KB disk pages.
                byte[] readBuffer = new byte[4096];
                int bytesRead = -1;
    
                // Copy the image to isolated storage. 
                while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                {
                   targetStream.Write(readBuffer, 0, bytesRead);
                }
             }
          }
    
          // Write message to the UI thread.
          Deployment.Current.Dispatcher.BeginInvoke(delegate()
          {
             txtDebug.Text = "Picture has been saved to isolated storage.";
          });
       }
       finally
       {
          // Close image stream
          e.ImageStream.Close();
       }
    }
    
    // Informs when thumbnail picture has been taken, saves to isolated storage
    // User will select this image in the pictures application to bring up the full-resolution picture. 
    public void cam_CaptureThumbnailAvailable(object sender, ContentReadyEventArgs e)
    {
       string fileName = savedCounter + "_th.jpg";
    
       try
       {
          // Write message to UI thread.
          Deployment.Current.Dispatcher.BeginInvoke(delegate()
          {
          txtDebug.Text = "Captured image available, saving thumbnail.";
          });
    
          // Save thumbnail as JPEG to isolated storage.
          using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
          {
             using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
             {
                // Initialize the buffer for 4KB disk pages.
                byte[] readBuffer = new byte[4096];
                int bytesRead = -1;
    
                // Copy the thumbnail to isolated storage. 
                while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                {
                   targetStream.Write(readBuffer, 0, bytesRead);
                }
             }
          }
    
          // Write message to UI thread.
          Deployment.Current.Dispatcher.BeginInvoke(delegate()
          {
             txtDebug.Text = "Thumbnail has been saved to isolated storage.";
          });
       }
       finally
       {
          // Close image stream
          e.ImageStream.Close();
       }
    }

    Este código implementa los eventos CaptureImageAvailable y CaptureThumbnailAvailable. El primer método guarda la imagen con resolución máxima en la librería multimedia y en almacenamiento aislado. El segundo método te muestra como se guarda una imagen thumbnail en almacenamiento aislado.

  2. En el dispositivo, ejecuta la aplicación seleccionando el comando de menú Debug|Start Debugging. Presiona el botón SH. El textblock txtDebug te indicara el estado de las operaciones para guardar las imágenes en almacenamiento aislado. Después de cerrar la aplicación, puedes encontrar las fotos que tomaste con tu aplicación la carpeta camera roll en el hub de fotos. En la siguiente imagen te ilustra como debería aparecer la interfaz grafica en este punto.

    En este ejemplo. el botón disparador SH, es mostrado en la esquina superior derecha de la interfaz. Una imagen de mangos es mostrado en el control Canvas nombrado viewFinderCanvas.

Cabe mencionar que estos ejemplos es solo una introducción a lo que se puede implementar usando la cámara. Existen mas funcionalidades útiles que involucran la cámara como usar el Flash, el enfoque, la resolución de la imagen capturada, etc.

Fuente:
How to: Create a Base Camera Application for Windows Phone

Generation Apps – Día 17 – Integración con Music + Video Hub para Windows Phone

El Hub de música y videos es un punto focal para toda las actividades de música, video y podcast en un Windows Phone. Aplicaciones en el Hub de Música y Videos provee una experiencia  integral de música y video en el teléfono como una función primaria. Estas aplicación se integran con este Hub usando las clases MediaHistory y MediaHistoryItem para asegurar una experiencia de usuario consistente para reproducción de material multimedia.

La arquitectura del Hub de Música + Videos

El Hub de música y videos esta dividido en las siguientes cuatro listas:

  • Zune: es el punto inicial para música, videos, podcasts, radio y el Marketplace. El botón en la parte inferior de la pantalla reproduce tu música de tu colección de manera aleatoria.

  • Historia: contiene música, videos, podcasts, listas de reproducción, artistas y estaciones de radio recientemente reproducidas por el usuario.

  • Nuevo: contiene una lista actualizada de nueva música, podcasts y video sincronizados en el teléfono o descargadas del Marketplace de Zune. Actualiza esta lista cuando tu aplicación reproduzca algún material multimedia.

  • Apps: Contiene la lista de aplicación de Música y videos que fueron instalados en el dispositivo. El proceso de registro y certificación de aplicación detectara que estas llamando los APIs de MediaHistory y MediaHistoryItem, y te dará el HubType a tu aplicación. Esto hará que tu aplicación aparezca en esta lista una vez instalada en el dispositivo.

Requerimientos de certificación de aplicación

Tu aplicación del hub de música y videos debe aprobar los requisitos de certificación de aplicación para Windows Phone para integrarse al Hub de música y videos. El proceso de registro al Marketplace de Windows Phone detecta el uso de APIs de música y videos y te permite el acceso de tu aplicación desde el Hub multimedia.

Mosaicos que son desplegados en el Hub de música y videos deben conformar unas reglas de iconografía adicionales

  1. Debes incluir el titulo o logo de tu aplicación en cada mosaico.

  2. El Mosaico «Now Playing» debe ser 358 pixeles x 358 pixeles. El archivo debe pesar menos de 75KB.

  3. Otros mosaicos deben tener un tamaño de 173 pixeles x 173 pixeles.

  4. La propiedad Title de la clase MediaHistoryItem debe ser asignada como texto que represente el contenido, tales como un nombre de estación, o titulo de video.

Para evitar confundir a los usuarios, Mosaicos de Hubs no deberían contener el arte de álbumes a menos que el álbum comience a sonar al momento que el usuario le de Tap a dicho mosaico. Esto no es un requisito de certificación, pero es una buena practica.

Probando la integración al Hub de Música + Videos

Mientras tu aplicación debe pasar por el proceso de verificación y certificación para entrar al Marketplace de Windows Phone antes de ser integrada al Hub de Música y Videos, existe una forma para saltar esto para propósitos de prueba. En el archivo «WMAppManifest.xml», asegúrate que la propiedad HubType tenga valor 1. El siguiente código muestra un ejemplo al respecto:

<App xmlns="" ProductID=" {00000000-0000-0000-0000-000000000000} 
     Title="WindowsPhoneApplication" RuntimeType="Silverlight" 
     Version="1.0.0.0" Genre="NormalApp" Author="" Description="" 
     Publisher="" HubType="1">

NOTA; En el release actual, no es posible probar la integración de una aplicación con el Hub de Música y Videos en el emulador Windows Phone. Deberás contar con un dispositivo físico para instalarlo.

NOTA: si intentas actualizar los mosaicos en el Hub de música y videos mientras el teléfono se sincroniza con el software Zune, los APIs arrojarán una excepción.

Actualizando el mosaico «Now Playing» en la lista «History»

El siguiente código de ejemplo muestra como actualizar el mosaico «Now Playing» en la lista «Historia» usando las clases de MediaHistory y MediaHistoryItem:

MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();

//<hubTileImageStream> must be a valid ImageStream.
mediaHistoryItem.ImageStream = <hubTileImageStream>; 
mediaHistoryItem.Source = "";
mediaHistoryItem.Title = "NowPlaying";
mediaHistoryItem.PlayerContext.Add("keyString", "Song Name");
MediaHistory.Instance.NowPlaying = mediaHistoryItem;

Actualizando la lista «History»

El siguiente ejemplo de código muestra como actualizar otros mosaicos además de Now Playing en la lista History usando las clases MediaHistory y MediaHistoryItem:

MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();

//<hubTileImageStream> must be a valid ImageStream.
mediaHistoryItem.ImageStream = <hubTileImageStream>; 
mediaHistoryItem.Source = "";
mediaHistoryItem.Title = "RecentPlay";
mediaHistoryItem.PlayerContext.Add("keyString", "Song Name");
MediaHistory.Instance.WriteRecentPlay(mediaHistoryItem);

Actualizando la lista «New»

El siguiente ejemplo de código muestra como actualizar la lista New usando las clases MediaHistory y MediaHistoryItem:

MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();

//<hubTileImageStream> must be a valid ImageStream.
mediaHistoryItem.ImageStream = <hubTileImageStream>; 
mediaHistoryItem.Source = "";
mediaHistoryItem.Title = "MediaHistoryNew";
mediaHistoryItem.PlayerContext.Add("keyString", "Song Name");
MediaHistory.Instance.WriteAcquiredItem(mediaHistoryItem);

Reproduciendo un ítem cuando es ejecutado de las listas «History» y «New»

El siguiente código de ejemplo te muestra como determinar si la aplicación fue ejecutada desde la lista History o New. Esto se logra en el manejador de evento OnNavigatedTo(NavigationEventArgs). La información en el NavigationContext es usado para determinar que tipo de elemento multimedia esta asociado, que en este caso, es una canción de la librería del dispositivo. La canción comienza a sonar en el manejador de evento Loader para el PhoneApplicationPage después que la pagina haya terminado de cargarse.

bool _historyItemLaunch = false;            // Indicates whether the app was launched from a MediaHistoryItem.
const String _playSongKey = "keyString";    // Key for MediaHistoryItem key-value pair.
Song _playingSong = null;                   // The song to play.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    MediaLibrary library = new MediaLibrary();

    if (NavigationContext.QueryString.ContainsKey(_playSongKey))
    {
        // We were launched from a history item.
        // Change _playingSong even if something was already playing 
        // because the user directly chose a song history item.

        // Use the navigation context to find the song by name.
        String songToPlay = NavigationContext.QueryString[_playSongKey];

        foreach (Song song in library.Songs)
        {
            if (0 == String.Compare(songToPlay, song.Name))
            {
                _playingSong = song;
                break;
            }
        }

        // Set a flag to indicate that we were started from a 
        // history item and that we should immediately start 
        // playing the song after the UI has finished loading.
        _historyItemLaunch = true;
    }
}

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    if (_historyItemLaunch)
    {
        // We were launched from a history item, start playing the song.
        if (_playingSong != null)
        {
            MediaPlayer.Play(_playingSong);
        }
    }
}

Fuente:
How to: Integrate with the Music and Videos Hub for Windows Phone

Generation Apps – Día 16 – Extender la experiencia de Pictures Hub y visor de Imágenes

Con App Connect, tu aplicación puede extenderse a la experiencia del hub de fotos y observador de fotos. Tambien puedes extender la funcionalidad de compartición de fotos y permite a los usuarios para cargar sus imágenes a un servicio web. Esta sección describe como puedes usar App Connect con tu aplicación Windows Phone.

Declarando extensiones

Para usar App Connect, especifica la manera en que quieres extender la experiencia de fotografía declarando una extensión de fotos. Las extensiones están declaradas en el elemento Extensions del archivo manifesto de tu aplicación Windows Phone (WMAppManifest.xml). Cada Extensión de fotografía sigue el mismo formato general. El siguiente ejemplo muestra una extension al hub de fotos.

<Extensions>
      <Extension ExtensionName="Photos_Extra_Hub" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" />
<Extensions>
  • Hub de Fotos: permite a usuarios ejecutar tu aplicación relacionada con fotografía desde la página pivote en el hub de fotos. Para que tu aplicación aparezca en este espacio, deberás declarar la extensión explicada anteriormente, colocando el atributo ExtensionName con el valor Photos_Extra_Hub.

    Una vez hecho esto, e instalado tu aplicación en un dispositivo o el emulador, dirígete al Hub de imágenes, y desplázate hacia la pantalla pivote de «Apps». Nota que la pantalla pivote de Apps no es visible hasta que allá al menos una aplicación agregada. Desde esa pantalla, dale Tap a tu aplicación, y veras que se ejecutara.

  • Picture Viewer: o observador de foto permite a los usuarios ejecutar tu aplicación relacionada con fotografía desde el enlace de aplicaciones en el observador de fotos. Desde el enlace URL, obtienes un token que corresponde a la foto del cual tu aplicación fue ejecutada.

    Para agregar tu aplicación a este espacio, deberás declarar la extensión explicada al inicio de esta lección, especificando el atributo ExtensionName con el valor Photos_Extra_Viewer. Cuando tu aplicación es ejecutada de esta manera, un parámetro con el nombre Token es pasado a tu aplicación vía enlace URL. El parámetro Token, corresponde con la imagen con la cual tu aplicación fue ejecutada. Usando el token, puedes proveer una experiencia agradable al usuario basándote en la imagen con la que ejecuto tu aplicación.

  • Share Picker: permite a los usuarios ejecutar tu aplicación relacionada con fotografía desde el enlace de compartir en el observador de fotos y compartir sus fotos a un servicio web.

    Si deseas extender tu aplicación de esta forma, deberás declarar la declaración explicada al inicio de esta lección, especificando el atributo ExtensionName con el valor Photo_Extra_Share. Cuando tu aplicación es ejecutada de esta manera, un parámetro nombrado FIleId es pasado a tu aplicación vía enlace URL. El valor del parámetro, FileId, corresponde con la imagen en la cual tu aplicación fue ejecutada. Usando este parámetro, puedes proveer una experiencia agradable al usuario para comparar imágenes a través de un servicio web.

Fuente:
Pictures Extensibility Overview for Windows Phone

Generation Apps – Día 9 – Realizar navegación de páginas en Windows Phone

Para este día en Generation Apps, quiero mostrarte algo de vital importancia para tu aplicación. Es la navegación, es decir, la forma cuando el usuario es llevado de una pagina a otra. Es algo común que encuentras en cualquier aplicación independientemente de la plataforma en la que te encuentres. Ya que en días anteriores tienes tu mapa de navegación esquemático, es hora de implementarlo en tu proyecto Windows Phone.

En el siguiente video, te mostrare como se hace esto con Expression Blend. Hay diversas formas de como implementarlo, e incluso te mostrare como se hace el pase de parámetros, para enviar datos de una página a otra.

Crear una pagina adicional

  1. Ejecuta Visual Studio 2010 Express para Windows Phone.
  2. Crea un nuevo proyecto seleccionando haciendo clic en Archivo | Nuevo Proyecto

  3. La ventana de Nuevo Proyecto aparece. Expande las plantillas de Visual C#, y selecciona la plantilla Silverlight para Windows Phone.

  4. Ahora selecciona la plantilla Aplicación Windows Phone. Coloca de nombre de proyecto tu preferencia.

  5. Da clic a OK. La ventana de selección de plataforma Windows Phone aparece. Selecciona Windows Phone OS 7.1 para la versión de Windows Phone objetivo.
  6. Da clic a OK. El proyecto nuevo es creado y se despliega el archivo MainPage.xaml en el diseñador de Visual Studio.

  7. En el diseñador, selecciona el titulo de pagina y colócale main page en la propiedad Text o directamente en el XAML

  8. Da clic derecho sobre el proyecto, selecciona Add->New Item

  9. Selecciona Windows Phone Portrait Page. Nómbralo SecondPage, da clic en Add

  10. Desde la vista de diseñador de SecondPage.xaml, renombra el titulo de la pagina a SecondPage en la propiedad Text o directamente en el XAML

Navegación entre paginas

  1. En MainPage.xaml, arrastra un botón tipo HyperlingButton desde el toolbox hacia el ContentPanel de la pagina. Selecciona el control y en las propiedades, asigna el valor Content el texto «Navigate To Second Page» o directamente en el XAML. Deberás expandir el ancho del control para ver el texto completo.

  2. Da un doble clic en el botón de hipervínculo para agregar el manejador de evento clic. El archivo MainPage.xaml.cs es desplegado.

  3. Para el evento Hyperlinkbutton1_Click, agrega la siguiente instrucción dentro del método:

    NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));
  4. En SecondPage.xaml, arrastra un botón del toolbox a la superficie del diseñador. Selecciona el control y cambia el valor de la propiedad Content a Navigate Back to Main Page o hazlo directamente en el XAML. Expande el botón para visualizar el texto completo.

  5. Da doble clic sobre el botón para agregar el manejador del evento clic button1_clic, El archivo SecondPage.xaml.cs será desplegado.

  6. Dentro del método button1_Clic, agrega la siguiente instrucción:

    NavigationService.GoBack();
  7. Ejecuta la aplicación con el comando de menú Debug | Start Debugging. Esto abrirá el emulador ejecutando tu aplicación

Cuando ejecutas la aplicación, veras que consiste de dos paginas: la pagina MainPage y SecondPage. Puedes navegar del MainPage hacia la pantalla secundaria usando el botón de hipervínculo con el URI destino en el evento clic. Puedes retornar de la pagina secundaria hacia la pagina principal usando el metodo GoBack().

Pasando Parámetros

  1. En MainPage.xaml, arrastra un control TextBox y un Button del toolbox y ubícalo debajo del botón de hipervínculo. Elimina el texto dentro del textbox. Para el botón, renómbralo a passParam, y en la propiedad Text, coloca Go.

  2. Da doble clic al botón Go, para agregar el manejador de evento clic.

  3. En el método passParam_Click recién generado, agrega la siguiente instrucción:

    NavigationService.Navigate(new Uri("/SecondPage.xaml?msg=" + textBox1.Text, UriKind.Relative));
  4. En SecondPage.xaml, arrastra un control tipo TextBlock del toolbox y ubícalo debajo del botón de retornar al main page. Elimina el texto dentro del TextBlock. Si deseas, incrementa las dimensiones del textblock al ancho del panel y un tamaño de fuente mayor para visualizar el parámetro mas fácilmente.

  5. Ahora en SecondPage.xaml.cs, crea el siguiente método debajo del constructor.

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
       base.OnNavigatedTo(e);
       string msg = "";
    
       if (NavigationContext.QueryString.TryGetValue("msg", out msg))
           textBlock1.Text = msg;
    }
  6. Ejecuta la aplicación con el comando de menú Debug | Start Debugging. Esto abrirá el emulador ejecutando tu aplicación. Ingresa texto en el TextBox y da clic sobre el botón Go, y veras que el mensaje ingresado aparecerá en la pagina secundaria.

En este punto, deberías tener tu aplicación con la interfaz bastante desarrollada (diseño visual y eventos), y la navegación entre cada pagina.

Fuente:
How to: Perform Page Navigation on Windows Phone

Generation Apps – Día 2 – Interfaces de Usuario

Creando tu primera interfaz de usuario Windows Phone

Una vez que ya se tiene la idea principal de la aplicación, con las funcionalidades a implementar, el flujo de las actividades que realizara el usuario, etc.; es momento de sentarse a planificar como será la interfaz de la aplicación.

Navegación

Planifica cuantas y cuales paginas son fundamentales para tu aplicación, pero también debes considerar el flujo de navegación de las pantallas. Siempre se sugiere realizar un pequeño diagrama a modo de identificar como las paginas están conectadas, a modo de un mapa de navegación. Procura hacerlo sencillo, q no sobrepase a mas de 3 niveles de profundidad. A continuación unos ejemplos.

La única forma que la navegación de la derecha sea aceptable es que sea alguna operación donde se involucra una serie de pasos consecutivos, como el registro de algún servicio, o realizar algún efecto sobre alguna foto, etc.

Diseño Visual

Procura escoger una paleta de colores limitada, y unos estándares en cuanto al diseño de elementos de controles, texto, fondos de pantalla, etc.; a modo de lograr una aplicación con una consistencia de diseño en la interfaz. A continuación muestro algunos ejemplos de interfaces de aplicaciones que ya se encuentran en el marketplace.

La imagen de arriba es una interfaz tipo panorama, donde el desplazamiento de las diversas pantallas es desplazándose de manera horizontal, y al hacer Tap a alguna foto, navegas a una pantalla aparte para interactuar con la imagen que seleccionaste. Otro ejemplo es la aplicación de Pizza Hut, observa el tema y la consistencia de colores y elementos que aplican para cada pantalla de su interfaz:

Es de suma importancia ser muy meticuloso en cuanto al diseño visual y la manera de interacción con el usuario, para incrementar tus posibilidades de éxito y vida de tu aplicación.

Generation Apps – Día 1 – Principios de diseño de IU Windows: Diseñar tu aplicación de Windows Phone

Para diseñar una aplicación, la mejor manera de conseguir una idea es respondiendo las siguientes tres preguntas:

«Mi aplicación es excelente para…»

La parte más importante de diseñar una aplicación es en que tarea es excepcional. Por ejemplo, digamos que vas a hacer una aplicación de fotos. Pensarías acerca de las funcionalidades que le ofrecerías al usuario, guardar el resultado, y compartir las fotos, y te das cuenta que ellos quieren revivir memorias, conectarse con seres queridos a través de fotos, y mantenerlas a salvo. Estos son aspectos en los que tu aplicación debería ser excelente, y utilizas estas experiencias para guiarte al resto del proceso de diseño. Simplemente, piensa en la frase “My aplicación es excelente para…” y al completarla, tienes la idea esencial en la debes basarte en la creación de la aplicación. Algunos ejemplos:

  • Mi Aplicación de viajar es excelente para ayudar a amigos a crear itinerarios de manera colaborativa para jornadas grupales.

  • Mi aplicación de ejercicio es excelente para que amigos puedan rastrear el progreso de ejercicios y compartir logros con unos a los otros.

  • Mi aplicación de compras de mercado es excelente para que familias puedan coordinar semanalmente las compras en el supermercado, para evitar la falta de algún bien en la casa.

Decide que actividades espera que el usuario realice

Un flujo es un conjunto de interacciones relacionadas que los usuarios tienen con tu aplicación para lograr tareas. Cada flujo debería estar fuertemente relacionado a tu principio “Mi aplicación es excelente para”, y debería ayudar usuarios lograr ese escenario en particular. Aplicaciones exitosas poseen flujos que son fáciles de aprender y que requieren poca interacción.

Decide las funcionalidades a incluir

Una vez que ya sabes que quiere hacer el usuario y como tu puedes ayudar para lograrlo, ahora puedes reflexionar acerca de las herramientas especificas que le planteas facilitar. Los pasos mas comunes para resolver este requerimiento son los siguientes:

  • Investigar la plataforma: averigua que facilidades te ofrece el SDK para implementarlas

  • Diagrama las asociaciones: conecta los flujos con las funcionalidades

  • Prototipo: realiza una aplicación de prueba poniendo en practica las funcionalidades a implementar

Diseña la interfaz de usuario

En este punto, después de planificar el propósito y las funcionalidades esenciales de tu aplicación, puedes comenzar a diseñar el flujo de navegación entre las distintas pantallas, el propósito de cada una y los controles que ofrece.

  • En Visual Studio, las plantillas de proyectos de aplicaciones de Windows Phone ofrece distintas maneras de presentar la pantalla principal, como el panorama y el pivote.

  • Diseña en la manera de como el usuario va interactuar con cada pagina de la aplicación. Saca provecho de los gestos táctiles que ofrece el SDK, a modo de hacer la interfaz innovadora e interesante para los usuarios.

Crea una buena primera impresión

El primer minuto en que el usuario abre tu aplicación, determina si el usuario encuentra tu aplicación útil, estéticamente atractivo y que valga la pena conservar en su teléfono (e incluso si desea sugerirlo a sus amigos, como la mejor meta). Saca provecho de algunos elementos importantes como:

  • Tile y las notificaciones: El Tile (o mosaico) es la cara de tu aplicación, es el icono de tu aplicación que se mostrara en la pantalla principal, y entre la lista de todas las aplicaciones instaladas en el Windows Phone. Es primordial realizar un buen diseño de este icono, que destaque entre el montón de aplicaciones, a modo que captes la atención del usuario.

  • Splash Screen: es la pantalla que se muestra al primer momento que se ejecuta tu aplicación, mientras se carga la aplicación y desplegar la pantalla principal.

  • Primera ejecución: Antes que el usuario deba proveer información para suscribirse a algún servicio o crear alguna cuenta, muéstrale el valor de tu aplicación y los distintos beneficios que adquiriría al momento de contar con una cuenta o servicio.

  • Home Page: Es la pagina donde el usuario llega al inicio de ejecutar la aplicación. Ya que es una pagina donde el usuario frecuenta, es importante hacerla amigable, animada, bien diseñada.

Prototipos y Validaciones

El simple hecho que tu aplicación se ejecute, no implica que esta lista para su lanzamiento. Asegúrate de validar toda la navegación, los formularios y diversos controles con las que interactúe el usuario, a modo de hacerlo robusto, a prueba de errores.

Fuente: User Experience Design Guidelines for Windows Phone

Diseña un sitio como este con WordPress.com
Comenzar