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
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Eseguire operazioni sui blob con Azure Storage Actions
Personalizzare l'errore del rate limiting middleware in ASP.NET Core
Sviluppare un'interfaccia utente in React con Tailwind CSS e Preline UI
Eseguire query manipolando le liste contenute in un oggetto mappato verso una colonna JSON
Installare le Web App site extension tramite una pipeline di Azure DevOps
Semplificare il deployment di siti statici con Azure Static Web App
Miglioramenti nell'accessibilità con Angular CDK
Gestire i null nelle reactive form tipizzate di Angular
Cambiare la chiave di partizionamento di Azure Cosmos DB
Trasformare qualsiasi backend in un servizio GraphQL con Azure API Management
Short-circuiting della Pipeline in ASP.NET Core
Evitare la script injection nelle GitHub Actions
I più letti di oggi
- Creare un messaggio di posta in diversi formati con ASP.NET 2.0
- Caricare un DTO esposto da un servizio tramite una query LINQ to Entities in Entity Framework
- Utilizzare il metodo reduce in #javascript https://aspit.co/ccc di @morwalpiz
- Elencare gli utenti di un dominio NT con ADSI
- Utilizzare SQL e #linq per eseguire una query con #entityframework Core https://aspit.co/bfv di @sm15455 #efcore1
- Disponibile il codice sorgente di ASP.NET MVC
- Concludiamo in bellezza con Giancarlo Sudano di Microsoft: q# for quantum programming Siamo in live streaming da: https://aspit.co/netconf-22 #aspilive #netconfit
- Caricare i dati di configurazione allo startup di un'applicazione Angular
- rilasciati nuovi template per la #aspnet web pages. funzionano anche con #webmatrix: http://u.aspitalia.com/lu
- Creare automaticamente una pipeline YAML da una sua definizione in Azure DevOps