[Tips and Tricks] Windows Phone 8. ¿Donde esta mi SplashScreen?

defaultsplashscreenIntroducción

Para quienes vengan de desarrollar para Windows Phone 7 pueden haber notado un pequeño cambio al crear proyectos Windows Phone 8… el recurso SplashScreenImage.jpg no existe en el proyecto!

¿Que ha pasado?, ¿ya no se pueden incluir pantallas Splash en nuestras aplicaciones?.

La respuesta es rápida y simple, si podemos seguir utilizando pantallas de Splash en nuestras aplicaciones Windows Phone 8 ya sea por resaltar la “marca” o por otros motivos. Vamos a tratar este punto en esta entrada.

A tener en cuenta, resoluciones

Uno de los cambios apreciables con suma rapidez en Windows Phone 8 con respecto a Windows Phone 7 son las resoluciones. Mientras que en Windows Phone 7 contábamos sólo con una única resolución (480 x 800 px) en Windows Phone 8 tenemos las siguientes resoluciones:

Resolución
WVGA (Wide Video Graphics Array) 480 x 800 px
WXGA (Wide eXtended Graphics Array) 768 x 1280 px
720P 720 x 1280 px
Resoluciones soportadas

Resoluciones soportadas

Añadir una SplashScreen

Entonces, ¿añadimos una imagen para cada resolución o como antes una única?.

Podemos utilizar una única imagen llamada SplashScreenImage.jpg de 768 x 1280 px (resolución de mayor tamaño) situada en la raíz del proyecto. El sistema escalará automáticamente la imágen dependiendo de la resolución del dispositivo donde se ejecute la aplicación. Sin embargo, podemos también utilizar una imagen para cada resolución (WXVGA, WXGA 720p) situadas también en la raíz del proyecto (pixel perfect). Los nombres de los archivos deben ser:

  • SplashScreenImage.screen-WVGA.jpg
  • SplashScreenImage.screen-720p.jpg
  • SplashScreenImage.screen-WXGA.jpg

NOTA: En las propiedades de cada imagen debemos establecer la propiedad Build Action al valor Content.

NOTA: Si utilizamos la imagen SplashScreenImage.jpg junto al resto (específicas por resolución), el sistema tomará esta imagen en lugar de la específica de la resolución.

Más información

Anuncios

Windows Phone 8. Distribución empresarial.

Windows-Phone-MetroIntroducción

Entre la lista de novedades recibidas en Windows Phone 8 cabe destacar el soporte para la distribución de aplicaciones a nivel empresarial sin necesidad de pasar por la Windows Phone Store. Las empresas pueden crear aplicaciones útiles a nivel interno como aplicaciones de recibos de pagos, entrega de paquetes o mapas sin querer pasar por la tienda Windows Phone. Los empleados pueden descargar las aplicaciones sólo tras agregar la cuenta de empresa al teléfono.

Además como empresa se puede también crear hubs donde incluir información relacionada con la empresa, novedades, gastos y un acceso rápido a las aplicaciones de la misma.

En la entrada actual vamos a centrarnos en como realizar la distribución empresarial de aplicaciones, ¿te apuntas?

Obtener certificados

Lo primero que debemos hacer para poder distribuir aplicaciones a nivel empresarial es conseguir el certificado correspondiente de Symantec. Para ello nos dirigimos al Dev Center:

Windows Phone Dev Center

Windows Phone Dev Center

Debemos entrar con nuestra cuenta de desarrollador para obtener cierta información que será necesaria para obtener el certificado. Una vez dentro debemos obtener la siguiente información:

  • Symantec Id: Id de Symantec. No es igual al GUID de publicador.
  • Email: Dirección de correo electrónica validada en la cuenta de desarrollador.

Tras obtener el Symantec Id y el email correspondiente debemos dirigirnos a la siguiente dirección:

https://products.websecurity.symantec.com/orders/enrollment/microsoftCert.do

Symantec

Symantec

Tras introducir el Id de editor de Symantec y el email nos pedirán la información de facturación (el certificado tiene un coste de $299).

Tras confirmar los términos y condiciones recibiremos un correo electrónico confirmando nuestro pedido. Debemos hacer clic sobre el enlace que nos llega en el correo para aprobar el pedido.

Tras aprobar el pedido recibiremos (en breves días) otro correo confirmando que el pedido ha sido aprobado. Haciendo clic en el enlace podremos descargar el certificado.

NOTA: Esta operación debería realizarse en el mismo ordenador e incluso en el mismo navegador desde donde realizamos la petición:

Certificado Symantec instalado

Certificado Symantec instalado

Firmar la aplicación

En Visual Studio compilamos en modo release nuestra aplicación Windows Phone. Accedemos al XAP en la carpeta \Bin\Release.

Tenemos ya nuestro XAP listo para ser firmado y así poder distribuirlo empresarialmente. Empezamos!

Abrimos la Línea de Comandos de Visual Studio 2012. Vamos a ejecutar la herramienta XapSignTool que podemos encontrar en la siguiente ruta:

C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Tools\XapSignTool\XapSignTool.exe

Ejecutaríamos la siguiente línea:

C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Tools\XapSignTool\XapSignTool.exe" sign /v "C:\Temp\AppName.xap"

¿Qué hemos realizado?

Utilizamos la herramienta XapSignTool para firmar una aplicación llamada “AppName” situada en una carpeta temporal:

  • /v indica modo verboso, es decir, vamos a mostrar en pantalla la mayor cantidad de información posible en el proceso (muy útil en caso de tener múltiples certificados registrados en la máquina).

Si todo ha ido correctamente, enhorabuena ya puedes distribuir empresarialmente la aplicación. En caso contrario, no desesperes falta “afinar” un poco el proceso de firmado.

Gracias al modo verboso podemos ver en pantalla todos los certificados que tenemos instalados. Buscamos el certificado “Symantec Enterprise Mobile CA for Microsoft” y copiamos su SHA1 Hash.

NOTA: Para copiar el SHA1 hacemos clic derecho sobre la ventana y seleccionamos la opción Marcar, seleccionamos el código y pulsamos Enter.

Una vez copiado el código SHA1 volvemos a intentar la firma. La línea a ejecutar sería:

"C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Tools\XapSignTool\XapSignTool.exe" sign /v /sha1 SHA1_CODE "C:\Temp\AppName.xap"

Hemos vuelvo a firmar la aplicación en modo verboso pero a diferencia del modo anterior en esta ocasión especificamos el certificado a utilizar mediante:

  • /sha1 Nos permite indicar un código SHA1 para identificar un certificado.

Si la línea la ejecutamos con éxito nuestro XAP estará firmado. Podemos enviar el fichero por correo electrónico a los destinatarios o subir el fichero a un servidor  para ser descargado directamente desde el dispositivo.

NOTA: Aunque el fichero está firmado no está encriptado por lo que podría llegar a descompilarse.

Generando el Application Enrolment Token (AET)

Abrimos la Línea de Comandos de Visual Studio 2012. Utilizaremos la herramienta AetGenerator para crear el AET:

"C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Tools\AETGenerator\AetGenerator.exe" certificado contraseña
  • Certificado: Obligatorio. Archivo PFX.
  • Contraseña: Obligatoria. Debe ser la clave utilizada para leer el archivo PFX.

NOTA: Puedes obtener un backup del certificado ( certificado.p12 o certificado.pfx) desde el propio navegador donde obtuvimos el certificado de Symantec.

La herramienta genera varios ficheros donde el más importante es el archivo con extensión .aetx. Puedes obtener más información al respecto desde el siguiente enlace.

Distribuir la aplicación

Llega el momento gratificante tras el proceso, la distribución. Lo primero que debe hacerse desde un dispositivo es inscribirlo a la empresa mediante el Application Enrolment Token conocido como AET. Este pequeño archivo anteriormente generado puede distribuirse vía email o mediante URL directa.

NOTA: La URL debería estar protegida mediante credenciales y disponible sólo sobre SSL.

Tras acceder al archivo veremos desde el dispositivo lo siguiente:

Abrir Certificado

Abrir Certificado

Pulsamos en la pantalla para abrir el AET y nos saldrá una pantalla como la siguiente:

Instalar Certificado

Instalar Certificado

Con esta operación inscribimos el dispositivo a la empresa. Esta operación sólo es necesaria inicialmente una única vez.

Por último, y tras abrir el AET, podemos instalar la Aplicación:

Instalar Aplicación

Instalar Aplicación

Tras pulsar instalar, la instalación de la Aplicación es totalmente silencionsa de cara al usuario.

Conclusiones

Como hemos podido ver a lo largo de la entrada, la distribución empresarial en Windows Phone 8 es muy fácil de implementar y abre un gran mundo de posibilidades antes inexistentes. Los pasos a realizar son:

  • Entramos en el portal Windows Phone Dev Center.
  • Usamos el Publisher ID del Dev Center para adquirir un certificado empresarial de Symantec.
  • Usamos la herramienta  AETGenerator tool para  generar el application enrollment token(AET).
  • Se firman las aplicaciones que serán distribuidas.
  • Los usuarios (empleados de la empresa) se inscriben a la distribución empresarial de la compañia para poder instalar las aplicaciones.
  • Aunque opcional, es interesante crear un Company HUB para que los usuarios puedan acceder desde un punto común y agrupado a todas las apliaciones así como la información relacionada con la empresa.

En próximas entradas nos centraremos en crear un Company HUB junto a otros detalles relacionados con la distribución empresarial. Keep Pushing!

CompanyHub

CompanyHub

Más información

Megathon Windows 2013

Introducción

En verano del año pasado, en Twitter, surgió una iniciativa brutal por la rapidez y alcance logrado. Jose Bonnin (Evangelism Management en Microsoft) publicó un tweet comentando los hackathons de Windows 8 que se estaban celebrando en Barcelona y Mallorca. A partir de ese tweet varios desarrolladores empezaron a preguntar si era posible celebrar un hackathon en su ciudad. Todo corrió como la pólvora hasta llegar a lo que fue el Megathon (Hackathon Windows 8 a nivel nacional).

El resultado fue abrumador, más de 400 desarrolladores participando de manera simultánea en una competición durante un fin de semana. Hubo grandes premios, se compartieron grandes momentos, un aprendizaje muy positivo y muchas ganas. Tantas ganas que muchos nos quedamos con ganas de más…

Y así llega el Megathon Windows 2013

Megathon Windows 2013

Megathon Windows 2013

Vuelve el Megathon Windows los 12, 13 y 14 de Abril. Concurso que se celebrará de nuevo de manera simultánea en varias ciudades, donde podrás sin duda aprender, conocer a otros programadores, compartir buenos momentos y ganar premios. En esta ocasión se ha cambiado un poco la dinámica del concurso:

  • Al poco de terminar el anterior Megathon y casi coincidiendo con la salida de Windows Phone 8, eramos muchos los que queríamos un Megathon sobre Windows Phone. En esta ocasión, se puede participar creando Apps tanto para Windows 8 como para Windows Phone 8.
  • Una de los pocos puntos flacos del anterior Megathon radicaba en las sesiones de formación. Todos estamos de acuerdo que son muy positivas para todos a la vez que necesarias. Sin embargo, el compaginar la formación con el tiempo de desarrollo era difícil para asistentes y para formadores. Para mejorar esto se van a reducir el número de sesiones a impartir durante el fin de semana y se ha preparado un conjunto de sesiones formativas online previas al evento.
  • Se entiende que para tener una gran aplicación terminada y pulida se necesita algo más que un fin de semana. Por ello, tendremos hasta un mes después del evento para terminar las Apps. Los premios más grandes se otorgarán a Apps publicadas (premios globales).
  • Se intentará que los participantes puedan estar la mayor cantidad de tiempo posible desarrollando. Para ello, las sesiones formativas se impartirán el día 12 de Abril (primer día).

El resto de bases se mantiene en general:

  • Equipos de hasta como máximo 4 personas (no es necesario que tengáis el equipo formado antes de llegar).
  • No se puede trar código preparado de casa (perdería la gracia el asunto) aunque si recursos (imágenes o base de datos por ejemplo).
  • Todos los participantes obtendrán un regalo por el simple hecho de participar. Si además durante la presentación de los proyectos el Domingo 14 de Abril resultáis ser los ganadores, os llevaréis un premio adicional para cada miembro del equipo.

¿Te lo vas a perder?

Premios

¿Cómo?, ¿aún no estáis convencidos?. Quizás conocer el listado de premios acabe de convencerte.

Local

Ganador del Megathon 2013 a nivel local: Placa Cerbuino Bee con modulo Ethernet personalizada especialmente para el Megathon 2013 y acceso al Nokia Premium Developer Program.

Nacional

Ganador del Megathon 2013: Entradas para el TechEd Europe 2013 más un cupón de promocional de Adduplex por valor de 1.000.000 de impresiones.

Windows 8 Windows Phone
2º Clasificado Nokia Lumia 920 dev Nokia Lumia 920 dev
3º Clasificado Nokia Lumia 820 dev Nokia Lumia 820 dev
4º Clasificado Nokia Lumia 820 dev Nokia Lumia 820 dev
5º Clasificado Nokia Lumia 820 dev Nokia Lumia 820 dev
6º Clasificado Nokia Lumia 820 dev Nokia Lumia 820 dev
7º Clasificado Juego XBox 360 Cazadora Snow Nokia

Más información

Windows Phone 8. Nuevos Lanzadores.

WP8IconIntroducción

En ocasiones nuestras aplicaciones necesitarán cierto grado de interacción con el sistema. Por ejemplo, realizar acciones como abrir Bing Maps para indicar una localización, abrir el MarketPlace para que el usuario puntue la aplicación o abrir el reproductor multimedia para reproducir un archivo.

¿Podemos realizar este tipo de acciones?

Por supuesto. Para ello tenemos a nuestra disposición los lanzadores. Un lanzador nos permite ejecutar una determianda acción en el sistema. Importante resaltar que cuando el lanzador se ejecuta, nuestra aplicación se cierra. Además, no vamos a recibir ningun tipo de información por parte del lanzador. Por ejemplo, al abrir el MarketPlace para puntuar la aplicación, el usuario puede votar  o no nuestra aplicación pero el lanzador no nos indicará que ha sucedido.

Nuevos Lanzadores

Con el nuevo SDK de Windows Phone 8 contamos a nuestra disposición con un nuevo conjunto de lanzadores distintos. Son los siguientes:

  • MapsTask. Inicia la aplicación de Mapas. Se puede indicar un parámetro para buscar una localización en el mapa, especificar un punto central (si no se especifica se utilizaría la posición actual como punto central) o el nivle de zoom.
  • MapsDirectionsTask. Inicia la aplicación de Mapas permitiendo indicar una ruta entre dos puntos dados.
  • MapDownloaderTask. Abre la configuración de la aplicación de Mapas permitiendo al usuario descargar mapas para su uso sin conexión.
  • SaveAppointmentTask. Inicia la aplicación Calendario del sistema y permite al usuario añadir una nueva cita.
  • ShareMediaTask. Permite al usuario compartir un archivo multimedia.

Como podemos ver tenemos nuevas opciones muy interesantes. Para aprender a utilizar cada uno de los nuevos lanzadores como siempre, crearemos un ejemplo práctico.

Windows Phone Application

La plantilla seleccionada será “Windows Phone Application” para simplificar al máximo el ejemplo.

Agregamos dentro del Grid principal de la página MainPage.xaml:

<StackPanel>
     <Button x:Name="btnMapsTask" Content="MapsTask"/>
     <Button x:Name="btnMapsDirectionsTask" Content="MapsDirectionsTask"/>
     <Button x:Name="btnMapDownloaderTask" Content="MapDownloaderTask"/>
     <Button x:Name="btnSaveAppointmentTask" Content="SaveAppointmentTask"/>
     <Button x:Name="btnShareMediaTask" Content="ShareMediaTask"/>
</StackPanel>

Conseguiremos la siguiente interfaz:

Página Principal

Página Principal

Añadimos el manejador del evento Click de cada botón:

<StackPanel>
     <Button x:Name="btnMapsTask" Content="MapsTask" Click="btnMapsTask_Click_1"/>
     <Button x:Name="btnMapsDirectionsTask" Content="MapsDirectionsTask" Click="btnMapsDirectionsTask_Click_1"/>
     <Button x:Name="btnMapDownloaderTask" Content="MapDownloaderTask" Click="btnMapDownloaderTask_Click_1"/>
     <Button x:Name="btnSaveAppointmentTask" Content="SaveAppointmentTask" Click="btnSaveAppointmentTask_Click_1"/>
     <Button x:Name="btnShareMediaTask" Content="ShareMediaTask" Click="btnShareMediaTask_Click_1"/>
</StackPanel>

Y en el code-behind:

private void btnMapsTask_Click_1(object sender, RoutedEventArgs e)
{
}

private void btnMapsDirectionsTask_Click_1(object sender, RoutedEventArgs e)
{
}

private void btnMapDownloaderTask_Click_1(object sender, RoutedEventArgs e)
{
}

private void btnSaveAppointmentTask_Click_1(object sender, RoutedEventArgs e)
{
}

private void btnShareMediaTask_Click_1(object sender, RoutedEventArgs e)
{
}

Comenzamos con el lanzador MapsTask. Veamos el código de ejemplo utilizado al pulsar sobre el primer botón:

MapsTask mapsTask = new MapsTask();
mapsTask.Center = new GeoCoordinate(37.387908, 6.001959);
mapsTask.ZoomLevel = 8; // 1- 20
mapsTask.SearchTerm = "restaurante";

mapsTask.Show();

Contamos con las siguientes propiedades:

  • Center. Localización a utilizar como centro del mapa (GeoCoordinate).
  • ZoomLevel. Nivel de zoom (Double).
  • SearchTerm. Término utilizado para buscar y localizar localizaciones.

NOTA: Debemos añadir la referencia a la librería System.Device. Una vez añadida la librería se deben añadir las siguientes using:

using System.Device.Location
using Microsoft.Phone.Tasks

Visualmente veremos algo como lo siguiente:

Lanzadores WP8 02

MapsTask

Continuamos con el lanzador  MapDirectionsTask. Este lanzador abre la aplicación de mapas de Nokia. Podemos especificar dos puntos para obtener la ruta entre ambos.

MapsDirectionsTask mapDirectionsTask = new MapsDirectionsTask();
mapDirectionsTask.Start = new LabeledMapLocation("Sevilla", new GeoCoordinate(37.387908, 6.001959));
mapDirectionsTask.End = new LabeledMapLocation("Madrid", new GeoCoordinate(40.420299, 3.705770));

mapDirectionsTask.Show();

Las propiedades a utilizar son:

  • Start. Localización inicial (LabeledMapLocation).
  • End. Localización final (LabeledMapLocation).
Lanzadores WP8 03

MapsDirectionsTask

El siguiente lanzador (MapDownloaderTask) nos permite descargas mapas de Nokia para trabajar con ellos offline. Su uso es sumamente sencillo:

MapDownloaderTask mapDownloaderTask = new MapDownloaderTask();

mapDownloaderTask.Show();

El resultado:

Lanzadores WP8 04

MapDownloaderTask

Continuamos con el lanzador SaveAppointmentTask que nos permite abrir la aplicación de calendario del sistema con el formulario de creación de cita abierto:

SaveAppointmentTask saveAppointmentTask = new SaveAppointmentTask();
saveAppointmentTask.StartTime = DateTime.Now.AddHours(1);
saveAppointmentTask.EndTime = DateTime.Now.AddHours(2);
saveAppointmentTask.Subject = "Artículo WP8";
saveAppointmentTask.Details = "Escribir artículo Lanzadores en Windows Phone 8";
saveAppointmentTask.Reminder = Reminder.FiveMinutes;

saveAppointmentTask.Show();

Las propiedades posibles a utilizar son:

  • StartTime. Fecha y hora de comienzo de la cita (DateTime).
  • EndTime. Fecha y hora final de la cita (DateTime).
  • Subject. Asunto de la cita.
  • Details. Detalles de la cita.
  • Reminder. Junto a la cita podemos añadir un recordatorio de la misma (Reminder).
  • Location. Localización de la cita (String).
  • AppointmentStatus. Enumeración de tipo AppointmentStatus que utilizamos para indicar el estado de la cita que afecta a como se tratará el bloque de la cita posteriormente.
  • IsAllDayEvent. Propiedad de tipo bool que utilizamos para indicar si la cita ocupa todo el día o no.
Lanzadores WP8 05

SaveAppointmentTask

Y para finalizar, nos centramos en ShareMediaTask que permite compartir un contenido multimedia en redes sociales:

private void btnShareMediaTask_Click_1(object sender, RoutedEventArgs e)
{
     PhotoChooserTask photoChooserTask = new PhotoChooserTask();
     photoChooserTask.ShowCamera = true;
     photoChooserTask.PixelHeight = 300;
     photoChooserTask.PixelWidth = 300;
     photoChooserTask.Completed += photoChooserTask_Completed;

     photoChooserTask.Show();
}

void photoChooserTask_Completed(object sender, PhotoResult e)
{
     ShareMediaTask shareMediaTask = new ShareMediaTask();
     shareMediaTask.FilePath = e.OriginalFileName;

     shareMediaTask.Show();
}

La propiedad a utilizar es FilePath. Espera la ruta al archivo multimedia a compartir:

Lanzadores WP8 06

ShareMediaTask

Puedes descargar el ejemplo realizado a continuación:

En futuras entradas algunos de estos lanzadores los utilizaremos viendolos con más detalle. Si os surgen dudas o sugerencias podéis dejarlas en los comentarios de la entrada.

Más información

[Tips and Tricks] Windows Phone 8. Estado de la batería.

WPBatteryIntroducción

Entre la gran cantidad de APIs que teníamos disponibles en Windows Phone 7 había ciertos aspectos sobre los que no teníamos control programáticamente. Uno de dichos aspectos era la batería.

Con el nuevo SDK de Windows Phone 8 contamos con una API pensada para poder obtener el estado de la batería, porcentaje restante y tiempo restante. En la entrada actual vamos a trabajar con esta API y sus posibilidades.

Controlando el estado de la batería

Dentro del namespace Windows.Phone.Devices.Power contamos con una clase llamada Battery que implementa la interfaz IBattery. Esta clase cuenta con un método GetDefault() que nos devolverá el objeto batería por defecto. Una vez obtenido el objeto batería por defecto, podemos acceder a sus propiedades de forma simple:

var remainingChargePercent = Battery.GetDefault().RemainingChargePercent;
var remainingDischargeTime = Battery.GetDefault().RemainingDischargeTime;

La propiedad remainingChargePercent nos devolverá el porcentaje restante hasta el fin de la batería.

La propiedad remainingDischargeTime nos devolverá el tiempo de carga restante en formato TimeSpan.

Extra

También podemos gestionar mediante un simple evento el estado de la batería gracias al evento RemainingChargePercentChanged que notificará cada vez que el porcentaje de la batería cambie (baje al menos un 1% con respecto al valor actual).

Más información

¿Qué no puedo hacer en el emulador de Windows Phone 8?

Introducción

Además de las herramientas necesarias para el desarrollo (Visual Studio y Expression Blend), tras instalar el SDK tenemos a nuestra disposición un emulador del sistema.

Lo más importante y la idea fundamental que se intenta transmitir al hablar del emulador es que nos permitirá probar de manera rápida y efectiva la aplicación que está en desarrollo sin la necesidad del dispositivo físico pero el emulador NO equivale a un dispositivo físico.

Bien, entonces…

¿Qué no se puede hacer en el emulador?

  • Batería. A nivel de desarrollo contamos con APIs para comprobar el estado de la batería. Es una opción interesante para cambiar el comportamiento de nuestra aplicación según el nivel de batería. Sin embargo, en el emulador el nivel de batería siempre será el 100%.
  • Brújula. Todo dispositivo Windows Phone 8 cuenta con brújula. No así el emulador. Necesitaremos de un dispositivo para recibir información de este sensor de nuestras aplicaciones.
  • Cámara. Si utilizamos la cámara del dispositivo de algun modo, ya sea para tomar fotografías o videos, no podremos probar bajo el emulador. Muchos equipos cuentan con cámara, sin embargo, no podremos aprovecharnos de ellas en el emulador.
  • Giroscopio. A pesar de contar con opciones avanzadas que nos permiten recibir información simulada del acelerómetro no contamos con la simulación del giroscopio.
  • Multi Touch. No contamos con simulación por parte de ratón para gestos multitáctiles. Si el equipo que hace de Host para el emulador cuenta con pantalla multi-touch podremos utilizarla. Sin embargo, dado que la mayoría de desarrolladores no cuentan con pantallas de dichas características en sus equipos de desarrollo la opción más barata actualmente sería recibir un préstamo de un dispositivo o adquirirlo.
  • Network Roaming. El emulador siempre simula estar conectado a una red “Fake GSM”. Por lo que no podemos probar cambios de una red a otra por ejemplo.
  • Vibración. Aunque es lógico tampoco podemos probar la vibración sin un dispositivo.

Deberíamos hacer también una mención especial a otros puntos a tener en cuenta. El Isolated Storage (almacenamiento aislado) se puede emular en el simulador. Sin embargo, al cerrar la sesión en el emulador los datos se pierden. Por supuesto, en un dispositivo físico los datos del almacenamiento aislado perduran entre sesiones.

Más información

[Tips and Tricks] Windows Phone 8. LongListSelector SelectedItem no bindable.

Introducción

Si en Windows Phone entramos al Hub People podemos ver que para acceder a un contacto de nuestro listado disponemos aparte de hacer scroll como en una lista común, de una serie de cuadrados con la letra inicial de los nombres que vienen a continuación.

Si pulsamos en uno de esos cuadrados aparece un listado con todas las letras del abecedario. Si seleccionamos uno de esos cuadrados nos posiciona en la sección que comienza por la letra que hemos pulsado.

Es ideal para interfaces que van a mostrar una gran colección de elementos. Facilitamos al usuario el acceso directo a la zona que desea.

Para quienes hayan probado el Toolkit de Windows Phone, el control LongListSelector les será un viejo conocido. Efectivamente el control estaba previamente incorporado dentro del conjunto del controles del Toolkit. Ahora, en Windows Phone 8, lo tenemos incluido dentro del propio SDK.

El problema

El control arrastra un pequeño problema que ya estaba presente en su versión del Windows Phone Toolkit. No cuenta con un objeto de tipo DependencyObject para la propiedad SelectedItem.

¿Cómo nos afecta?

La propiedad SelectedItem nos indica el elemento seleccionado. Es sin duda una de las propiedades más importantes del control. Sin embargo, no podemos hacer Binding con dicha propiedad. Nos rompe una correcta implementación del patrón MVVM por ejemplo.

La solución

¿Tiene solución el problema?. Por supuesto. Ya hemos mencionado que el control no cuenta con un objeto de tipo DependencyObject para la propiedad SelectedItem. Vamos a crear una clase que deriva del control LongListSelector incluido dentro del namespace Microsoft.Phone.Controls. Creamos una propiedad de dependencia (DependencyProperty) junto a un método para controlar los cambios de selección en el control. Y lo más importante creamos una nueva propiedad SelectedItem que reemplazará la propiedad que utilizamos del control:

public class LongListSelector : Microsoft.Phone.Controls.LongListSelector
    {
        public LongListSelector()
        {
            SelectionChanged += LongListSelector_SelectionChanged;
        }

        void LongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SelectedItem = base.SelectedItem;
        }

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register(
                "SelectedItem",
                typeof(object),
                typeof(LongListSelector),
                new PropertyMetadata(null, OnSelectedItemChanged)
            );

        private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var selector = (LongListSelector)d;
            selector.SelectedItem = e.NewValue;
        }

        public new object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }
    }

Más información

Windows Phone 7.8. Actualizar tiles.

wp8-tilesIntroducción

En Windows Phone 8 y en el reciente Windows phone 7.8 contamos con nuevos tiles que componen la pantalla de inicio. Si tenemos una aplicación desarrollada para Windows Phone 7 y no queremos (o podemos) actualizarla a Windows Phone 8 podemos acceder mediante reflexión a características de la API de Tiles de Windows Phone 7.8 y Windows Phone 8. De esta forma si nuestra aplicación se ejecuta en un dispositivo Windows Phone 7 mostrará los Tiles habituales (1 único tamaño y plantilla). Sin embargo, si se ejecuta en dispositivos con Windows Phone 7.8 o Windows Phone 8 podemos ofrecer a nuestros usuarios características de los nuevos Tiles.

Suena interesante, ¿verdad?. En la entrada actual vamos a analizar como realizar esta tarea.

Utilizando los nuevos Tiles de Windows Phone 8 desde una App Windows Phone 7

Vamos a crear una aplicación Windows Phone 7 de ejemplo para probar como acceder por reflexión a las APIs de Tiles de Windows Phone 8.

Windows Phone Application

En este ejemplo para simplificar al máximo el proceso y lograr concentrar toda la atención en lo importante vamos a seleccionar un proyecto de tipo Windows Phone Application.

En el constructor de nuestra aplicación vamos a actualizar el tile de la aplicación:

ShellTile tile = ShellTile.ActiveTiles.First();

if (tile != null)
{
     StandardTileData tileData = new StandardTileData
     {
          Title = "Titulo",
          Count = 19,
          BackTitle = "Título trasero",
          BackContent = "Contenido"
     };

     tile.Update(tileData);
}

Recordamos que la API ShellTile es la que nos permite trabajar con los Live Tiles de nuestra aplicación. Para actualizar la información del Tile de la Aplicación utilizaremos el método Update de la API. Dicho método espera un objeto de tipo StandardTileData. El objeto StandardTileData incluye la información básica del Tile.

Si compilamos el resultado que obtenemos es el siguiente:

WP78 Tile 01

Modificar el archivo de manifiesto

En el explorador de soluciones hacemos clic derecho sobre el arhivo WMAppManifest.xml Elegimos la opción “Text Editor”. Justo debajo del elemento <App> debemos añadir:

<AppExtra xmlns="" AppPlatformVersion="8.0">
    <Extra Name="Tiles"/>
</AppExtra>

Usando reflexión

Dependiendo del sistema operativo donde se ejecute la aplicación debemos actualizar el tile tal y como haríamos en Windows Phone 7 o mediante reflexión. Por lo tanto, lo primero que debemos conseguir es un método rápido y sencillo para distinguir entre las distintas versiones de sistema operativo. Creamos una variable estática que almacena donde almacenaremos la versión exacta del sistema Windows Phone 7.8 (7.10.8859):

private static Version wp7Version = new Version(7, 10, 8858);

Utilizaremos la variable creada en el get de una propiedad que comparará la versión establecida con la versión del sistema devolviendo un bool. El bool será true si el sistema es Windows Phone 7.8 o Windows 8. De esta forma podremos detectar ante que versión del sistema estamos y actualizar el Tile de la Aplicación en consecuencia.

public static bool isWp8Version { get { return Environment.OSVersion.Version >= wp7Version; } }

Tan sólo debemos utilizar un simple if:

if (isWp8Version)
{

}
else
{

}

Para usar reflexión lo primero que debemos hacer es obtener un objeto de un tipo en concreto (vamos a poner un ejemplo sencillo):

var mytype = Type.GetType("assembly-name");

Invocamos al constructor del tipo:

var mynewtile = mytype.GetConstructor(new Type[] { }).Invoke(null);

Una vez creado el objeto, podemos asignar valores a sus propiedades. Lo primero que debemos hacer es obtener el tipo de la propiedad a utilizar. Accedemos a la propiedad (utilizando el nombre de la misma). Obtendremos un objeto de tipo PropertyInfo con toda la información de la propiedad:

var setMethod = instance.GetType().GetProperty("Property").GetSetMethod();

Por último, invocamos a la propiedad pasandole el valor deseado:

setMethod.Invoke(instance, new object[] { value });

El proceso es “pesado” y repetitivo. Por lo tanto, la mejor opción será crear un método que reciba la instancia, propiedad y valor para facilitarnos la vida a la hora de utilizar propiedades del tile por reflexión:

private static void SetProperty(object instance, string property, object value)
{
     var method = instance.GetType().GetProperty(property).GetSetMethod();
     method.Invoke(instance, new object[] { value });
}

Vamos a utilizar reflexión para utilizar los nuevos tiles. Primero obtenemos el tipo del objeto FlipTileData y creamos una nueva instancia. Posteriormente, utilizamos el método anteriormente creado para asignar las propiedades correspondientes con los valores deseados. Por último, actualizaremos el tile:

Type flipTileData = Type.GetType("Microsoft.Phone.Shell.FlipTileData, Microsoft.Phone");

Type shellTile = Type.GetType("Microsoft.Phone.Shell.ShellTile, Microsoft.Phone");

var tileToUpdate = ShellTile.ActiveTiles.First();

var UpdateTileData = flipTileData.GetConstructor(new Type[] { }).Invoke(null);

SetProperty(UpdateTileData, "Title", "Título");
SetProperty(UpdateTileData, "Count", 19);
SetProperty(UpdateTileData, "BackTitle", "Título Atrás");
SetProperty(UpdateTileData, "BackContent", "Contenido.");
SetProperty(UpdateTileData, "WideBackContent", "Contenido para el tile en tamaño ancho.");

shellTile.GetMethod("Update").Invoke(tileToUpdate, new Object[] { UpdateTileData });

Ejecutando nuestra aplicación Windows Phone 7 en un dispositivo (o emulador) Windows Phone 7.8 o Windows Phone 8 obtendremos el siguiente resultado:

WP78 Tile 02

De modo que, finalmente el código quedaría:

public MainPage()
{
     InitializeComponent();

     if (isWp8Version)
     {
          Type flipTileData = Type.GetType("Microsoft.Phone.Shell.FlipTileData, Microsoft.Phone");

          Type shellTile = Type.GetType("Microsoft.Phone.Shell.ShellTile, Microsoft.Phone");

          var tileToUpdate = ShellTile.ActiveTiles.First();

          var UpdateTileData = flipTileData.GetConstructor(new Type[] { }).Invoke(null);

          SetProperty(UpdateTileData, "Title", "Título");
          SetProperty(UpdateTileData, "Count", 19);
          SetProperty(UpdateTileData, "BackTitle", "Título Atrás");
          SetProperty(UpdateTileData, "BackContent", "Contenido.");
          SetProperty(UpdateTileData, "WideBackContent", "Contenido para el tile en tamaño ancho.");

          shellTile.GetMethod("Update").Invoke(tileToUpdate, new Object[] { UpdateTileData });
     }
     else
     {
          ShellTile tile = ShellTile.ActiveTiles.First();

          if (tile != null)
          {
               StandardTileData tileData = new StandardTileData
               {
                    Title = "Titulo",
                    Count = 19,
                    BackTitle = "Título trasero",
                    BackContent = "Contenido"
               };

               tile.Update(tileData);
          }
     }
}

Puedes descargar el ejemplo realizado:

Espero que lo visto en la entrada os resulte interesante además de útil. Recordar, cualquier duda o sugerencia será bienvenida en los comentarios de la entrada.

Conclusiones

Una aplicación Windows Phone 7.1 que se ejecuta en dispositivos Windows Phone 7.8 o Windows Phone 8 puede acceder mediante reflexión a características de la nueva API de Tiles. Recordar que en Windows Phone diferenciamos entre dos tipos de Tiles:

  • Tile de Aplicación.Es el acceso directo a una aplicación creado por el usuario tras anclar al incio la misma.
  • Tiles Secundarios. Se crean desde una aplicación en concreto por una acción realizada por el usuario.

¿Hasta donde podemos llegar?

  • En Tile de Aplicación sólo podemos utilizar la plantilla Flip Tile.
  • Para Tiles Secundarios podemos utilizar todas las plantillas disponibles en Windows Phone 8, Flip Tile, Iconic Tile y Cycle Tile.
  • Podemos utilizar las APIs de ShellTile o notificaciones Push para actualizar el Tile.

Más información

Error. El emulador de Windows Phone 8 no puede crear la máquina virtual

Introducción

Hace poco me encontré con un problema al arrancar el emulador de Windows Phone 8 bastante extraño y digno de compartir. Tras actualizar el sistema a Windows 8 Pro e instalar Visual Studio al arrancar el emulador para probar la aplicación desarrollada se obtiene el siguiente error:

Error

Error

¿Cómo solucionarlo?

Abrimos el “Administrador de Hyper-V”:

Hyper-V Admin

Hyper-V Admin

A continuación, seleccionamos la opción “Administrador de conmutadores virtuales”. Creamos un nuevo conmutador virtual de tipo interno (red interna). Le asignamos el nombre “Windows Phone Emulator Switch”. También debemos activar la opción “Habilitar la identificación de LAN virtual para el sistema operativo de administración”.

Switch hyperV Admin

Listo. Problema resuelto!.

Más información

Windows Phone 8. Introducción al control LongListSelector.

Un viejo conocido

Si en Windows Phone entramos al Hub People podemos ver que para acceder a un contacto de nuestro listado disponemos aparte de hacer scroll como en una lista común, de una serie de cuadrados con la letra inicial de los nombres que vienen a continuación.

Si pulsamos en uno de esos cuadrados aparece un listado con todas las letras del abecedario. Si seleccionamos uno de esos cuadrados nos posiciona en la sección que comienza por la letra que hemos pulsado.

LongListSelector

LongListSelector

Es ideal para interfaces que van a mostrar una gran colección de elementos. Facilitamos al usuario el acceso directo a la zona que desea.

Para quienes hayan probado el Toolkit de Windows Phone, el control LongListSelector les será un viejo conocido. Efectivamente el control estaba previamente incorporado dentro del conjunto del controles del Toolkit. Ahora, en Windows Phone 8, lo tenemos incluido dentro del propio SDK.

En este artículo vamos a analizar las posibilidades del control, ¿comenzamos?

RECUERDA: El control LongListSelector es como un control ListBox avanzado que puede mostrar dos listas, una  plana y otra agrupada. Ayuda a los usuarios a navegar a través de largas listas, le permite saltar entre las diferentes secciones de la lista mediante una rejilla que se superpone a la lista cuando el usuario selecciona uno de los encabezados.

NOTA: El LongListSelector incluido en el SDK de Windows Phone 8 es diferente al ya conocido LongListSelector  del Windows Phone Toolkit. Aunque a simple vista pueden parecer similares, el nuevo control expone propiedades diferentes y se utiliza de una manera ligeramente diferente.

Manos a la obra

Creamos un nuevo proyecto:

Aplicación Windows Phone

Aplicación Windows Phone

Para probar el control necesitamos una fuente de información. En nuestro ejemplo simplificaremos el proceso al máximo construyendo una colección de elementos en memoria. Vamos a mostrar una colección de teléfonos agrupados por sistema operativo. Comenzamos creando la estructura de la información a mostrar. Creamos una carpeta Models. Dentro de la carpeta vamos a crear una clase Telephone.cs:

public class Telehpone
{
    public string Name
     {
          get;
          set;
     }

     public string OS
     {
          get;
          set;
     }
}

Creamos una carpeta ViewModels donde añadimos una nueva clase llamada MainPageViewModel.cs:

public MainPageViewModel()
{

}

Necesitamos una colección de elementos para abastecer al control LongListSelector:

private List<Telehpone> _telephones;

En el constructor del ViewModel vamos a crear la colección de elementos a mostrar:

public MainPageViewModel()
{
     _telephones = new List<Telehpone>();
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 700", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 800", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 620", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 820", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Nokia Lumia 920", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "HTC Titan", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "HTC 8S", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "HTC 8X", OS = "Windows Phone" });
     _telephones.Add(new Telehpone() { Name = "Samsung Galaxy S", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "Samsung Galaxy S2", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "Samsung Galaxy S3", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "Sony Xperia S", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "Sony Xperia U", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "HTC Desire", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "HTC One S", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "HTC One X", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "HTC Sensation XL", OS = "Android" });
     _telephones.Add(new Telehpone() { Name = "iPhone 4", OS = "IOS" });
     _telephones.Add(new Telehpone() { Name = "iPhone 4S", OS = "IOS" });
     _telephones.Add(new Telehpone() { Name = "iPhone 5", OS = "IOS" });
}

Nuestro objetivo es mostrar la información agrupada por sistema operativo. De esta forma el usuario podrá pulsar sobre las cabeceras del LongListSelector (los distintos sistemas operativos móviles, los grupos) y así poder acceder al conjunto de elementos pertenecientes a un grupo de manera rápida y efectiva. Para ello, vamos a crear una pequeña clase que nos permita agrupar la información:

public class Group<T> : List<T>
{
     public Group(string name, IEnumerable<T> items)
     : base(items)
     {
          this.OS = name;
     }

     public string OS
     {
          get;
          set;
     }
}

La clase Group nos permitirá almacenar en una lista los teléfonos de un mismo sistema operativo.

NOTA: La clase es genérica con el objetivo de poder reutilizarla con otros tipos de datos.

LongListSelector Structure 1

Continuamos contruyendo la interfaz de usuario. Nos centramos en el archivo MainPage.xaml.

Vamos a definir las distintas plantillas que debemos utilizar en el LongListSelector y que ya hemos analizado previamente. Comenzamos con la plantilla GroupHeaderTemplate que definirá el aspecto de las cabeceras de cada grupo:

<DataTemplate x:Key="TelephoneGroupHeaderTemplate">
     <Border Background="Transparent" Padding="5">
          <Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="462"
          Height="62" Margin="0,0,18,0" HorizontalAlignment="Left">
               <TextBlock Text="{Binding OS}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="24" Padding="6"
               FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
          </Border>
     </Border>
</DataTemplate>

La siguiente plantilla, ItemTemplate, define el aspecto de cada elemento de la lista:

<DataTemplate x:Key="TelephoneItemTemplate">
     <Grid>
          <TextBlock Text="{Binding Name}"/>
     </Grid>
</DataTemplate>

Podemos definir ya el control LongListSelector:

<phone:LongListSelector x:Name="longListSelector"
     Background="Transparent"
     IsGroupingEnabled="True"
     LayoutMode="List"
     ItemsSource="{Binding TelephonesGrouped}"
     GroupHeaderTemplate="{StaticResource TelephoneGroupHeaderTemplate}"
     ItemTemplate="{StaticResource TelephoneItemTemplate}"/>

Si compilamos y probamos podemos observar que algo no va bien… ¿que ocurre?

Al pulsar sobre una de las cabeceras no ocurre nada. Debería de superponerse una rejilla con cada uno de los grupos de modo que permitan posicionar al usuario al inicio del grupo en la lista plana.

¿Cómo lo solucionamos?

Utilizamos la propiedad JumpListStyle para ello. Con esta propiedad indicaremos como se comporta el LongListSelector al pulsar cabeceras.

NOTA: Si no definimos la propiedad IsGroupingEnable a True la lista aparecería sin agrupar, al igual que veríamos en un ListBox.

Lo primero que haremos será utilizar dos Converters disponibles en el SDK para determinar fuente y fondo de cada grupo que aparecerá en la rejilla que superpones al pulsar una cabecera (si aparece pero con otro color o no, etc):

<phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
<phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>

A continuación, definimos el estilo JumListStyle:

<Style x:Key="TelephoneJumpListStyle" TargetType="phone:LongListSelector">
     <Setter Property="GridCellSize"  Value="480,113"/>
     <Setter Property="LayoutMode" Value="Grid" />
     <Setter Property="ItemTemplate">
          <Setter.Value>
               <DataTemplate>
                    <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="480" Height="113" Margin="6">
                         <TextBlock Text="{Binding OS}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="24" Padding="6"
                         Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/>
                    </Border>
               </DataTemplate>
          </Setter.Value>
     </Setter>
</Style>

Se lo asignamos al LongListSelector:

JumpListStyle="{StaticResource TelephoneJumpListStyle}"

De modo que finalmente quedaría así:

<phone:LongListSelector x:Name="longListSelector"
     Background="Transparent"
     IsGroupingEnabled="True"
     LayoutMode="List"
     ItemsSource="{Binding TelephonesGrouped}"
     JumpListStyle="{StaticResource TelephoneJumpListStyle}"
     GroupHeaderTemplate="{StaticResource TelephoneGroupHeaderTemplate}"
     ItemTemplate="{StaticResource TelephoneItemTemplate}"/>

NOTA: El control LongListSelector está definido dentro del namespace “Microsoft.Phone.Controls”.

Si compilamos nuestro proyecto para probar debemos obtener el siguiente resultado:

Ejemplo LongListSelector 1

Vista con todos los elementos

Ejemplo LongListSelector 2

Vista grupos

Conclusiones

Puedes descargar el ejemplo realizado:

El control LongListSelector lo tenemos ahora disponible en el SDK de Windows Phone 8. Es un control sumamente versátil con múltiples opciones de agrupación. Además, soporta virtualización de datos y de interfaz de usuario por lo que se recomienda su uso incluso para mostrar listas planas de datos (tal como haríamos con un control ListBox).

Recordar, cualquier duda o sugerencia será bienvenida en los comentarios de la entrada.

Más información