Condividi tramite


Trasferimento in background e NSURLSession in Xamarin.iOS

Un trasferimento in background viene avviato configurando uno sfondo NSURLSession e accodando le attività di caricamento o download. Se le attività vengono completate mentre l'applicazione è in background, sospesa o terminata, iOS informerà l'applicazione chiamando il gestore di completamento in AppDelegate dell'applicazione. Il diagramma seguente illustra questa operazione in azione:

Un trasferimento in background viene avviato configurando una NSURLSession in background e accodando attività di caricamento o download

Configurazione di una sessione in background

Per creare una sessione in background, crearne una nuova NSUrlSession e configurarla usando un NSUrlSessionConfiguration oggetto .

L'oggetto di configurazione determina le operazioni che la sessione può eseguire e i tipi di attività che è possibile eseguire. Le sessioni configurate usando il CreateBackgroundSessionConfiguration metodo verranno eseguite in un processo separato ed eseguono trasferimenti discrezionali (WiFi) per mantenere i dati e la durata della batteria. L'esempio di codice seguente illustra la corretta configurazione di una sessione di trasferimento in background usando il CreateBackgroundSessionConfiguration metodo e un identificatore di stringa univoco:

public partial class SimpleBackgroundTransferViewController : UIViewController
{
  NSUrlSession session = null;

  NSUrlSessionConfiguration configuration =
      NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration ("com.SimpleBackgroundTransfer.BackgroundSession");
  session = NSUrlSession.FromConfiguration
      (configuration, new MySessionDelegate(), new NSOperationQueue());

}

Oltre a un oggetto di configurazione, una sessione richiede anche un delegato di sessione e una coda. La coda determina l'ordine in cui verranno completate le attività. Il delegato di sessione esegue il passaggio del processo di trasferimento e gestisce l'autenticazione, la memorizzazione nella cache e altri problemi correlati alla sessione.

Uso di attività e delegati

Ora che è stata configurata una sessione in background, è possibile avviare le attività per gestire il trasferimento. È possibile tenere traccia di queste attività usando un'istanza NSUrlSessionDelegate denominata delegato di sessione. Il delegato di sessione è responsabile della riattivazione di un'applicazione terminata o sospesa in background per gestire l'autenticazione, gli errori o il completamento del trasferimento.

Fornisce NSUrlSessionDelegate i metodi di base seguenti per controllare lo stato del trasferimento:

  • DidFinishEventsForBackgroundSession : questo metodo viene chiamato al termine di tutte le attività e il trasferimento è completo.
  • DidReceiveChallenge : chiamata per richiedere le credenziali quando è necessaria l'autorizzazione.
  • DidBecomeInvalidWithError : chiamato se l'oggetto NSURLSession diventa invalidato.

Le sessioni in background richiedono delegati più specializzati a seconda dei tipi di attività in esecuzione. Le sessioni in background sono limitate a due tipi di attività:

  • Carica attività : le attività di tipo NSUrlSessionUploadTask usano l'interfaccia INSUrlSessionTaskDelegate , che implementa INSUrlSessionDelegate. In questo modo sono disponibili metodi aggiuntivi per tenere traccia dello stato di avanzamento del caricamento, gestire il reindirizzamento HTTP e altro ancora.
  • Download Tasks : le attività di tipo NSUrlSessionDownloadTask usano l'interfaccia INSUrlSessionDownloadDelegate , che implementa INSUrlSessionDelegate e INSUrlSessionTaskDelegate. Vengono forniti tutti i metodi per le attività di caricamento, nonché i metodi specifici del download per tenere traccia dello stato di avanzamento del download e determinare quando un'attività di download è stata ripresa o completata.

Il codice seguente definisce un'attività che può essere usata per scaricare un'immagine da un URL. L'attività viene avviata chiamando CreateDownloadTask nella sessione in background e passando la richiesta URL:

const string DownloadURLString = "http://xamarin.com/images/xamarin.png"; // or other hosted file
public NSUrlSessionDownloadTask downloadTask;

NSUrl downloadURL = NSUrl.FromString (DownloadURLString);
NSUrlRequest request = NSUrlRequest.FromUrl (downloadURL);
downloadTask = session.CreateDownloadTask (request);

Creare quindi un nuovo delegato di download della sessione per tenere traccia di tutte le attività di download in questa sessione. La classe delegato deve ereditare e NSObject implementare l'interfaccia richiesta:

public class MySessionDelegate : NSObject, INSUrlSessionDownloadDelegate
{
  public void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
  {
    Console.WriteLine (string.Format ("DownloadTask: {0}  progress: {1}", downloadTask, progress));
    InvokeOnMainThread( () => {
      // update UI with progress bar, if desired
    });
  }
  ...
}

Per scoprire lo stato di avanzamento di un'attività di download, eseguire l'override del DidWriteData metodo per tenere traccia dello stato di avanzamento e persino aggiornare l'interfaccia utente. Gli aggiornamenti dell'interfaccia utente verranno visualizzati immediatamente se l'applicazione è in primo piano o sarà in attesa dell'utente alla successiva apertura dell'applicazione.

L'API del delegato di sessione offre un ampio toolkit per interagire con le attività. Per un elenco completo dei metodi del delegato di sessione, vedere la documentazione dell'API NSUrlSessionDelegate .

Importante

Le sessioni in background vengono avviate in un thread in background, quindi tutte le chiamate per aggiornare l'interfaccia utente devono essere eseguite in modo esplicito nel thread dell'interfaccia utente chiamando InvokeOnMainThread per evitare che l'app venga interrotta da iOS.

Gestione del completamento del trasferimento

Il passaggio finale consiste nel informare l'applicazione quando tutte le attività associate alla sessione sono state completate e gestiscono il nuovo contenuto.

AppDelegateIn sottoscrivere l'evento HandleEventsForBackgroundUrl . Quando l'applicazione entra in background e viene eseguita una sessione di trasferimento, questo metodo viene chiamato e il sistema passa un gestore di completamento:

public System.Action backgroundSessionCompletionHandler;

public void HandleEventsForBackgroundUrl (UIApplication application, string sessionIdentifier, System.Action completionHandler)
{
  this.backgroundSessionCompletionHandler = completionHandler;
}

Usare il gestore di completamento per informare iOS quando l'applicazione viene eseguita l'elaborazione.

Tenere presente che una sessione può generare diverse attività per elaborare un trasferimento. Al termine dell'ultima attività, un'applicazione sospesa o terminata viene riavviata in background. Quindi, l'applicazione si connette nuovamente all'oggetto NSURLSession usando l'identificatore di sessione univoco e chiama DidFinishEventsForBackgroundSession il delegato di sessione. Questo metodo è l'opportunità dell'applicazione di gestire nuovi contenuti, incluso l'aggiornamento dell'interfaccia utente per riflettere i risultati del trasferimento:

public void DidFinishEventsForBackgroundSession (NSUrlSession session) {
  // Handle new information, update UI, etc.
}

Al termine della gestione del nuovo contenuto, chiamare il gestore di completamento per comunicare al sistema che è sicuro creare uno snapshot dell'applicazione e tornare alla sospensione:

public void DidFinishEventsForBackgroundSession (NSUrlSession session) {
  var appDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;

  // Handle new information, update UI, etc.

  // call completion handler when you're done
  if (appDelegate.backgroundSessionCompletionHandler != null) {
    NSAction handler = appDelegate.backgroundSessionCompletionHandler;
    appDelegate.backgroundSessionCompletionHandler = null;
    handler.Invoke ();
  }
}

Questa procedura dettagliata ha illustrato i passaggi di base per implementare il servizio trasferimento in background in iOS 7 e versioni successive.