25

Jan

Push notifications in Mango: eliminazione delle tile e background agents

Nel post precedente abbiamo visto come creare più tile dalla nostra applicazione e come gestire la navigazione e i deep link in modo che, utilizzando una tile  secondaria, l’utente possa accedere direttamente ad una sezione specifica della nostra app.

In questo post chiuderemo la panoramica sulle novità legate alle push notifications introdotte in Mango: daremo all’utente la possibilità di rimuovere una tile secondaria direttamente dall’applicazione e realizzeremo un background agent, in grado di aggiornare le tile.

Rimuovere una tile

Le tile secondarie si comportano in tutto e per tutto come le tile tradizionali: il modo più semplice per l’utente, perciò, per rimuoverle è tenere premuto il dito su una di esse e poi, una volta entrati in modalità di “edit” della home, premere l’apposita icona di cancellazione.

In linea di massima, però, è una buona idea prevedere la possibilità di eliminare le tile anche dall’applicazione stessa: ecco perciò che andremo a modificare l’applicazione che abbiamo realizzato nel post precedente per far si che i pulsanti che abbiamo creato per aggiungere le tile secondarie supportino una duplice funzione: creazione se la tile non esiste, eliminazione se la tile esiste già.

Innanzitutto, la prima cosa che facciamo è determinare quali tile secondarie sono già presenti in home, così da adattare di conseguenza l’etichetta dei nostri pulsanti:

void MainPage_Loaded(object sender, RoutedEventArgs e)
      {
      //aggiorno la label dei pulsanti in base alla presenza o meno delle tile secondarie
      foreach (ShellTile activeTile in ShellTile.ActiveTiles)
      {
      if (activeTile.NavigationUri.ToString().Contains("ID=1"))
      isTile1Pinned = true;
      if (activeTile.NavigationUri.ToString().Contains("ID=2"))
      isTile2Pinned = true;
      if (activeTile.NavigationUri.ToString().Contains("ID=3"))
      isTile3Pinned = true;
      }

      if (isTile1Pinned)
      btnTile1.Content = "Remove tile 1";
      if (isTile2Pinned)
      btnTile2.Content = "Remove tile 2";
      if (isTile3Pinned)
      btnTile3.Content = "Remove tile 3";
      }

Come abbiamo già visto nella prima parte di questo tutorial, il cuore per interagire con le tile secondarie pinnate in home è la proprietà ActiveTiles, di tipo IEnumerable, messa a disposizione dalla classe ShellTile. Ciclando questa collezione siamo in grado di accedere a tutte le tile disponibili in home: la prima sarà sempre quella principale (caratterizzata da uno “/” come NavigationUri). Attenzione! ActiveTiles contiene sempre la tile predefinita, anche se questa non è pinnata in home page. Questo perché avremo la possibilità di aggiornarla comunque e far si che, nel momento in cui l’utente deciderà di fare il pin in home page, la tile sia già alla versione più recente.

Tornando al nostro codice, quello che facciamo è semplicemente verificare se il NavigationUri contiene il parametro che identifica la nostra tile (ID=) e aggiornare di conseguenza l’etichetta del pulsante e una variabile booleana, la quale ci serve per introdurre la seconda modifica alla nostra applicazione: i pulsanti utilizzati per creare la tile dovranno infatti servire anche a rimuoverla, nel caso in cui questa sia già presenta in home. Per determinare se la tile è già in home o meno useremo proprio le variabili booleane che abbiamo valorizzato in fase di caricamento della pagina. Ecco perciò che il codice associato al Click di ogni pulsante cambierà in questo modo:

private void CreateTile1_Click(object sender, RoutedEventArgs e)
      {
      if (!isTile1Pinned)
      {
      StandardTileData tile1 = new StandardTileData
      {
      Title = "Tile 1",
      BackContent = "I'm the first tile",
      BackgroundImage = new Uri("/Images/Background1.png", UriKind.Relative)
      };

      ShellTile.Create(new Uri("/DetailPage" + ".xaml?ID=1", UriKind.Relative), tile1);
      }
      else
      {
      ShellTile.ActiveTiles.SingleOrDefault(x => x.NavigationUri.ToString().Contains("ID=1")).Delete();
      isTile1Pinned = false;
      btnTile1.Content = "Add tile 1";
      }
      }

Innanzitutto, verifichiamo il valore della corrispettiva proprietà booleana (nell’esempio, trattandosi dell’evento associato al pulsante per gestire la prima tile, la variabile di riferimento è isTile1Pinned): se questa è a false, allora creiamo la tile nello stesso modo in cui abbiamo fatto nel post precedente. Se invece è a false allora la tile è già presente e dobbiamo rimuoverla: in questo caso, grazie a LINQ, andiamo a recuperare la tile che ci interessa (nell’esempio, quella identificata dall’ID 1) e chiamiamo il metodo Delete.

Aggiorniamo le tile con un background agent

In realtà, grazie al codice che abbiamo introdotto per supportare la rimozione delle tile è molto semplice realizzare un background agent che le aggiorni in maniera indipendente: il cuore dell’agent, infatti, sarà anche in questo caso la collezione ActiveTiles, che cicleremo per interagire con ognuna delle tile pinnate in home page.

Se non lo avete già fatto, prima di procedere vi consiglio di leggere i tutorial dedicati ai background agent: se invece siete già esperti sull’argomento, allora saprete già cosa fare. Aggiungete alla soluzione un nuovo progetto di tipo Windows Phone Task Scheduler Agent e avrete a disposizione la classe TaskScheduler, nella quale andremo a definire il metodo OnInvoke (che, vi ricordo, viene chiamato ogni qualvolta il background agent viene eseguito dal sistema operativo).

protected override void OnInvoke(ScheduledTask task)
      {
      foreach (ShellTile activeTile in ShellTile.ActiveTiles)
      {
      string id = string.Empty;
      if (activeTile.NavigationUri.ToString().Contains("ID="))
      id = GetId(activeTile.NavigationUri.ToString());

      StandardTileData data = new StandardTileData
      {
      Title = "Tile " + id,
      BackContent = DateTime.Now.ToString()
      };

      activeTile.Update(data);
      }

      NotifyComplete();
      }

Andremo ad aggiornare ognuna delle tile inserendo sul retro la data e l’ora corrente: ci serve però recuperare l’ID di ogni tile, così da mostrarlo nel titolo. C’è poco da commentare questo codice, dato che è lo stesso principio che abbiamo applicato in precedenza per determinare quali tile erano pinnate in home page e quali no. L’unica differenza è che in questo caso sfruttiamo un helper (un metodo chiamato GetId) che, utilizzando le funzioni messe a disposizione dal framework per interagire con le stringhe, estrae l’ID della tile dal NavigationUri.

L’ultimo step mancante è il collegamento tra il background agent e l’applicazione: innanzitutto, dobbiamo aggiungere il task allo ScheduledActionService di Windows Phone e lo facciamo nel momento in cui la nostra applicazione viene inizializzata.

public MainPage()
      {
      InitializeComponent();
      Loaded += new RoutedEventHandler(MainPage_Loaded);
      //aggiungo il background agent tra i servizi in background di Windows Phone
      ScheduledAction action = ScheduledActionService.Find("TileAgent");
      if (action != null)
      ScheduledActionService.Remove("TileAgent");

      PeriodicTask task = new PeriodicTask("TileAgent")
      {
      Description = "Updates the tiles with the latest date and time"
      };

      ScheduledActionService.Add(task);
      }

Infine, ci basta aggiungere una reference al background agent nella nostra applicazione per far si che Visual Studio aggiunga automaticamente al file di manifest la definizione del nostro task.

Se abbiamo fatto tutto correttamente, nel momento in cui usciremo dalla nostra applicazione il background agent verrà eseguito e noteremo tutte le tile secondarie pinnate in home page aggiornarsi di conseguenza.

In conclusione

Le potenzialità che Mango ci offre relative alle notifiche e all’interazione con le tile sono veramente interessanti e aprono una serie di scenari che con la versione 7.0 erano impensabili. L’importante è non abusarne e lasciare sempre all’utente la possibilità di scegliere e di decidere (ricordate il motto “al centro l’utente”?). Un’applicazione che riempie di tile la home page del telefono sicuramente non sarà ben vista dagli utenti!

Di seguito, trovate il link per scaricare il codice sorgente del progetto utilizzato in questo tutorial.

by Il blog di Matteo Pagani on 1/25/2012
Post archive