[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (5 de N)

Hola a todos!

En esta quinta entrega de la serie, tras haber visto como funcionan los contratos en las aplicaciones metro, vamos a profundizar un poco más con tres contratos muy útiles: buscar, compartir y configuración. Cada uno de estos contratos va a dar una gran funcionalidad a nuestra aplicación e integrarla con la forma de trabajar de Windows 8. Empecemos!

Search

El contrato de búsqueda permite que el usuario consulte a nuestra aplicación desde cualquier parte del sistema:

image

En esta pantalla, además de buscar aplicaciones, configuraciones o archivos, podemos buscar dentro de las propias aplicaciones listadas a la derecha. Si nuestra aplicación soporta el contrato de búsqueda vendrá listada aquí también.  Si por ejemplo escogemos la aplicación Weather y buscamos una ciudad, recibiremos resultados que podremos escoger:

image

¿Qué necesitamos para comenzar? En primer lugar, como recordaréis del último artículo, necesitamos indicar en las declaraciones de nuestra aplicación (package.appxmanifest) que deseamos soportar el contrato de búsqueda. Lo siguiente es que en nuestra clase App controlemos la activación mediante una búsqueda, con el método OnSearchActivated, lo que vamos a hacer en este caso es llamar a un método de nuestra página que recogerá el texto introducido por el usuario y lo mostrará en pantalla:

BlankPage.xaml.cs
  1. public void SetSearchQuery(string query)
  2. {
  3.     txtSearchQuery.Text = string.Format(«Search query:{0}», query);
  4. }

 

App.xaml.cs
  1. protected override void OnSearchActivated(SearchActivatedEventArgs args)
  2. {
  3.     base.OnSearchActivated(args);
  4.  
  5.     if (Window.Current.Content == null)
  6.     {
  7.         Window.Current.Content = new BlankPage();
  8.         Window.Current.Activate();
  9.     }
  10.  
  11.     ((BlankPage)Window.Current.Content).SetSearchQuery(args.QueryText);
  12. }

Si realizamos un despliegue de nuestra aplicación y a continuación abrimos la búsqueda de Windows, veremos que ya aparece listada y que al seleccionarla se activa y muestra el texto que hayamos indicado. Pero no hace mucho más, no nos ofrece sugerencias como la aplicación del tiempo… vamos a solucionar esto desde nuestra página BlankPage.xaml.

En primer lugar necesitamos añadir un using al namespace Windows.ApplicationModel.Search y a continuación crearemos dos variables privadas en nuestra clase, una será lista con distintas palabras y la otra almacenará la referencia al panel de búsqueda:

Variables
  1. private SearchPane searchPane;
  2. private List<string> list = new List<string>() { «prueba», «yeray», «julin», «Ferreiro», «Plain Concepts» };

Ahora, en el constructor vamos a obtener la instancia actual de la búsqueda y manejar el evento SuggestionsRequested que nos llegará cuando el usuario escriba en la caja de búsqueda:

Constructor
  1. public BlankPage()
  2. {
  3.     this.InitializeComponent();
  4.  
  5.     this.searchPane = SearchPane.GetForCurrentView();
  6.     this.searchPane.SuggestionsRequested += searchPane_SuggestionsRequested;
  7. }

De esta forma, cada vez que el usuario escriba en la caja de búsqueda, nos llegará la llamada al evento SuggestionsRequested y podremos obtener la consulta del usuario y añadir las sugerencias que coincidan (usando nuestro propio criterio de coincidencia) al panel de sugerencias:

SuggestionsRequested
  1. void searchPane_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
  2. {
  3.     args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list.FindAll(i => i.Contains(args.QueryText)).ToList());
  4. }

También disponemos de más métodos para añadir solo una sugerencia o, por ejemplo, añadir un texto de separación usando el método AppendSearchSeparator:

AppendSearchSeparator
  1. void searchPane_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
  2. {
  3.     args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list.FindAll(i => i.Contains(args.QueryText)).ToList());
  4.     args.Request.SearchSuggestionCollection.AppendSearchSeparator(«Another sugestions»);
  5.     args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list.FindAll(i => i.Contains(args.QueryText)).ToList());
  6. }

El resultado, podemos mostrar sugerencias, obtener las búsquedas y reaccionar de forma adecuada:

image

Share

El contrato de Share, compartir, nos permite intercambiar información entre aplicaciones. En Windows Phone 7.5 teníamos dos lanzadores, ShareStatusTask y ShareLinkTask, que nos permitían compartir texto o enlaces en las redes sociales configuradas en el sistema. En Windows 8 el contrato Share tiene un sentido mucho más amplio. Podemos hacer que nuestra aplicación sea una fuente de información y que otras aplicaciones puedan recoger esa información y usarla. De la misma forma podemos declarar que somos capaces e utilizar cierto tipo de información, de esa forma cuando alguna aplicación comparta, por ejemplo textos o imágenes, apareceremos en la lista de posibles destinos.

Esta operación de compartir información, como ya hemos comentado, consta de dos partes: la fuente de datos y el destino al que compartir. Veamos a continuación como implementar cada uno:

Share source

Nuestra aplicación puede contener información que el usuario quiera tratar, compartir, editar o modificar en otra aplicación. Por ejemplo, podemos tener una aplicación de Rss sobre noticias y el usuario puede tener una aplicación donde organiza todos los artículos que le parecen interesantes, podemos compartir las Urls de los artículos y que otras aplicaciones los recojan.

¿Como podemos hacerlo? Muy sencillo, lo primero que necesitamos es prepararnos para poder transferir datos, obteniendo una instancia de la clase DataTransferManager del namespace Windows.ApplicationModel.DataTransfer y manejando el evento DataRequested para cuando otra aplicación nos solicite datos:

DataTransferManager
  1. DataTransferManager datatransferManager;
  2. datatransferManager = DataTransferManager.GetForCurrentView();
  3. datatransferManager.DataRequested += datatransferManager_DataRequested;

A continuación vamos a crear la interface de usuario que nos permita compartir un texto introducido por el usuario:

XAML
  1. <Grid Background=»{StaticResource ApplicationPageBackgroundThemeBrush}«>
  2.     <Grid Margin=»110,20,20,20″>
  3.         <Grid.RowDefinitions>
  4.             <RowDefinition Height=»Auto»></RowDefinition>
  5.             <RowDefinition></RowDefinition>
  6.         </Grid.RowDefinitions>
  7.             
  8.         <TextBlock Text=»Windows 8 share source» FontSize=»36″></TextBlock>
  9.             
  10.         <StackPanel Grid.Row=»1″ Margin=»0,12,0,0″>
  11.             <TextBlock Text=»Texto a compartir» FontSize=»16″></TextBlock>
  12.             <TextBox Name=»txtText» Height=»100″ TextWrapping=»Wrap» AcceptsReturn=»True» Margin=»0,12,0,12″></TextBox>
  13.             <Button Content=»Compartir» Click=»Button_Click_1″></Button>
  14.         </StackPanel>
  15.     </Grid>
  16. </Grid>

En el evento del botón compartir mostramos la UI de compartir:

Button_click
  1. private void Button_Click_1(object sender, RoutedEventArgs e)
  2. {
  3.     DataTransferManager.ShowShareUI();
  4. }

Esto provocará que el sistema lance el evento DataRequested para identificar el tipo de datos que vamos a compartir y otras propiedades como el título y la descripción de la información que estamos compartiendo:

DataRequested
  1. void datatransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
  2. {
  3.     args.Request.Data.Properties.Title = «Compartiendo texto»;
  4.     args.Request.Data.Properties.Description = «Ejemplo de como usar el contrato Share»;
  5.     args.Request.Data.SetText(this.txtText.Text);
  6. }

Si ejecutamos nuestra aplicación, escribimos un texto y presionamos el botón compartir, aparecerá a la derecha una lista de las aplicaciones que pueden trabajar con la información que hemos expuesto:

image

Si a continuación seleccionamos la aplicación de correo, aparecerá directamente la vista de envío de un nuevo correo, con los datos que hemos indicado al compartir introducidos:

image

Como podemos observar es realmente sencillo usar la comunicación entre aplicaciones. Pero no solo podemos compartir texto, también podemos compartir imágenes o cualquier otro tipo de datos. Vamos a usar un FileOpenPicker, del namespace Windows.Storage.Pickers  para poder seleccionar una imagen de nuestro pc y compartirla:

Obtener una imágen
  1. FileOpenPicker imagePicker = new FileOpenPicker
  2. {
  3.     ViewMode = PickerViewMode.Thumbnail,
  4.     SuggestedStartLocation = PickerLocationId.PicturesLibrary,
  5.     FileTypeFilter = { «.jpg», «.png», «.bmp», «.gif», «.tif» }
  6. };
  7.  
  8. this.imageFile = await imagePicker.PickSingleFileAsync();

En el evento DataRequested podemos usar el método SetBitmap para establecer la imagen a compartir:

SetBitmap
  1. args.Request.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(this.imageFile));

Pero la aplicación de correo no es capaz de compartir imágenes, por lo que no aparecerá ninguna aplicación disponible, no hay problema, vamos a ver como podemos crear una aplicación que pueda recibir imágenes o texto de forma indistinta.

Share target

Ahora que ya sabemos como hacer que nuestra aplicación se comunique con el resto del sistema usando las capacidades de compartir, veamos como podemos recibir información de otras aplicaciones, exponiéndonos como destino de los datos. Lo primero que necesitamos hacer es añadir a nuestra aplicación el contrato de Share Target y los tipos de datos que soportamos, editando la configuración del archivo Package.appxmanifest en este caso usaremos los tipos de datos de texto e imágenes:

image

Una vez añadidos estos tipos de datos que deseamos soportar, vamos a editar nuestro archivo App.xaml.cs para que soporte la activación de nuestra aplicación mediante el contrato Share, la entrada se realizará por el método OnShareTargetActivated:

OnShareTargetActivated
  1. protected async override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
  2. {
  3.     BlankPage shareTargetPage = new BlankPage();
  4.     await shareTargetPage.ShowData(args);
  5. }

Lo que hemos hecho es cargar nuestra página principal, aunque podría ser una página especial para cuando recibamos datos a compartir, y llamar a un método de esta página que hemos creado y será el encargado de cargar y mostrar todos los datos recibidos, el método ShowData:

ShowData
  1. public async Task ShowData(ShareTargetActivatedEventArgs args)
  2. {
  3.     txtApp.Text = args.ShareOperation.Data.Properties.ApplicationName;
  4.     txtTitle.Text = args.ShareOperation.Data.Properties.Title;
  5.     txtDescription.Text = args.ShareOperation.Data.Properties.Description;
  6.     txtText.Text = await args.ShareOperation.Data.GetTextAsync();
  7.  
  8.     IRandomAccessStreamReference imageReceived = await args.ShareOperation.Data.GetBitmapAsync();
  9.     IRandomAccessStreamWithContentType stream = await imageReceived.OpenReadAsync();
  10.     BitmapImage bitmapImage = new BitmapImage();
  11.     bitmapImage.SetSource(stream);
  12.     img.Source = bitmapImage;
  13.  
  14.     Window.Current.Content = this;
  15.     Window.Current.Activate();
  16. }

Igual que al compartir usamos los métodos SetBitmap y SetText, ahora usamos sus homónimos GetTextAsync y GetBitmapAsync, lo que nos permite obtener la imagen seleccionada por el usuario en la otra aplicación y el texto que escribió y mostrarlo en pantalla:

image

Como podemos ver, es realmente sencillo comunicar aplicaciones entre sí usando el contrato Share, además mantenemos nuestras aplicaciones independientes, pues lo único que necesitamos exponer es el tipo de datos que soportamos, nada más.

Settings

Por regla general, todas las aplicaciones tienen alguna opción que configurar, siempre hemos tenido que crear una pantalla de configuración para permitir al usuario personalizar su experiencia. En Windows 8 podemos integrar este trabajo con la barra de charms, teniendo las configuraciones de nuestra aplicación en el mismo sitio que los settings del sistema. Por defecto, automáticamente tendremos una sección de permisos, donde el usuario podrá habilitar o deshabilitar las capacidades otorgadas a nuestra aplicación. Por ejemplo, si requerimos acceso al micrófono o la localización:

image

De esta forma nos ahorramos pantallas especiales, enlaces y demás, el propio sistema se encarga de todo y además el usuario sabe donde encontrar la configuración de nuestra aplicación en cualquier momento. Además de esto, que se realiza de forma automática, podemos crear nuestras propias secciones con su contenido personalizado e integrarlo en el mismo menú de settings.

Lo que vamos a hacer es registrar nuevos botones al lanzar nuestra aplicación, en primer lugar tenemos que obtener una referencia al panel de settings actual, usando el tipo SettingsPane del namespace Windows.UI.ApplicationSettings:

SettingsPane
  1. private async Task RegisterSettings()
  2. {
  3.     SettingsPane settings = SettingsPane.GetForCurrentView();
  4.     settings.CommandsRequested += settings_CommandsRequested;
  5. }

A continuación en el evento CommandsRequested vamos a crear nuestros comandos y agregarlos a la barra de settings:

CommandsRequested
  1. void settings_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
  2. {
  3.     SettingsCommand HelpCommand = new SettingsCommand(«helpSetting», «Help», new UICommandInvokedHandler(onHelpCommand));
  4.     args.Request.ApplicationCommands.Add(HelpCommand);
  5.     SettingsCommand VideoCommand = new SettingsCommand(«videoSettings», «Video», new UICommandInvokedHandler(onVideoCommand));
  6.     args.Request.ApplicationCommands.Add(VideoCommand);
  7. }

Para cada comando además definimos un método que ejecutará al seleccionarlo:

Código comandos
  1. public async void onHelpCommand(IUICommand command)
  2. {
  3.     SettingsCommand HelpCommand = (SettingsCommand)command;
  4.     MessageDialog dlg = new MessageDialog(«Has seleccionado Help»);
  5.     await dlg.ShowAsync();
  6. }
  7.  
  8. public async void onVideoCommand(IUICommand command)
  9. {
  10.     SettingsCommand VideoCommand = (SettingsCommand)command;
  11.     MessageDialog dlg = new MessageDialog(«Has seleccionado Video»);
  12.     await dlg.ShowAsync();
  13. }

Si ejecutamos nuestra aplicación, veremos las nuevas secciones y al seleccionar una se nos mostrará el texto indicado:

image

De esta forma podemos permitir que el usuario acceda a la configuración de nuestra aplicación desde un punto unificado.

Conclusión

Con esto, hemos terminado nuestro repaso a los contratos de Windows 8, hay muchos más, pero creo que habiendo visto en profundidad los contratos de busqueda, compartir y settings, el resto no nos darán problemas. Como siempre, os dejo los proyectos con el código completo de los ejemplos que hemos visto, podéis descargarlos aquí. Espero veros a todos en próximos artículos.

Un saludo y Happy Coding!

2 comentarios sobre “[Windows 8] Apps Metro para desarrolladores Windows Phone 7.5 (5 de N)”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *