[Windows Phone] Buscar por actualizaciones desde la propia App

Introducción

Al desarrollar aplicaciones tarde o temprano
tendremos la necesidad de actualizarlas ya sea bien por necesidad, para
corregir bugs, o bien para añadir nueva funcionalidad. En ambos casos,
nuestro mayor interés es que la mayor cantidad de usuariosse actualice a
la última versión. Sin embargo, esto no siempre sucede.

¿Por que?

Podemos arrojar varias posibles causas:

  • El usuario utiliza el móvil con internet de manera muy puntual.
  • No tiene la Store anclada al inicio y no se da cuenta de las actualizaciones.
  • No se preocupa de revisar las actualizaciones.
  • Directamente el usuario desconoce como realizar la acción.

Sin
abrir la aplicación de la Store y sin tenerla anclada al inicio puede
provocar que los usuarios tengan aplicaciones sin actualizar a la última
versión, no disfrutando de mejoras y lo que es peor sufriendo bugs que
incluso pueden estar resueltos en versiones posteriores.

Para
mejorar esta situación podemos indicarle al usuario de la disponibilidad
de una actualización disponible. Pero… ¿cómo detectamos desde nuestra
aplicación de la existencia de una actualización?

Cimbalino al rescate

Cimbalino
Windows Phone Toolkit es un completo conjunto de herramientas
destinadas a ahorrarnos tiempo y esfuerzo al desarrollar aplicaciones
para Windows Phone del que ya hablamos previamente. Entre el conjunto de
posibilidades que nos brinda, nos ofrece un servicio llamado IMarketplaceInformationService que
nos permite verificar la existencia de actualizaciones de la aplicación
dentro de la misma. Vamos a crear una Aplicación de ejemplo para
utilizar el Toolkit y poder verificar la existencia de actualizaciones.

Tras crear el proyecto, comenzamos añadiendo el Toolkit. Tenemos
disponible Cimbalino en NuGet por lo que podemos instalarlo usando Nuget Package Manager.

En las referencias del proyecto hacemos clic derecho y seleccionamos la opción Manage NuGet Packages …

En la ventana modal que nos aparece, en la parte superior derecha donde podemos realizar una búsqueda, buscamos por “cimbalino”:

Seleccionamos el primero de los elementos y pulsamos el botón Install.
Tras un breve periodo donde se procede a descargar e incluir las
librerías en las referencias del proyecto, tendremos el siguiente
resultado:

Ya con la librería instalada podemos continuar con nuestro objetivo.
Comenzamos definiendo la interfaz del ejemplo. En nuestro caso
colocaremos un botón en la interfaz para verificar la existencia de
actualizaciones. Sin embargo, la verificamos se puede realizar
perfectamente en el arranque de la aplicación.

<Button Content="Buscar Actualizaciones"/>

Le añadimos un comando a ejecutar al ser pulsado:

<Button Content="Buscar Actualizaciones" Command="{Binding ChechForUpdatesCommand}" Height="100" VerticalAlignment="Center"/>

En el ViewModel correspondiente a la interfaz contaremos con el comando:

private ICommand _chechForUpdatesCommand;
 
public ICommand ChechForUpdatesCommand
{
     get { return _chechForUpdatesCommand = _chechForUpdatesCommand ?? new DelegateCommand(ChechForUpdatesCommandDelegate); }
}
 
public void ChechForUpdatesCommandDelegate()
{
 
}

Para utilizar el servicio IMarketplaceInformationService
en la acción de nuestro comando necesitamos inyectar el servicio. Los
servicios asi como la propia ViewModel no se creará manualmente sino que
se resolverá automáticamente en tiempo de ejecución por el contenedor
de dependencia. En el contenedor utilizaremos Unity (proyecto Open
Source de Microsoft) para soportar la inyección de dependencias:

public Container()
{
     _currentContainer = new UnityContainer();
 
     //Servicios
     _currentContainer.RegisterType<IMarketplaceInformationService, MarketplaceInformationService>();
     _currentContainer.RegisterType<IMessageBoxService, MessageBoxService>();
     _currentContainer.RegisterType<IMarketplaceDetailService, MarketplaceDetailService>();
 
     //Vistas
     _currentContainer.RegisterType<MainViewModel>(new ContainerControlledLifetimeManager());
}

En el punto de entrada de la ViewModel (el contructor) inyectaremos los
servicios necesarios previamente registrados en el contenedor:

public MainViewModel(IMarketplaceInformationService marketplaceInformationService, IMessageBoxService messageBoxService,
IMarketplaceDetailService marketplaceDetailService)<br />
{
     _marketplaceInformationService = marketplaceInformationService;
     _messageBoxService = messageBoxService;
     _marketplaceDetailService = marketplaceDetailService;
}

Con el servicio disponible, verificaremos la versión de la aplicación (por reflection):

var data = new AssemblyName(Assembly.GetExecutingAssembly().FullName);
var currentVersion = data.Version;

Y la compararemos con la versión disponible en la Store:

Version updatedVersion;
Version.TryParse(node.Entry.Version, out updatedVersion);

Para obtener la versión de la Store utilizaremos el método GetAppInformation del cual también tenemos versión asíncrona del servicio MarketPlaceInformationService.

En el resultado obtenido por la petición podemos obtener una enorme
cantidad de la información relacionada con la apliación publicada en la
Store:

  • Título
  • Versión
  • Publicador
  • Icono
  • Fotos
  • Fecha de publicación
  • Puntuaciones

Por lo que el servicio puede ser utilizado para una enorme variedad
de situaciones con información relevante del estado de la apliación en
la Store.

Comparamos versiones, si la actual es superior a la de la Store,
tenemos actualización disponible. Utilizamos el servicio
MessageBoxService de Cimbalino para notificar al usuario:

if (updatedVersion > currentVersion
&&
_messageBoxService.Show(Resources.AppResources.DownloadUpdate,
Resources.AppResources.UpdateAvalaible, MessageBoxButton.OKCancel) ==
MessageBoxResult.OK)
{
 
}

Por último, si el usuario desea abriremos la Store directamente con la
apliación para que solo tenga que pulsar un botón para actualizar. Para
ello usaremos otro servicio de Cimbalino, MarketPlaceReviewService:

_marketplaceDetailService.Show(ProductId);

NOTA: Dado que la aplicación de ejemplo no esta
en la Store, para este ejemplo hemos utilizado una aplicación ya
publicada en la Store en concreto Dev Center que va por su
versión 1.4.1312.4.

Fácil, ¿verdad?. Tenemos disponible el ejemplo realizado a continuación:

Más información

[Tips and Tricks] Windows Phone. DeviceStatus. Uso de memoria

Introducción

Por encima de cuidar detalles como la
funcionalidad o la estética de nuestra aplicación, tenemos que lograr un
objetivo que parece simple pero que a veces se escapa, nuestra
aplicación debe funcionar correctamente bajo todas las condiciones en
todos los dispositivos para la que sea lanzada. Un fallo comun suele ser
que se escape la gestión de memoria de la aplicación pudiendo obtener una excepción de tipo OutOfMemoryException. Ya vimos como el control MemoryCounter del Coding4Fun Toolkit nos ayuda a saber el uso de memoria en todo momento. También tenemos disponible la herramienta Windows Phone Performance Analysis
para poder analizar el uso de memoria de nuestra aplicación entre otras
opciones. Sin embargo, el propio SDK nos incluye la posibilidad de
saber el uso de memoria de nuestra aplicación e incluso el límite máximo
de uso de memoria o la memoria disponible del dispositivo. Vamos a
aprender como realizar esta tarea en este artículo.

Monitorear la memoria

Tenemos disponible en el SDK de Windows Phone la API DeviceStatus
que nos permite obtener información del hardware del dispositivo como
la cantidad de memoria o la versión del sistema por ejemplo. Además,
tenemos disponible una serie de eventos a los que podemos suscribirnos
para recibir una notificación cuando un parámetro del sistema cambia.

Vamos a realizar un ejemplo práctico donde utilizar la API DeviceStatus. Creamos un nuevo proyecto:

La plantilla seleccionada será “Windows Phone Application
para simplificar al máximo el ejemplo. Comenzamos creando la base de
nuestra interfaz. Añadiremos dos botones, uno para aumentar el consumo
de memoria y otro para liberarla:

<Button Content="Aumenta consumo memoria"/>
<Button Content="Libera consumo memoria"/>

Añadimos sus eventos clic:

<Button Content="Aumenta consumo memoria" Click="AumentaMemoria_Click" />
<Button Content="Libera consumo memoria" Click="LiberaMemoria_Click"/>

Y en el code-behind:

private void AumentaMemoria_Click(object sender, RoutedEventArgs e)
{

}

private void LiberaMemoria_Click(object sender, RoutedEventArgs e)
{

}

Creamos una colección de Bytes para cargar en memoria:

List<Byte[]> _memoria;

En el primer botón añadimos 10MB al uso de memoria cada vez que sea
pulsado. En el segundo, limpiamos la colección y llamamos el recolector
de basura:

private void AumentaMemoria_Click(object sender, RoutedEventArgs e)
{
_memoria.Add(new Byte[1024 * 1024 * 10]);
}

private void LiberaMemoria_Click(object sender, RoutedEventArgs e)
{
_memoria.Clear();
GC.Collect();
}

Hasta aqui todo lo necesario para poder probar la memoria, podemos
aumentarla y liberarla. Sin embargo, no tenemos ahora mismo posibilidad
de saber que consumo esta realizando la aplicación. Vamos a añadir en
nuestra interfaz un TextBlock donde mostrar la información relacionada
con el uso de memoria:

Vamos a crear un método que actualice el texto del TextBlock anterior
con la información relacionada con la memoria. Dentro del método
usaremos la API DeviceStatus para acceder a ciertas propiedades
relacionadas con la memoria. Las propiedades son:

private void ActualizarDatos()
{
Data.Text = String.Format(@"
Actual: {0}MB
Pico máximo: {1}MB
Límite de uso: {2}MB
Total dispositivo: {3}MB",
(DeviceStatus.ApplicationCurrentMemoryUsage / 1000000).ToString(CultureInfo.InvariantCulture),
(DeviceStatus.ApplicationPeakMemoryUsage / 1000000).ToString(CultureInfo.InvariantCulture),
(DeviceStatus.ApplicationMemoryUsageLimit / 1000000).ToString(CultureInfo.InvariantCulture),
(DeviceStatus.DeviceTotalMemory / 1000000).ToString(CultureInfo.InvariantCulture));
}

Para finalizar llamaremos al método en los clic de los botones para
actualizar los valores en pantalla cada vez que pulsemos uno de ellos:

ActualizarDatos();

Sin duda una forma sencilla para poder consultar el uso de memoria. Sin
embargo, no es práctico en nuestras aplicaciones mostrar la información
en pantalla. Para solventar esa situación, podemos realizar un sencillo
Helper, llamado MemoryHelper, que contenga un método
que obtendrá la misma información cada X segundos y las mostrará en la
ventana de Output de Visual Studio:

public static void GetMemoryData(int seconds)
{
_timer = new Timer(state =>
{
string result = string.Empty;
result += String.Format(@"
Fecha: {0}
Actual: {1}MB
Pico máximo: {2}MB
Límite de uso: {3}MB
Total dispositivo: {4}MB",
DateTime.Now.ToLongTimeString(),
(DeviceStatus.ApplicationCurrentMemoryUsage / 1000000).ToString(CultureInfo.InvariantCulture),
(DeviceStatus.ApplicationPeakMemoryUsage / 1000000).ToString(CultureInfo.InvariantCulture),
(DeviceStatus.ApplicationMemoryUsageLimit / 1000000).ToString(CultureInfo.InvariantCulture),
(DeviceStatus.DeviceTotalMemory / 1000000).ToString(CultureInfo.InvariantCulture));

Deployment.Current.Dispatcher.BeginInvoke(() => Debug.WriteLine(result));
},
null,
TimeSpan.FromSeconds(seconds),
TimeSpan.FromSeconds(seconds));
}

Podéis descargar el ejemplo a continuación:


Más información

[Tips and Tricks] Windows Phone. Aumentar la cantidad de memoria a utilizar por nuestras Apps

Uso de memoria en Windows Phone 8

Con la maduración del
mercado con respecto a Windows Phone, contamos con una variedad de
dispositivos con distintas características. Una de las características
que de forma comun varía entre diferentes dispositivos es la memoria
RAM. Contamos con dispositivos con 512MB, 1GB o 2GB de RAM. Para llegar a
la mayor cantidad de usuarios posibles tenemos que adaptar nuestra
aplicación para que funcione correctamente bajo cualquier circunstancia.

Límites de memoria

Los límites de uso de memoria son los siguientes:

El límite de memoria viene marcado por la memoria total del
dispositivo. Contamos con tres categorías, teléfonos con memoria baja
con 512MB como por ejemplo el Nokia Lumia 520, teléfonos con 1GB como
por ejemplo el Nokia Lumia 925 y teléfonos con 2GB como el Nokia Lumia
1520.

En aplicaciones utilizando XAML los límites son 150MB en dispositivos de baja memoria, 300MB en dispositivos de 1GB y 2GB.

Sin
embargo, si nuestra aplicación lo requiere podría llegar a aumentar el
límite de consumo de memoria en 30MB en dispositivos de baja memoria,
80MB en dispositivos de 1GB y en 270MB en dispositivos de 2GB (por ahora
el Nokia Lumia 1520, pensando en el uso de recursos de alta definición
con pantallas de gran tamaño).

Aumentar la cantidad disponible

Por lo tanto, si nuestra aplicación requiere un mayor consumo de memoria podemos aumentar los límites. Bien, pero… ¿como?

Lo
podemos hacer con facilidad modificando el archivo de manifiesto.
Podemos definir una Capability que indique que nuestra aplicación
requiere un mayor consumo de memoria.

Bastará con añadir:

<App>
<FunctionalCapabilities>
<FunctionalCapability Name="ID_FUNCCAP_EXTEND_MEM"/>
</FunctionalCapabilities>
</App>

La entrada anterior permite establecer los límites en 180MB en
dispositivos de baja memoria, 380MB en dispositivos de 1GB y 570MB en
dispositivos de 2G.

Si por la naturaleza de nuestra aplicación es
inviable su funcionamiento en dispositivos de baja memoria, podemos
añadir otra Capability en el archivo de manifiesto para evitar que se
pueda instalar en estos dispositivos (no aparecería en la Store la
aplicación bajo un dispositivo de estas características). Debemos
añadir:

<App>
<Requirements>
<Requirements Name="ID_REQ_MEMORY_300"/>
</Requirements>
</App>

Más información

Dev Center: App memory limits for Windows Phone 8

Añade soporte a múltiplos idiomas en tu App Windows Phone usando Multilingual App Toolkit

Introducción

Al publicar aplicaciones en la Store podemos
hacerlo hasta en 191 países diferentes. Esto nos ofrece unas
posibilidades increíbles a la hora de llegar a un público variado y
tener un gran alcance. Sin embargo, el publicar la aplicación en
múltiples países requiere tener en cuenta ciertos aspectos. Aspectos
como si la aplicación tiene sentido o no en un pais concreto, además de
tener en cuenta aspectos que debemos adaptar en nuestra aplicación.
Probablemente aunque tu aplicación sea una gran aplicación, destacada en
la Store, si la lanzas en español en China no tendra un gran impacto.

En
la medida de lo posible, debemos localizar la aplicación a los idiomas
donde la aplicación vaya a ser lanzada. En el artículo actual vamos a
aprender a utilizar un toolkit que nos facilitará la vida a la hora de
localizar nuestras aplicaciones, Multilingual App Toolkit.

Multilingual App Toolkit

El toolkit se instala como un plugin en Visual Studio. Podemos descargar el plugin desde el siguiente enlace.

Una
vez accedido al enlace podemos descargar el toolkit en múltiples
idiomas, seleccionamos el deseado y descargamos. Tras descargar pasamos a
instalar el Toolkit. La instalación es bastante simple.

Manos a la obra!

Vamos a crear una Aplicación de ejemplo donde utilizar y aprender las posibilidades del Multilingual App Toolkit:

Creamos un proyecto desde la plantilla más básica para concentrar
nuestra atención en el componente que nos ocupa en esta entrada.

Vamos a realizar una aplicación muy simple, con un único botón que al ser pulsado muestra un saludo.

Los textos de nuestra aplicación deben estar en una archivo de
recursos para poder utilizar el Toolkit. En todo proyecto Windows Phone
se crea por defecto un archivo de recursos que será el utilizado.

Añadimos recursos a mostrar en el contenido del botón y en el mensaje que mostramos.

Añadimos el botón en nuestra interfaz:

<Button Content="{Binding Path=LocalizedResources.ClickButton, Source={StaticResource LocalizedStrings}}" Click="Button_OnClick"/>

Y en el code-behind:

private void Button_OnClick(object sender, RoutedEventArgs e)
{
     MessageBox.Show(AppResources.HelloMessage);
}

Trabajando con el Toolkit

Para comenzar a utilizar el Multilingual App Toolkit lo primero que
debemos hacer es habilitarlo. Desde Visual Studio, seleccionamos la
opción del menu Tools, y hacemos clic sobre Enable Multilingual App Toolkit.

Tras habilitar el Toolkit lo que nos interesa es realizar el objetivo
por el cual lo utilizamos, añadir soporte a más idiomas en nuestra
aplicación. Para ello, hacemos clic derecha sobre el proyecto bajo el
Explorador de soluciones y seleccionamos la opción Add translation languages…

Al seleccionar la opción nos aparecerá un ventana modal como la siguiente:

Podremos marcar los idiomas que queramos utilizar en nuestra
aplicación. Por cada idioma seleccionado se creará un fichero llamado AppResources.[cultura].xf en la carpeta Resources. Se creará un fichero XLIFF que puede ser exportado e importado en nuestor proyecto.

NOTA: Los ficheros .xlf son convertidos al formato .resx durante el proceso de compilación.

Una vez creado el fichero .xlf contamos el Multilingual Editor Tool. Es un editor sencillo que nos permite acceder a cada valor del recurso utilizado para traducirlo.

Cada valor traducible lleva asociado un icono que nos indica su
estado. Podemos marcar cada texto como traducido, pendiente de revisión,
etc. Estos estados son muy útiles cuando la traducción se realiza por
múltiples personas.

Si dominamos el idioma al que se realiza la traducción podemos
realizarla nosotros mismos. Tan solo basta con seleccionar el valor a
traducir y en el campo “Conversión” escribir el valor traducido.

Sin embargo, en la mayoría de ocasiones no dominaremos todos los idiomas en los que deseamos publicar la aplicación.

¿Qué hacemos en estos casos?

Tenemos varias opciones. Por un lado podemos utilizar el servicio de
Microsoft Translator. En la herramienta Multilungual Editor Tool podemos
pulsar el botón “Traducir” con la opción “Traducir todo” y se realizará
una traducción automática. También podemos hacer clic derecho
directamente sobre el fichero .xlf y seleccionar la opción Generate machine translations:

Una opción válida pero no ideal. Una traducción literal a veces pierde sentido o no significa lo mismo en distintos idiomas.

¿Qué hacer?

Que lo traduzca una persona en lugar de un proceso automática.
Podemos exportar el fichero, enviarlo a un traductor, recibir el fichero
traducido e importarlo en nuestro proyecto. Lo que haremos será
compartir un fichero en formato XLIFF soportado por multitud de
herramientas.

Una vez que recibimos el fichero traducimos podremos utilizarlo con facilidad, solo bastará importarlo.

Ya solo quedaría probar la traducción. Para ello bastará con modificar
el lenguaje utilizado en un dispositivo o en el emulador. Tenemos
información al respecto aqui.

Podéis descargar el ejemplo a continuación:

Más información