Download di file in background con Windows Phone 7.5

di Cristian Civera, in Windows Phone 7.1, Windows Phone,

Come ormai noto, Windows Phone non permette l'esecuzione multipla di applicazioni, ma esegue solo quella in foreground scelta dall'utente. Il modello scelto tutela l'utente dando la possibilità allo sviluppatore di eseguire task in background ad intervalli regolari, con il pieno controllo da parte dell'utente che può scegliere se disabilitarli o meno.

Se nella propria applicazione la necessità è quella di scaricare o caricare contenuti dal web e questi file sono di grandi dimensione, vi è la possibilità, con Windows Phone 7.5, di effettuare queste operazioni in background, senza che l'applicazione sia attiva. Questo è possibile grazie ad un engine del sistema che prende in carico le richieste di tutte le applicazioni e le gestisce in base alle impostazioni dell'utente e allo stato del telefono.

Per usufruire di questa funzionalità, utile anche quando l'applicazione è in foreground, perché si vuole dare libertà all'utente di entrare e uscire dall'app, non bisogna più usare HttpWebRequest/WebClient, ma una nuova classe di nome BackgroundTransferRequest. La si istanzia passando l'URI da scaricare e impostando il percorso dell'isolated storaged dove salvare il file. Poiché il download è gestito dal sistema, anche quando l'app non è attiva, non è possibile gestire manualmente lo stream, ma è il sistema che se ne occupa e deposita il file nell'isolated storage. Ecco quindi come creare la richiesta:

// Creo la nuova richiesta
BackgroundTransferRequest request = new BackgroundTransferRequest(new Uri("https://www.winphoneitalia.com/"));
request.Method = "GET";
// Posizione dove salvare il file
request.DownloadLocation = new Uri("/shared/transfers/file.html", UriKind.Relative);
// Concesso il trasferimento con batteria
request.TransferPreferences = TransferPreferences.AllowBattery;

// Gestisco gli eventi e lo stato della richiesta
HandleRequest(request);
// Affido la richiesta all'engine di sistema
BackgroundTransferService.Add(request);

Tra le informazioni che è possibile impostare vi è la proprietà TransferPreferences che permette di indicare se il download può essere effettuato anche quando il dispositivo non è in carica, oppure quando il dispositivo non è connesso ad una rete wi-fi. Normalmente, infatti, il download inizia e prosegue solo quando il dispositivo è in carica e connesso in wi-fi, con lo scopo di preservare la batteria. Il download dev'essere inoltre obbligatoriamente scaricato nella cartella di sistema /shared/transfers/. Nell'esempio precedente si usa poi BackgroundTransferService per affidare la richiesta al sistema. A questo punto è possibile gestire gli eventi di essa per conoscere lo stato del trasferimento e quando è terminato.

private void HandleRequest(BackgroundTransferRequest request)
{
  // Gestisco gli eventi
  request.TransferStatusChanged += request_TransferStatusChanged;
  request.TransferProgressChanged += request_TransferProgressChanged;

  // Processo lo stato corrente
  ProcessStatus(request);
}

void request_TransferProgressChanged(object sender, BackgroundTransferEventArgs e)
{
  Debug.WriteLine("{0}/{1}", e.Request.BytesReceived, e.Request.TotalBytesToReceive);
}

void request_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
{
  ProcessStatus(e.Request);
}

La funzione ProcessStatus controlla la proprietà TransferStatus per conoscere lo stato della richiesta. Si esegue questo controllo immediatamente e sull'evento TransferStatusChanged per reagire al cambio di stato. Se lo stato è completato è possibile poi accedere all'isolated storage per leggere il file come normalmente è possibile fare con tutti gli altri.

private static void ProcessStatus(BackgroundTransferRequest request)
{
  switch (request.TransferStatus)
  {
    case TransferStatus.Completed:
      // Rimuovo sempre la richiesta dall'engine
      BackgroundTransferService.Remove(request);

      // Gestisco gli eventuali errori
      if (request.TransferError != null)
        MessageBox.Show("Errore: " + request.TransferError.Message);
      else if (request.StatusCode != 200 && request.StatusCode != 206)
        MessageBox.Show("Errore nel trasferimento: " + request.StatusCode);
      else
      {
        MessageBox.Show("Download completato");
      }

      break;
    case TransferStatus.Waiting:
      break;
    case TransferStatus.WaitingForWiFi:
      break;
    case TransferStatus.WaitingForExternalPower:
      break;
    case TransferStatus.Transferring:
      break;
  }
}

Le proprietà StatusCode e TransferError permettono di conoscere l'esito della richiesta e agire di conseguenza in base al flusso della propria applicazione.

Poiché l'utente potrebbe chiudere e riaprire l'app, nell'entry point dell'applicazione è opportuno richiamare HandleRequest su tutte le richieste attive, in modo da intercettare gli eventi e controllare lo stato delle richieste già in corso.

// Gestisco tutti i trasferimenti attivi
foreach (BackgroundTransferRequest request in BackgroundTransferService.Requests)
{
  HandleRequest(request);
}

Infine, se si usa questa tecnica, le guidelines prevedono che l'utente venga avvisato ed eventualmente gli venga data la facoltà di scegliere la modalità di trasferimento del file.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi