Supportare i dispositivi Windows Phone 8 da un’applicazione Windows Phone 7.x

Print Content | More

Settimana scorsa sul blog ufficiale MSDN è stato pubblicato un mio guest post, dedicato all’ottimizzazione delle applicazioni Windows Phone 7.x per Windows Phone 8. Come sappiamo, infatti, le applicazioni per Windows Phone 7 sono compatibili con la nuova versione del sistema operativo, ma non è vero il contrario. Di conseguenza, se vogliamo supportare entrambe le piattaforme abbiamo la necessità di mantenere due progetti differenti.

In alcuni casi può essere un costo troppo oneroso, soprattutto se si tratta di un’applicazione semplice e che potrebbe trarre benefici molto limitati dalle novità di Windows Phone 8.

Nel corso dell’articolo scoprirete alcuni trucchi e consigli per supportare i device di nuova generazione senza essere costretti ad aggiornare il vostro progetto.

Trovate l’articolo all’indirizzo http://blogs.msdn.com/b/italy/archive/2012/12/10/guest-post-supportare-i-dispositivi-windows-phone-8-da-un-applicazione-windows-phone-7-x.aspx

Buona lettura!


Windows Phone

0 comments

Slide e demo dal Windows Phone Developer Day: condividere codice con applicazioni Windows 8

Print Content | More

Mercoledì 5 Dicembre si è tenuto presso il Microsoft Innovation Center il Windows Phone Developer Day, una giornata di approfondimento dedicata alle novità di Windows Phone 8. Tra gli speaker coinvolti ho avuto l’onore di esserci anche io, proponendo una sessione dedicata alla condivisione di codice con altre piattaforme Microsoft, nello specifico Windows Phone 7 (per ottimizzare le applicazioni già sviluppate per il nuovo sistema operativo) e Windows 8.

Tutte le sessioni della giornata sono state registrate, in separate sede, nella video room di Microsoft e saranno prossimamente disponibili su Channel 9. Nel frattempo, metto a disposizione slide e demo utilizzate durante la mia sessione: sarà mia premura aggiornare il post nel momento in cui anche il video sarà disponibile.


Windows Phone , Windows 8 , Microsoft

0 comments

Qualche chiarimento su SQL Lite e Windows Phone

Print Content | More

Mi sono reso conto che, l’altro giorno durante il Windows Phone Developer Day, posso aver fatto passare un messaggio un po’ confusionario durante la mia sessione: SQL Lite è supportato da Windows Phone 8, ma allo stesso tempo non è utilizzabile.

Vediamo di chiarire meglio, facendo però prima un passo indietro: Windows Phone 7.5 aveva finalmente introdotto il supporto ai database relazionali mediante SQL CE e sfruttando la tecnologia LINQ to SQL per effettuare operazioni. Con Windows Phone 8 c’è stato però un cambiamento di rotta, con l’ottica di offrire una maggiore compatibilità con Windows 8 e, più in generale, con le altre piattaforme mobile come Android e iOS. SQL CE è ancora disponibile in Windows Phone 8, ma la nuova tecnologia consigliata da Microsoft è SQL Lite: si tratta di un engine cross platform e, di conseguenza, offre la possibilità di utilizzare lo stesso database su altre piattaforme.

Microsoft ha lavorato a stretto contatto con il team affinchè, poco dopo il rilascio, fosse disponibile una versione dell’engine di SQL Lite per le sue due nuove piattaforme, ovvero Windows Phone e Windows 8. Il risultato è disponibile nella Visual Studio Gallery di Visual Studio: sono infatti disponibili due package (uno per Windows Phone 8 e uno per Windows 8) che consentono di includere il motore di SQL Lite in un progetto.

Attenzione però (ed è da qui che può nascere un po’ di confusione): si tratta solamente del motore di SQL Lite, ovvero di quella libreria che si occupa di supportare tutte le operazioni più comuni di interazione con un database. Tale libreria è nativa: è necessario perciò codice nativo per effettuare le operazioni vere e proprie, come creare una tabella o estrarre dei dati.

Di conseguenza, l’unico modo per interagire con un linguaggio ad alto livello è quello di utilizzare una libreria che faccia da wrapper verso le chiamate native e che permetta di raggiungere lo stesso risultato che si ottiene utilizzando LINQ to SQL con SQL CE: effettuare operazioni con il database senza scrivere a mano le query, ma lavorando con collezioni e oggetti.

Il problema e la confusione attuale nascono dal fatto che, al momento, questa libreria non esiste ancora per Windows Phone 8: Microsoft è al lavoro su un progetto di questo tipo e possiamo aspettarci delle interessanti novità a breve ma è un dato di fatto che, al momento, anche se SQL Lite è ufficialmente supportato non sia possibile utilizzarlo in un progetto Windows Phone, a meno di non scrivere noi stessi un wrapper verso le chiamate native.

Su Windows 8 la situazione invece è diversa, perché esistono già delle librerie di questo tipo, come sqlite-net, di cui ho parlato in questo articolo che ho pubblicato sul mio blog in inglese. Purtroppo tale libreria non è compatibile con Windows Phone 8, perché utilizza alcune funzionalità del Windows Runtime che non sono disponibili nel subset di Windows Phone.

Se avete la necessità, perciò, di sviluppare un’applicazione Windows Phone che faccia uso di un database e non potete posticipare i lavori, quali possibilità avete?

La prima è quella di utilizzare SQL CE: si tratta di una valida soluzione, da prendere in considerazione nel caso in cui non vi interessi la compatibilità con Windows 8 o con altre piattaforme.

Una seconda possibilità è quella di utilizzare csharp-sqlite, una libreria pubblicata su Google Code che consente di utilizzare il motore di SQL Lite all’interno di applicazioni scritte in C#. Anche Windows Phone è supportato: questa soluzione vi permette di condividere il database con altre piattaforme ed è supportato anche da Windows Phone 8. Il difetto? Che la libreria integrata per accedere ai dati utilizza classi e metodi che fanno riferimento al framework .NET e, di conseguenza, non sono disponibili nel Windows Runtime. Ciò significa che non potrete riutilizzare il vostro strato di accesso ai dati, ad esempio, in un’applicazione Windows Store, ma solamente il database vero e proprio.

Spero di aver aiutato chi ha partecipato al Windows Phone Developer Day (e non solo, questa domanda mi è stata fatta anche da altri sviluppatori tramite altri canali) ad avere le idee più chiare sullo stato attuale del supporto a SQL Lite da parte di Windows Phone!


Windows Phone , Windows 8 , SQL Lite

2 comments

Windows Phone 8 e lo sharing di dati tra applicazioni: i file – Parte 2

Print Content | More

Nel post precedente abbiamo iniziato a dare uno sguardo approfondito ad una delle nuove feature più interessanti di Windows Phone 8: lo sharing di dati tra applicazioni. L’esempio che stiamo utilizzando nel corso di questo tutorial è composto da due applicazioni: nel post precedente abbiamo creato l’applicazione “launcher”, che genera un file di testo e prova ad aprirlo. In questo post, invece, andremo a creare l’applicazione “reader”, che riceverà il file creato dall’applicazione “launcher” e lo elaborerà per mostrarne il contenuto all’utente.

L’applicazione “reader”: come registrare un’estensione

Iniziamo a creare l’applicazione “reader”: create un nuovo progetto di tipo Windows Phone 8 (potete utilizzare il template base Windows Phone App) e iniziamo con il modificare il file di manifest. Purtroppo, come ho già avuto modo di sottolineare nell’articolo pubblicato su ASPItalia dedicato alle novità di Windows Phone 8, il nuovo editor visuale ha ancora qualche limite e non supporta tutti gli scenari: per registrare una specifica estensione di file dovremo perciò modificare manualmente il manifest, facendo clic con il tasto destro sul file WMAppManifest.xml all’interno della cartella Properties e scegliendo View code.

Protocolli ed estensioni vengono registrati nella sezione Extensions: nel caso in cui sia assente, potete aggiungerla manualmente sotto la sezione Tokens. Ecco come registriamo l’estensione log:

      <FileTypeAssociation Name="LogFile" TaskID="_default" NavUriFragment="fileToken=%s">
        <SupportedFileTypes>
          <FileType ContentType="text/plain">.log</FileType>
        </SupportedFileTypes>
      </FileTypeAssociation>

Ogni associazione è identificata dal nodo FileTypeAssociation, caratterizzato da una proprietà Name univoca. Gli attributi TaskID e NavUriFragment definiscono come il file viene passato all’applicazione: si tratta di due valori fissi, non devono essere modificati ma devono essere sempre come nel codice di esempio.

All’interno di questo nodo potete specificare le tipologie di file che andrete a supportare, aggiungendo un nodo di tipo FileType e specificando l’estensione e il content type. Avete anche la possibilità di includere un logo che rappresenta la tipologia di file, che sarà utilizzato dal sistema operativo ove necessario (ad esempio, di fianco al nome di un allegato nell’applicazione Mail). In tal caso, dovete creare tre differenti tipologie di immagine (con le risoluzioni 33x33, 69x69 e 176x176), aggiungerle al vostro progetto e includerle nella definizione del nodo FileTypeAssociation, come nell’esempio:

 <FileTypeAssociation Name="LogFile" TaskID="_default" NavUriFragment="fileToken=%s">
<Logos>
           <Logo Size="Small">log-33x33.png</Logo>
           <Logo Size="Medium">log-69x69.png</Logo>
           <Logo Size="Large">log-176x176.png</Logo>
       </Logos>
        <SupportedFileTypes>
          <FileType ContentType="text/plain">.log</FileType>
        </SupportedFileTypes>
      </FileTypeAssociation>

Una volta che avete registrato la vostra estensione è tempo di scrivere un po’ di codice. Sono due le operazioni che andremo a fare: definire un UriMapper e creare una pagina che gestirà il file ricevuto.

La classe UriMapper

Prima di parlare della classe UriMapper, è meglio spiegare come il sistema operativo gestisce l’associazione di file da parte di applicazioni di terze parti. Quando un’applicazione viene aperta come conseguenza dell’apertura di un file supportato (utilizzando il meccanismo visto nel post precedente), viene utilizzato uno speciale Uri che ha la seguente struttura:

/FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19

Dopo la parola chiave by FileTypeAssociation viene passato un unico parametro chiamato fileToken, che è un GUID che identifica in maniera univoca il file. Come vedremo a breve, Windows Phone 8 espone delle API per recuperare fisicamente il file tramite il token.

Ora che abbiam ocapito come funziona dietro la quinte la gestione dei file, dovrebbe essere semplice capire lo scopo della classe UriMapper, ovvero quello di mettersi “in mezzo” alle richieste di navigazione dell’applicazione e ridirigere le chiamate verso la pagina più appropriata, a seconda dell’Uri che è stato richiesto. Nel nostro caso, andremo a verificare se l’applicazione è stata aperta in seguito all’apertura di un file e, in caso affermativo, porteremo l’utente in una specifica pagina dell’applicazione che sarà in grado di elaborare il nostro file di log.

    public class UriMapper : UriMapperBase
    {
        private string tempUri;

        public override Uri MapUri(Uri uri)
        {
            tempUri = uri.ToString();

            // File association launch
            if (tempUri.Contains("/FileTypeAssociation"))
            {
                // Get the file ID (after "fileToken=").
                int fileIDIndex = tempUri.IndexOf("fileToken=") + 10;
                string fileID = tempUri.Substring(fileIDIndex);

                // Get the file name.
                string incomingFileName =
                    SharedStorageAccessManager.GetSharedFileName(fileID);

                // Get the file extension.
                int extensionIndex = incomingFileName.LastIndexOf('.') + 1;
                string incomingFileType =
                    incomingFileName.Substring(extensionIndex).ToLower();

                // Map the .log files to the appropriate pages.
                switch (incomingFileType)
                {
                    case "log":
                        return new Uri("/LogDetail.xaml?fileToken=" + fileID, UriKind.Relative);
                    default:
                        return new Uri("/MainPage.xaml", UriKind.Relative);
                }

            }
            // Otherwise perform normal launch.
            return uri;
        }
    }

La prima cosa da fare è aggiungere una nuova classe al vostro progetto, che deve ereditare dalla classe UriMapperBase. Questa classe vi richiederà di implementare il metodo MapUri, che viene chiamato nel momento in cui l’applicazione viene inizalizzitata portando con sè come parametro un Uri.

Nel caso in cui l’applicazione sia stata aperta in seguito all’apertura di un file, l’URL conterrà la stringa FileTypeAssociation: in questo caso, siamo in grado di ottenere il token del file semplicemente manipolando la stringa dell’URL, dato che le parole chiave FileTypeAssociation e fileToken sono fisse. Dopodichè, andiamo ad utilizzare la classe SharedStoreAccessManager, che è in grado di gestire le operazioni con i file: in questo caso utilizziamo il metodo GetSharedFileName che, dato il token, restituisce il nome del file così come era stato definito nel’applicazione “launcher”.

Tramite il nome e giocando con le stringhe siamo in grado di ottenere l’informazione che ci serve: l’estensione del file. In questo modo siamo in grado di identificarne la tipologia e gestirla nella maniera più appropriata. Nel nostro caso, gestiamo solamente l’estensione .log, perciò il blocco switch contiene solo due possibilità: l’estensione log (in tal caso l’utente viene portato alla pagina LogDetail.xaml, portando con sè in query string il token), mentre in caso non ci sia una corrispondenza l’utente viene semplicemente portato alla pagina principale.

L’ultima cosa che dobbiamo fare è dire all’applicazione che abbiamo un oggetto UriMapper, che deve essere invocato ogni qualvolta viene lanciata una navigazione: per farlo dobbiamo aprire il file App.xaml.cs e, all’interno del metodo InitializePhoneApplication(), subito dopo che l’oggetto RootFrame è stato inizializzato, valorizzare la sua proprietà UriMapper con l’oggetto che abbiamo appena creato, come nell’esempio:

private void InitializePhoneApplication()
{
    if (phoneApplicationInitialized)
        return;

    // Create the frame but don't set it as RootVisual yet; this allows the splash
    // screen to remain active until the application is ready to render.
    RootFrame = new PhoneApplicationFrame();
    RootFrame.Navigated += CompleteInitializePhoneApplication;
    RootFrame.UriMapper = new Helpers.UriMapper();

    // Handle navigation failures
    RootFrame.NavigationFailed += RootFrame_NavigationFailed;

    // Handle reset requests for clearing the backstack
    RootFrame.Navigated += CheckForResetNavigation;

    // Ensure we don't initialize again
    phoneApplicationInitialized = true;
}

Recuperiamo il file!

Ora è tempo di creare la pagina LogDetail.xaml, che utilizzeremo per mostrare il contenuto del file. Aggiungete una nuova pagina vuota al progetto e dategli il nome LogDetail.xaml: nel code behind andremo a gestire l’evento OnNavigatedTo, che viene invocato nel momento in cui l’utente naviga verso la pagina corrente.

In questo evento andremo a recuperare il token che identifica il file e lo utilizzeremo per recuperarne il contenuto, che ci è stato passato dall’applicazione “launcher”. Ecco il codice:

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            if (NavigationContext.QueryString.ContainsKey("fileToken"))
            {
                await SharedStorageAccessManager.CopySharedFileAsync(ApplicationData.Current.LocalFolder, "rss.log",
                                                               NameCollisionOption.ReplaceExisting,
                                                               NavigationContext.QueryString["fileToken"]);

            }
        }

Se avete già sviluppato applicazioni Windows Phone il meccanismo dovrebbe esservi famigliare, dato che è simile a quello introdotto in Windows hone 7.5 per gestire alcuni scenari avanzati di navigazione (ad esempio, quando l’applicazione viene aperta da una tile secondaria): se il NavigationContext contiene un parametro in query string chiamato fileToken allora andiamo ad utilizzare nuovamente la classe SharedStorageManager per recuperare il file vero e proprio tramite il metodo CopySharedFileAsync.

Questo metodo si occupa di tradurre il token in un file vero e proprio e di copiarlo all’interno dello storage locale dell’applicazione. I parametri richiesti sono:

  • La cartella dello storage dove salvare il file, sotto forma di oggetto di tipo StorageFolder. Nell’esempio passiamo l’oggetto base LocalFolder: in questo caso il file sarà copiato nella root dello storage.
  • Il nome del file da salvare.
  • Cosa fare nel caso in cui esista già un file con lo stesso nome.
  • Il token che identifica il file che abbiamo recuperato dalla query string.

Una volta che il file è disponibile nello storage possiamo elaborarlo a piacimento. Per esempio, possiamo leggerne il contenuto e mostrarlo in una casella di testo utilizzando l’extension method ReadFromFile, che andremo a dichiarare nella classe FileExtensions creata nel post precedente:

public static class FileExtensions
{
    public static async Task<string> ReadFromFile(string fileName,StorageFolder folder = null)
    {
        folder = folder ?? ApplicationData.Current.LocalFolder;
        var file = await folder.GetFileAsync(fileName);

        using (var fs = await file.OpenAsync(FileAccessMode.Read))
        {
            using (var inStream = fs.GetInputStreamAt(0))
            {
                using (var reader = new DataReader(inStream))
                {
                    await reader.LoadAsync((uint)fs.Size);
                    string data = reader.ReadString((uint)fs.Size);
                    reader.DetachStream();
                    return data;
                }
            }
        }
    }
}

Ora, grazie a questo extension method, possiamo fare nell’evento OnNavigatedTo della classe LogDetail una cosa di questo tipo:

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    if (NavigationContext.QueryString.ContainsKey("fileToken"))
    {
        SharedStorageAccessManager.CopySharedFileAsync(ApplicationData.Current.LocalFolder, "rss.log",
                                                       NameCollisionOption.ReplaceExisting,
                                                       NavigationContext.QueryString["fileToken"]);

        string content = await FileExtensions.ReadFromFile("rss.log");
        log.Text = content;
    }
}

It’s debugging time!

Fare  il debug di questa feature è piuttosto semplice: è sufficiente fare il deploy di entrambe le applicazioni sull’emulatore o su un device (facendo click con il tasto destro su entrambi i progetti e selezionando la voce Deploy). Dopodichè eseguite l’applicazione “launcher” che abbiamo sviluppato nel post precedente, create il file di log e premete il pulsante Open file. Se avete fatto tutto correttamente, vedrete avviarsi l’applicazione “reader” e aprirsi direttamente sulla pagina LogDetail, la quale mostrerà il contenuto file XML.


Windows Phone , Microsoft

0 comments

Windows Phone 8 e lo sharing di dati tra applicazioni: i file – Parte 1

Print Content | More

Una delle limitazioni più “fastidiose” per gli sviluppatori Windows Phone era quella di non poter condividere dati tra le applicazioni. Questa limitazione non era esclusiva delle applicazioni di terze parti, ma non eravamo in grado di gestire neanche le tipologie di file supportate nativamente da Windows Phone (come i file di Office): l’unico workaround disponibile era quello di aprire il file utilizzando il browser; in questo modo, se la tipologia era supportata dal sistema operativo, il file veniva scaricato e aperto con l’applicazione corretta. Il problema di questo workaround è che funzionava solo con i file disponibili online: se il file era memorizzato nello storage dell’applicazione, non era possibile applicarlo.

E’ perciò che, con un caloroso applauso, diamo il benvenuto ad una nuova funzionalità di Windows Phone 8, che consente alle applicazioni di terze parti di registrare uno specifico procollo o tipologia di file: in questo modo, nel momento in cui un’altra applicazione dovesse cercare di aprire un file di quel tipo, la nostra sarebbe in grado di intercettare la richiesta ed elaborare il file.

Ci sono due modalità per condividere dati: registrandosi per una specifica tipologia di file o per un protcollo. Nel primo caso, l’applicazione registra una specifica estensione (ad esempio, .log): quando un’altra app tenta di aprire un file con questa estensione, il file viene passato all’applicazione e copiato nel suo storage locale. Nel secondo caso, invece (che andremo ad approfondire in un altro post), possiamo registrarci per uno specifico protocollo (ad esempio, log:/), così che un’altra applicazione possa utilizzarlo per inviarci dei dati in formato testuale.

Cosa succede quando un’applicazione di terze parti registra una tipologia di file? Il sistema operativo va alla ricerca di applicazioni che, tramite il file di manifest, hanno dichiarato di essere in grado di trattare quella specifica tipologia: se l’utente non ne ha, avrà la possibilità di accedere allo Store e di visualizzare solo le applicazioni in grado di supportare quell’estensione. Se sono disponibili, invece, più applicazioni, avrà la possibilità di scegliere quale vuole utilizzare; infine, se ne è presente solamente una, sarà aperta direttamente, senza che sia necessario alcun intervento dell’utente.

In questo tutorial ci focalizzeremo sull’associazione di file. Nell’esempio andremo a creare due applicazioni Windows Phone separate: la prima, che chiameremo “launcher”, sarà l’applicazione che tenterà di aprire un file di tipo .log, il quale sarà elaborato dall’app che invece chiameremo “reader”. Useremo un file testuale con estensione .log, con il quale condivideremo del testo tra le due applicazioni.

L’applicazione “launcher”: creare e aprire il file.

Nell’applicazione “launcher” andremo a svolgere due compiti: il primo è quello di creare un file tipo log, che sarà un semplice file di testo. Il secondo è quello di tentare di aprire il file, così che l’applicazione reader possa utilizzarla. Iniziamo con il creare il file di log: per questo scopo useremo una classe che aggiunge due semplici extension method per lavorare con le stringh e e con lo storage. Il primo metodo è chiamato WriteToFile e serve per salvare il contenuto di una stringa in un file locale, il secondo si chiama invece ReadFromFile e fa esattamente l’opposto: apre un file dallo storage, contenente del testo, e ne restituisce la rappresentazione sotto forma di stringa.

Iniziamo perciò proprio con il creare la classe che includerà i nostri extension methods: facciamo clic con il tasto destro sul vostro progetto e selezionate Add New File. Dategli un nome a piacimento e marcate la classe come static, come nell’esempio. In questo post andremo a vedere solo il metodo WriteToFile, dato che è l’unico che useremo nell’applicazione “launcher”.

namespace ShareData.Launcher.Helpers
{
    public static class FileExtensions
    {   
        public static async Task WriteToFile(this string contents, string fileName, StorageFolder folder = null)
        {
            folder = folder ?? ApplicationData.Current.LocalFolder;
            var file = await folder.CreateFileAsync(
                fileName,
                CreationCollisionOption.ReplaceExisting);
            using (var fs = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (var outStream = fs.GetOutputStreamAt(0))
                {
                    using (var dataWriter = new DataWriter(outStream))
                    {
                        if (contents != null)
                            dataWriter.WriteString(contents);

                        await dataWriter.StoreAsync();
                        dataWriter.DetachStream();
                    }

                    await outStream.FlushAsync();
                }
            }
        }
    }
}

Questo metodo prende una stringa come parametro e lo salva in un file nello storage locale, il cui nome viene passato come parametro. Il metodo accetta anche un altro parametro in ingresso, il cui tipo è StorageFolder (che è la classe di WinRT che identifica una cartella nello storage locale): possiamo utilizzarlo nel caso in cui vogliamo che il file sia memorizzato in una specifica cartella, altrimenti il file sarà creato nella root.

Questo metodo utilizza le API standard di WinRT per creare il file e le classi OutputStream e DataWriter per salvare il contenuto della stringa al suo interno.

Il prossimo passo è installare il pacchetto Microsoft.Bcl.Async da NuGet, che abbiamo imparato ad utilizzare in questo post: il suo scopo, in questo tutorial, è quello di metterci a disposizione degli extension method per utilizzare la classe WebClient con le keyword async e await, che utilizzeremo per scaricare il contenuto di un feed RSS da salvare in un file.

Ora lavoriamo sulla UI: aggiungeremo semplicemente due pulsanti all’interno del file MainPage.xaml, uno per scaricare l’XML del feed e salvarlo in un file, l’altro per “aprirlo”.

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <StackPanel>
        <Button Content="Create file" Click="OnCreateFileButtonClicked" />
        <Button Content="Open file" Click="OnOpenFileButtonClicked" />
    </StackPanel>
</Grid>

Graze all’extension method che abbiamo creato per lavorare con i file e a quello incluso nella libreria Microsoft.Bcl.Async per espandere la classe WebClient, diventa molto semplice raggiungere l’obiettivo di scaricare l’XML del feed RSS e salvarlo in un file dall’estensione .log.

private async void OnCreateFileButtonClicked(object sender, RoutedEventArgs e)
{
    WebClient client = new WebClient();
    string result = await client.DownloadStringTaskAsync("http://feeds.feedburner.com/qmatteoq");

    await result.WriteToFile("rss.log");
}

Quello che andiamo a fare è semplicemente scaricare l’RSS utilizzando il metodo DownloadStringTaskAsync (nell’esempio, andiamo a scaricare l’RSS di questo blog) e lo salviamo in un file chiamato rss.log, che viene posizionato nella root dello storage locale.

Lo step successivo è quello di aprire il file, andando a gestire l’evento di tap sul secondo pulsante:

private async void OnOpenFileButtonClicked(object sender, RoutedEventArgs e)
{
    StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("rss.log");
    Windows.System.Launcher.LaunchFileAsync(file);
}

Anche in questo caso l’operazione che andiamo a fare è molto semplice: dopo aver ottenuto un riferimento al file (utilizzando il metodo GetFileAsync) lo apriamo utilizzando il metodo LaunchFileAsync della classe Launcher (appartenente al namespace Windows.System). Cosa succede nel momento in cui premiamo il pulsante? Allo stato attuale, comparirà un messaggio che vi avviserà che non avete applicazioni in grado di aprire file di tipo log e vi verrà proposto di cercarla nello store. Per il momento, ignorate il messaggio: nel prossimo post andremo a vedere come creare l’applicazione “reader”, che registrerà l’estensione log e che sarà in grado di aprire il nostro file.

Se volete mettere alla prova quanto abbiamo sviluppato, nel frattempo, provate a rinominare il file salvato dall’applicazione in rss.txt, semplicemente cambiando il nome che viene passato ai metodi result.WriteToFile() e LocalFolder.GetFileAsync(). Dato che txt è un’estensione supportata nativamente dal sistema operativo, il file sarà aperto da Word e avrete la possibilità di leggere il contenuto del file XML.

Nella prossima puntata

Nel prossimo post andremo a sviluppare l’applicazione “reader”, che sarà in grado di intercettare l’operazione di apertura e di elaborare il file rss.log che abbiamo creato in questo post.


Windows Phone , Microsoft

0 comments

API for Mobile: tutto quello che vorreste sapere sul mondo dei servizi Microsoft

Print Content | More

Da diversi anni a questa parte il concetto di “servizio” ha assunto sempre maggiore importanza nel mondo dello sviluppo, in virtù anche della grande diffusione di dispositivi mobile come gli smartphone e i tablet. Anche le tecnologie utilizzate per lo sviluppo di servizi si sono evolute nel corso del tempo: se, per quanto riguarda il mondo Microsoft, WCF ha sempre fatto da padrone, si sono affacciate negli ultimi anni nuove tecnologie come ASP.NET WebAPI che, utilizzando protocolli e formati di comunicazione standard (come HTTP e JSON), si adattano molto bene a scenari mobile e multi piattaforma: non solo Windows Phone e Windows 8, ma anche Android, iOS o client web.

Per questo motivo DotNetLombardia ha organizzato un pomeriggio di approfondimento sul mondo delle Web API e dei servizi REST: sul palco si alterneranno alcuni speaker della community (come Roberto e Antonio), che illustreranno best practise ed esempi di codice basati su WCF e ASP.NET WebApi. In conclusione, io vi mostrerò come è semplice integrare questi servizi lato client, all’interno di applicazioni Windows 8 e Windows Phone 8.

Vi aspettiamo Mercoledì 12 Dicembre presso la sede di Assago (MI) di Intel che, gentilmente, ci ospita ancora una volta: l’evento inizierà intorno alle ore 14 e si concluderà per le 19 circa: seguirà una cena, come da migliore tradizione community, a cui ovviamente sono tutti invitati.

Il sito ufficiale dell’evento, dove trovate l’agenda completa e il link per iscrivervi, è http://share.dotnetlombardia.org/events/121212/default.aspx

Vi aspettiamo!


Windows 8 , Windows Phone , Web API , DotNetLombardia

0 comments

Unit testing in Windows Phone 8 – Mocking e metodi asincroni

Print Content | More

Uno degli scenari più frequenti da testare è l’utilizzo di metodi asincroni: WinRT è pesantemente basato su questo approccio, sia in Windows 8 che in Windows Phone 8. In più, grazie alle nuove keyword async e await, è diventato più semplice per gli sviluppatori gestire correttamente tale approccio.

Qual è il modo giusto per testare metodi asincroni? Vediamo qual è l’approccio da adottare.

Le operazioni asincrone

Per il nostro test andremo ad utilizzare la classe WebClient, che è il modo più semplice disponibile in Windows Phone per effettuare operazioni di rete, come scaricare o caricare un file. Al contrario di Windows 8 (che non ha una classe WebClient, ma una molto simile chiamata HttpClient), il WebClient supporta solamente l’utilizzo di metodi asincroni con il vecchio approccio delle callback: si usa un metodo per lanciare l’operazione e ci si sottoscrive ad un evento, che viene scatenato nel momento in cui l’operazione è terminata e siamo pronti per elaborare il risultato. Questo approccio è comunque supportato dal Phone Unit Test Framework, come vedremo dopo, ma preferisco mostrarvi prima come usare e testare il nuovo approccio basato sulle keyword async e await.

Per raggiungere il nostro scopo installiamo prima la libreria Microsoft.Bcl.Async da NuGet, che abbiamo imparato a conoscere in questo post. Vi ricordo che, per trovarla, dovete cambiare il filtro predefinito di NuGet per mostrare anche i pacchetti in versione non definitiva, selezionando l’opzione Include prerelease nel menu a tendina posizionato in alto nella finestra che compare quando fate clic con il tasto destro sul progetto e scegliete Manage NuGet packages. Grazie all’utilizzo di questa libreria saremo in grado di utilizzare la classe WebClient con il nuovo approccio basato sulle keyword async e await. Nello specifico, andremo ad utilizzare il metodo DownloadStringTaskAsync, che restituisce un Task<string> con il contenuto della risposta.

Ecco un semplice test che esegue il metodo e verifica che la dimensione della risposta sia superiore a 0.

[TestMethod]
public async void AsyncMethod()
{
    WebClient client = new WebClient();
    string s = await client.DownloadStringTaskAsync("http://www.qmatteoq.com");
    Assert.IsTrue(s.Length == 0);
}

Ho intenzionalmente creato questo test per fallire: infatti, dato che il metodo DownloadStringTaskAsync restituisce l’HTML della home page di questo blog, la dimensione del risultato sarà sempre uguale a 0.

Lanciate l’applicazione e… il test passerà! Se avete il debugger di Visual Studio collegato noterete che prima il test passerà, dopodichè sarà scatenata una AssertFailedException sul metodo Assert.IsTrue. Questo succede perché l’applicazione non aspetta che il metodo DownloadStringTaskAsync abbia completato l’esecuzione prima di concludere il test: dato che il metodo si conclude senza eccezioni, l’applicazione segna il test come valido. Nel momento in cui l’operazione è veramente completata la assert viene valutata e fallisce, ma è troppo tardi, il test ormai è già stato marcato come passato.

Dobbiamo apportare tre modifiche per consentire all’applicazione di eseguire correttamente il test in maniera asincrona. La prima è cambiare la classe che contiene i test, affinchè erediti dalla classe WorkItemTest, contenuta nel namespace Microsoft.Phone.Testing. Il sercondo passo è marcare il test come asincrono, utilizzando l’attributo [Asynchronous]. La terza e ultima modifica è quella di comunicare all’applicazione quando l’esecuzione del test è realmente terminata e la assert può essere valutata: per farlo dobbiamo chiamare il metodo EnqueueTestComplete() (che fa parte della classe WorkItemTest da cui eredita la nostra classe) dopo che l’operazione asincrona è terminata. Ecco come apparirà la versione finale del nostro metodo:

[TestClass]
public class SimpleUnitTest: WorkItemTest
{
    [TestMethod]
    [Asynchronous]
    public async void AsyncMethod()
    {
        WebClient client = new WebClient();
        string s = await client.DownloadStringTaskAsync("http://www.qmatteoq.com");
        Assert.IsTrue(s.Length == 0);
        EnqueueTestComplete();
    }
}

Lanciate nuovamente l’applicazione: questa volta vedrete il test fallire correttamente, dato che il test runner aspetterà che il metodo EnqueueTestComplete venga chiamato prima di considerare il test completato.

La coppia attributo [Asynchronous] / metodo EnqueueTestComplete può essere utilizzata anche in combinazione con gli altri pattern per l’esecuzione di metodi asincroni. Ecco, ad esempio, come utilizzare lo stesso approccio per testare il metodo di download della classe WebClient basato sul meccanismo delle callback.

[TestMethod]
[Asynchronous]
public void AsyncMethod()
{
    WebClient client = new WebClient();
    client.DownloadStringCompleted += (obj, args) =>
                                          {
                                              Assert.IsTrue(args.Result.Length == 0);
                                              EnqueueTestComplete();
                                          };
    client.DownloadStringAsync(new Uri("http://www.qmatteoq.com"));
}

Il risultato sarà esattamente lo stesso: il test fallirà correttamente, dato che la dimensione del risultato è maggiore di 0.

Per corretteza, è giusto precisare che quello che abbiamo eseguito non è uno unit test, ma un test di integrazione. Questo perché, per eseguirlo, dobbiamo soddisfare delle dipendenze esterne che sono disponibili solo in un ambiente reale (nel nostro caso, il telefono). Nel caso del nostro test, è la disponibilità di una connessione ad Internet: altri esempi di test di integrazione sono quelli che coinvolgono la scrittura di un file nello storage o l’utilizzo del sensore GPS per rilevare la posizione corrente dell’utente. Nel prossimo paragrafo vedremo come, grazie al mocking, possiamo trasformare un test di integrazione in uno unit test.

Mocking: di cosa si tratta?

Spesso può capitare di dover testare della logica che dipende da altre classi o altri metodi, i quali svolgono delle operazioni sui dati che possono influire sul risultato finale. Il fatto, però, è che voi avete la necessità di testare che la logica di quello specifico metodo sia corretta, senza preoccuparsi di tutte le altre dipendenze e dei fattori esterni. Vediamo meglio un esempio per spiegare il concetto.

Ipotizziamo che voi abbiate una classe (con la corrispondente interfaccia) che espone un metodo che usa la classe WebClient per recuperare il contenuto della pagina e restituirlo.

public interface INetworkService
{
    Task<string> GetContent(string url);
}

public class NetworkService: INetworkService
{
    public async Task<string> GetContent(string url)
    {
        WebClient client = new WebClient();
        string content = await client.DownloadStringTaskAsync(url);
        return content;
    } 
}

 

L’applicazione ha poi un’altra classe, che chiamiamo DataProvider, che utilizza il NetworkService per recuperare la dimensione del contenuto della pagina:

 

public class DataProvider
{
    private readonly INetworkService networkService;

    public DataProvider(INetworkService networkService)
    {
        this.networkService = networkService;
    }

    public async Task<int> GetLength(string url)
    {
        string content = await networkService.GetContent(url);
        return content.Length;
    }
}

 

Con questa struttura possiamo scrivere, nella MainPage della nostra applicazione, del codice che utilizzi la classe DataProvider per connettersi alla rete e recuperare la dimensione del contenuto di una pagina, come nell’esempio:

private async void Button_Click_1(object sender, RoutedEventArgs e)
{
    INetworkService networkService = new NetworkService();
    DataProvider provider = new DataProvider(networkService);

    int length = await provider.GetLength("http://www.qmatteoq.com");

    MessageBox.Show(length.ToString());
}

In un’applicazione reale probabilmente avremmo usato un approccio basato sulla dependency injection ma, dato che queste classi ci servono per scopo didattico, non rendiamo lo scenario troppo complesso. Il nostro obiettivo è testare il metodo GetLength della classe DataProvider: questo metodo dipende da un’altra classe, NetworkService, per effettuare l’operazione di rete. Potremmo semplicemente scrivere un test che esegua la vera richiesta web e controlli se la dimensione della risposta è maggiore di 0, ma in questo caso sarebbe stato un test di integrazione, nonché legato a dipendenze esterne: il fatto che la richiesta possa fallire (ad esempio, perché per la mancanza di una connessione ad Internet) non significa che la logica del metodo GetLength sia sbagliata. Introduciamo perciò il concetto di mock: mocking significa creare una classe finta, che espone le stesse proprietà e metodi della classe originale, ma che possiamo istruire per specificare cosa un metodo deve fare e quale risultato deve restituire senza che questo sia effettivamente eseguito.

Nel nostro esempio, il nostro obiettivo è quello di creare il mock della classe NetworkService, così da simulare l’esecuzione del metodo GetContent e ritornare un contenuto fittizio, che sarà poi elaborato dal metodo GetLength della classe DataProvider. Per raggiungere questo scopo andremo ad utilizzare una libreria chiamat Moq, che è disponibile anche su NuGet ma che, per il momento, dobbiamo scaricare dal sito ufficiale. Il motivo è che Moq non supporta ufficialmente Windows Phone, per cui NuGet fallirebbe l’installazione perché non trova una piattaforma supportata. Se invece scaricare la libreria dal sito, troverete una versione per Silverlight che funziona senza problemi anche su Windows Phone: semplicemente scompattate il file scaricato dal sito, copiate il file chiamato Moq.Silverlight.dll in una cartella e aggiungetela al progetto tramite l’opzione Add service reference. Comparirà un avvertimento che la libreria non è compatibile al 100% con il tipo di progetto: semplicemente cliccate su Yes e la libreria sarà aggiunta alla vostra applicazione.

Diamo un occhio al codice del test che verifica se il metodo GetLength della classe DataProvider funziona correttamente:

[TestMethod]
public async void ComplexTest()
{
    TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
    tcs.SetResult("done");

    Mock<INetworkService> mock = new Mock<INetworkService>();
    mock.Setup(x => x.GetContent(It.IsAny<string>())).Returns(tcs.Task);

    DataProvider provider = new DataProvider(mock.Object);
    int length = await provider.GetLength("http://www.qmatteoq.com");

    Assert.IsTrue(length > 0);
}

Usare Moq è molto semplice: prima creiamo un mock della classe della quale abbiamo bisogno di simulare il comportamento, ovvero la classe NetworkService. Dopodichè, utilizzando il metodo Setup, diciamo alla libreria quale metodo vogliamo simulare e, utilizzando la funzione Returns, specifichiamo quale risultato vogliamo ottenere. Il parametro viene passato al metodo Setup tramite una lambda expression: nell’esempio, definiamo una finta chiamata al metodo GetContent. Potete notare l’uso del metodo It.IsAny<T>, che permette di generare un parametro fittizio da passare alla richiesta. T è il tipo del parametro: nell’esempio è uguale a string, dato che rappresenta l’URL del sito del quale vogliamo scaricare l’HTML.

Per gestire correttamente il metodo Returns dobbiamo sfruttare un piccolo workaround, dato che GetContent è un metodo asincrono. Per evitare che la Assert venga valutata prima che il metodo sia effettivamente terminato dobbiamo preparare prima il risultato del metodo GetContent usando la classe TaskCompletionSource (che, tipicamente, viene utilizzata per trasformare metodi asincroni basati su vecchi approcci, ad esempio sulle callback, in metodi utilizzabili con le keyword async e await). Nell’esempio vogliamo che il metodo GetContent restituisca la stringa “done” al posto del vero contenuto HTML della pagina, perciò definiamo un oggetto di tipo TaskCompletionSource<string> e passiamo la nostra stringa al metodo SetResult.

Ora abbiamo tutto il necessario per simulare il metodo GetContent: è sufficiente passare al metodo Returns l’oggetto di tipo Task che è restituito dall’oggetto di tipo TaskCompletionSource.

Infine utilizziamo la classe DataProvider come avremmo fatto in un’applicazione reale: l’unica differenza è che, invece di passare al costruttore una istanza reale della classe NetworkService, passiamo il mock dell’oggetto, che è disponibile tramite la proprietà Object dell’oggetto di tipo Mock.

Se ora eseguite il test vedrete che passerà correttamente. Se posizionate un breakpoint e fate debug step by step del test vedrete che il nostro mock ha funzionato correttamente: la dimensione restituita dal metodo GetLength sarà 4, dato che il metodo GetContent ha correttamente restituito la stringa done, come abbiamo specificato nella funzione Returns.

Fate attenzione! Potete notare che, questa volta, non abbiamo marcato il test con l’attributo Asynchronous e non abbiamo chiamato il metodo EnqueueTestComplete: questo perché, dato che abbiamo creato un mock dell’operazione GetContent, il metodo non è più asincrono, dato che il risultato viene immediatamente restituito.


Windows Phone , Unit testing

0 comments

Unit testing in Windows Phone 8 – Le basi

Print Content | More

Lo unit testing in Windows Phone non è mai stato ufficialmente supportato da Microsoft: l’unico sistema semi-ufficiale per fare unit testing in Windows Phone 7 è quello di utilizzare una variante del Silverlight Unit Test Framework sviluppata da Jeff Wilcox. Questa libreria è in grado di creare a runtime una speciale applicazione Windows Phone, in grado di lanciare tutti i test inclusi nel progetto. Lo svantaggio di questo approccio è che dovrete utilizzare un progetto Windows Phone dedicato per eseguire i test, invece di utilizzare un tool integrato come quelli offerti da ReSharper. Il vantaggio principale, invece, è che i test vengono eseguiti in un ambiente reale, perciò è semplice utilizzare questo framework anche per scrivere test di integrazione, in grado di fare uso ad esempio dello storage o della connessione ad Internet.

Data l’importanza crescente degli unit test nel mondo dello sviluppo, Microsoft ha deciso di adattare il Silverlight Unit Test Framework a Windows Phone 8, cambiandone il nome (ora si chiama semplicemente Phone Unit Test Framework) e integrandolo con il toolkit ufficiale per Windows Phone. Vediamo come usarlo, come lanciare alcuni semplici test e, nel prossimo post, come affrontare alcuni scenari più avanzati (come il mocking o il testing di codice asincrono).

Preparare l’ambiente di testing

Come vi ho anticipato, i test vengono eseguiti in un’applicazione Windows Phone separata: per questo motivo, dovrete aggiungere un nuovo progetto di tipo Windows Phone alla vostra soluzione. Una volta che avete compiuto questa operazione, potete installare da NuGet il Windows Phone toolkit e il framework di testing: ora siamo pronti per configurare l’applicazione.

La prima cosa da fare è aprire il file di code behind della pagina principale, ovvero MainPage.xaml.cs, e aggiungere nel costruttore, subito dopo la chiamata al metodo InitializeComponente, il codice seguente:

public MainPage()
{
    InitializeComponent();
    this.Content = UnitTestSystem.CreateTestPage();
}

In questo modo, quando l’applicazione viene lanciata, sarà automaticamente caricato il test runner: potete vederlo con i vostri occhi semplicemente lanciando l’applicazione nell’emulatore. La prima schemata vi chiederà se volete utilizzare o meno i tags (vedremo più avanti lo scopo di questa funzionalità): se premete il pulsante Play presente nella application bar verrete portati alla pagina principale dell’applicazione, anche se al momento non troverete alcun test dato che non ne abbiamo ancora definiti.

 

unit1

 

Il prossimo step è quello di creare una o più classi in cui definire gli unit test: in uno scenario reale probabilmente creeremmo una classe per ognuna delle classi reali che dovremmo testare. Per questo esempio ci limiteremo a creare un’unica classe: possiamo posizionarla dove vogliamo all’interno del progetto, l’applicazione sarà in grado di rilevarla comunque. Per mantenere la struttura del progetto organizzata, comunque, ho preferito creare una cartella chiamata UnitTests, all’interno della quale ho creato una nuova classe chiamata SimpleUnitTest tramite il menu contestuale che compare cliccando sulla cartella con il tasto destro e scegliendo Add – New Item e Class file come tipologia.

La prima cosa da fare è aggiungere nella dichiarazione il namespace Microsoft.VisualStudio.TestTools.UnitTesting: in questo modo possiamo accedere agli attributi e alle classi che ci serviranno per scrivere i test. Il secondo step è quello di marcare l’intera classe con l’attributo [TestClass]: in questo modo diciamo all’applicazione che la nostra classe contiene degli unit test che devono essere valutati.

Ora aggiungiamo un semplice unit test (anche se, a dire la verità, l’esempio che vedremo lo definirei stupido più che semplice Smile): lo scopo è solmente quello di mettervi a vostro agio con il framework.

 

[TestClass]
public class SimpleUnitTest
{
    [TestMethod]
    public void SimpleTest()
    {
        int a = 1;
        int b = 2;

        int c = a + b;

        Assert.IsTrue(c == 3);
    }
}

Potete notare che il metodo SimpleTest è stato marcato con l’attributo [TestMethod]: in questo modo diciamo all’applicazione che il metodo rappresenta un test e che deve quindi essere valutato. Il test è molto semplice: sommiamo due numeri e controlliamo che il risultato sia corretto, utilizzando la classe Assert, che contiene diversi metodi che possono essere utilizzati per valutare il risultato di un test. In questo caso, dobbiamo testare una condizione di tipo booleano, quindi possiamo usare il metodo IsTrue. Altri esempi di metodi disponibili solo IsNotNull (per verificare che un oggetto sia stato correttamente inizializzato e contenga un valore) o IstanceOfType (per verificare che il tipo di un oggetto sia quello atteso).

Lanciate l’applicazione ed eseguite i test: questa volta il test sarà eseguito e sarà mostrato l’esito. Ovviamente, in questo caso, il test passerà, dato che 1+2 = 3.

 

unit2

Ora creiamo un esempio di test che fallisce: cambiate la condizione che viene verificata in modo che non sia più vera, come nell’esempio:

[TestClass]
public class SimpleUnitTest
{
    [TestMethod]
    public void SimpleTest()
    {
        int a = 1;
        int b = 2;

        int c = a + b;

        Assert.IsTrue(c == 4);
    }
}

Lanciate nuovamente l’applicazione: questa volta vedrete il test fallire. Cliccando su di esso potrete vedere i dettagli e il motivo per cui è fallito: in questo caso, ad esempio, potete chiaramente vedere che l’operazione Assert.IsTrue ha dato esito negativo.

 

unit3

Usare i tag

In alcuni casi non avete la necessità di eseguire tutti i test che sono disponibili nel progetto, ma solamente un sottoinsieme: ecco qual è lo scopo dei tag. Per utilizzarli, dovete aggiungere un nuovo namespace alla vostra classe, Microsoft.Phone.Testing, il quale vi permetterà di decorare i metodi con l’attributo Tag, seguito da una parola chiave. Per mettere alla prova questa funzionalità aggiungiamo un nuovo test alla nostra classe. Andremo però ad aggiungere l’attributo Tag solo ad uno dei due metodi disponibili.

 

[TestClass]
public class SimpleUnitTest
{  
    [Tag("SimpleTests")]
    [TestMethod]
    public void SimpleTest()
    {
        int a = 1;
        int b = 2;

        int c = a + b;

        Assert.IsTrue(c == 3);
    }

    [TestMethod]
    public void SimpleTest2()
    {
        int a = 3;
        int b = 1;

        int c = a + b;

        Assert.IsTrue(c == 4);
    }
}

Lanciate nuovamente l’applicazione e, questa volta, nella schermata iniziale, impostate lo switch Use tags su On. Vi verrà chiesto di specificare una parola chiave che sarà utilizzata dall’applicazione per determinare i test da esegire: inserite la keword SimpleTests (ovvero il tag che abbiamo assegnato al metodo SimpleTest) e premete il pulsante Play. Potrete notare che, nonostante il fatto che ci siano due metodi di test nella vostra classe, solamente il primo sarà eseguito.

Il tagging è un ottimo modo per raggruppare gli unit test così che, se dovete testare solo una specifica classe o feature, non siate costretti ad eseguire nuovamente tutti i test che, nell’ambito di un grosso progetto, possono diventare molto numerosi.

Debugging

Se un test fallisce e non riuscite a capire perchè, è molto semplice fare il debug: dato che, quando lanciate lo unit test runner da Visual Studio, state lanciando una normale applicazione Windows Phone, potete semplicemente impostare dei breapoint all’interno dei metodi: quando i test verranno eseguiti l’esecuzione si fermerà e avrete così la possibilità di ispezionare il codice per capire cosa sta succedendo.

Nella prossima punata

Nel prossimo post andremo avedere alcuni scenari più avanzati, ma piuttosto comuni, come il testing di metodi asincroni e il mocking.


Windows Phone , Unit testing

0 comments

Async Targeting Pack: perchè è utile nei progetti Windows Phone 8

Print Content | More

Microsoft ha rilasciato recentemente l’Async Targeting Pack per Visual Studio 2012, ovvero il successore della vecchia Async CTP che era disponibile per Visual Studio 2010. Il suo scopo è quello di aggiungere il supporto al nuovo pattern async / await introdotto in C# 5 anche alle “vecchie tecnologie” che, essendo ancora basate sulla versione 4 di C#, non sono in grado di utilizzarlo. Esempi di queste tecnologie sono Silverlight (sia la 4 che la 5) e Windows Phone 7.5: in parole povere, stiamo parlando di tutte quelle tecnologie che sono basate sul .NET Framework 4, dato che il nuovo framework .NET 4.5 (che è stato rilasciato insieme a Windows 8) è basato su C# 5.

L’installazione è molto semplice: è sufficiente utilizzare NuGet, facendo clic con il tasto destro sul progetto e selezionando Manage NuGet packages. La prima cosa da fare è cambiare il filtro di ricerca predefinito: dato che l’async targeting pack è ancora in beta, occorre cambiare il filtro posizionato in cima alla finestra (all’interno del menu a tendina) da Stable only a Include prerelease. Una volta fatta questa modifica, dovete lanciare la ricerca usando la keyword Bcl.Async e installare il pacchetto dal nome Async for .NET Framework 4, Silverlight 4 and 5 and Windows Phone 7.5. Automaticamente NuGet risolverà tutte le dipendenze richieste e installerà anche il pacchetto Microsoft.Bcl.

image_thumb2

Ma veniamo al titolo del post: per quale motive questo pacchetto dovrebbe essere interessante anche per lo sviluppo di applicazioni per Windows Phone 8? Si tratta, infatti, di una nuova tecnologia, basata su un subset del Windows Runtime, perciò il supporto alle keyword async e await è nativo.

Il motivo è che, per mantenere la retro compatibilità con la vecchia versione della piattaforma (che non supportava il pattern async e await, a meno di non utilizzare la Async CTP), alcune delle vecchie classi che sono state mantenute anche nel nuovo runtime non espongono i metodi necessari per effettuare operazioni asincrone con il nuovo pattern. Prendiamo come esempio la classe WebClient, che è spesso utilizzata per effettuare operazioni di rete (come scaricare un file). Al contrario delle altre API di WinRT (come quelle per lavorare con lo storage o con i sensori), questa classe utilizza ancora il vecchio approccio basato sulle callback: ci si registra per un evento, che viene scatenato nel momento in cui l’operazione di rete è terminata, si lancia il download o l’upload e, all’interno dell’event handler, si gestiscono tutte le operazioni che devono essere eseguite con il risultato (ad esempio, salvare il file nello storage o mostrarlo a video).

Ecco un esempio:

WebClient client = new WebClient();
client.DownloadStringCompleted += (obj, args) =>
                                      {
                                          if (args.Error == null)
                                          {
                                              MessageBox.Show(args.Result);
                                          }
                                      };
client.DownloadStringAsync(new Uri("http://www.qmatteoq.com"));

Quello che facciamo è scaricare l’HTML della home page di questo blog e, quando l’operazione è terminata, se non si sono verificati errori, lo mostriamo utilizzando una MessageBox.

Questo codice non è altrettanto semplice da scrivere e da capire come quello che potremmo scrivere grazie all’utilizzo delle keyword async e await, principalmente perchè non viene eseguito in maniera sequenziale: le eventuali righe di codice posizionate dopo la chiamata al metodo DownloadStringAsync verrebbero eseguite subito dopo aver attivato l’operazione di rete ma, ad un certo punto, l’esecuzione si bloccherebbe e l’applicazione inizierebbe ad eseguire il codice contenuto nell’event handler DownloadStringCompleted.

In più, probabilmente, il risultato sarà del codice un po’ confusionario: dobbiamo utilizzare l’approccio basato su callback per gestire l’operazione di rete ma, ad esempio, dovremmo utilizzare il pattern async e await per salvare l’HTML della pagina in un file nello storage tramite le nuove API.

Ecco che ci viene in aiuto l’Async targeting pack: oltre ad aggiungere il supporto alle keyword async e await (che non è necessario nel nostro caso, dato che il Windows Runtime for Windows Phone le supporta già) aggiunge una serie di extension methods, che introducono nelle “vecchie classi” dei nuovi metodi per lavorare con la classe Task e che possono essere usati, perciò, in combinazione con la keyword await.

Alcuni esempi di classi che beneficiano dell’installazione di questa libreria sono WebClient, HttpWebRequest e Stream. In questo modo possiamo modificare l’esempio precedente per utilizzare il nuovo approccio:

private async void OnDownloadAsync(object sender, RoutedEventArgs e)
{
    WebClient client = new WebClient();
    string result = await client.DownloadStringTaskAsync("http://wp.qmatteoq.com");
    MessageBox.Show(result);
}

 

Oppure, ad esempio, possiamo effettuare un’operazione di rete utilizzando la classe HttpWebRequest in maniera molto più semplice rispetto al vecchio approccio:

 

private async void OnDownloadAsync(object sender, RoutedEventArgs e)
{
    HttpWebRequest request = HttpWebRequest.CreateHttp("http://wp.qmatteoq.com");
    HttpWebResponse webResponse = await request.GetResponseAsync() as HttpWebResponse;
    MessageBox.Show(webResponse.StatusDescription);
}

 

Oppure, ancora, possiamo usare gli extension methods della classe Stream per recuperare il contenuto della richiesta di tipo HttpWebRequest vista nell’esempio precedente:

 

private async void OnDownloadAsync(object sender, RoutedEventArgs e)
{
    HttpWebRequest request = HttpWebRequest.CreateHttp("http://wp.qmatteoq.com");
    HttpWebResponse webResponse = await request.GetResponseAsync() as HttpWebResponse;
    Stream responseStream = webResponse.GetResponseStream();

    using (StreamReader reader=new StreamReader(responseStream))
    {
        string content = await reader.ReadToEndAsync();
        MessageBox.Show(content);
    }
}


Avrete certamente capito, perciò, il motivo per cui vi consiglio caldamente di installare l’Async targeting pack in qualsiasi progetto Windows Phone 8 con il quale andrete a lavorare!


Windows Phone , Microsoft , Async

3 comments

Nokia Premium Developer Program

Print Content | More

Nokia ha annunciato una nuova iniziativa per gli sviluppatori Windows Phone decisamente interessante. Di cosa si tratta? Allo stesso prezzo dell’account sviluppatori tradizionale (ovvero 99 $) avrete accesso ai seguenti benefit:

  • Un token per iscriversi sul Windows Phone Dev Center, potendo così pubblicare le vostre applicazioni sullo Store e sbloccare fino a 3 device. Il token può essere usato sia per la prima iscrizione, che per rinnovare un account già esistente (vi ricordo infatti che l’iscrizione è annuale).
  • Una licenza per la suite di controlli di Telerik dedicata a Windows Phone.
  • Un anno di iscrizione a Buddy.com, che offre una serie di servizi cloud per gestire notifiche push, messaggisitica, autenticazione, ecc nelle vostre applicazioni. Il vantaggio di questi servizi è che sono giá pronti per essere utilizzati: lo sviluppatore deve solo configurarli, senza doverli implementare da zero. Buddy.com offre diversi tipi di abbonamento: quello incluso nell’offerta vi mette a disposizione 1 milione di chiamate al mese verso le loro API.
  • 2 ticket per richiedere supporto a Nokia per risolvere problemi con lo sviluppo della vostra applicazione.

Il valore totale di tutti questi benefit è di 1500 $: capite quindi l’assoluto vantaggio di questo pacchetto che, al prezzo della sola iscrizione allo Store, offre tanti altri vantaggi di grande valore. Se state pensando di iscrivervi oppure avete un abbonamento in scadenza che volete rinnovare, non avete motivi per non approfittarne!

Trovate tutte le informazioni e il link per acquistare l’offerta in questa pagina del portale Nokia Developer.


Windows Phone , Nokia , Marketplace

0 comments