Una nuova libreria per integrare Facebook nelle applicazioni Windows 8.1, Windows Phone 8.1 e Windows 10
Questo post è stato scritto da Matteo Pagani , Support Engineer in Microsoft per il programma AppConsult.
Qualche tempo fa, sempre su questo blog, ho avuto il piacere di pubblicare alcuni articoli dedicati all'integrazione con Facebook nelle Windows Store app per Windows e Windows Phone 8.1.
Oggi sono qui per parlarvi di una nuova libreria dedicata a questo scopo che, come Microsoft, abbiamo recentemente rilasciato sotto forma di progetto open source disponibile su GitHub.
I punti di forza di questa libreria rispetto a Facebook. NET (trattata nei precedenti articoli) sono:
- Maggiore semplicità di utilizzo, soprattutto per quanto riguarda l'integrazione del login
- E' sviluppata in C++, di conseguenza offre migliori performance e non ha dipendenze dal CLR di .NET
- Oltre a supportare le Windows Store app per Windows 8.1 e Windows Phone 8.1, è compatibile anche con le nuovissime Universal Windows app di Windows 10
Nel corso di questo post vedremo come integrarla e utilizzarla nelle nostre applicazioni.
Aggiungere la libreria al vostro progetto
La libreria non viene, al momento, distribuita come pacchetto NuGet. Di conseguenza, dovete scaricarla manualmente a aggiungerla alla vostra soluzione di Visual Studio. Il progetto, come già anticipato, è disponibile su GitHub all'indirizzo https://github.com/Microsoft/winsdkfb: il modo più semplice per scaricarlo è usare i tool Git integrati in Visual Studio. In questo modo, sarà più semplice per voi mantenere la libreria aggiornata ogni qualvolta il team rilascerà degli aggiornamenti.
Ecco come fare:
- Aprite Visual Studio (il riferimento per questa guida è la versione 2015, ma i passaggi sono gli stessi con la 2013).
- Aprite Team Explorer (se non è già presente nella schermata iniziale, lo trovate dal menu View – Team Explorer)
- Troverete la voce "Local Git repositories": premete il pulsante Clone e specificate
- Nel primo campo, l'URL del repository GIT, ovvero https://github.com/Microsoft/winsdkfb
- Nel secondo campo, la cartella sul vostro disco nella quale volete creare una copia del progetto
- A questo punto premete il pulsante Clone e Visual Studio creerà una copia locale del progetto sul vostro computer. In qualsiasi momento, potrete accedere, sempre da Team Explorer, al repository e alla sezione Sync, che vi permetterà di sincronizzare la copia locale con quella presente su GitHub, dandovi così la possibilità di scaricare eventuali aggiornamenti.
Ora che avete una copia locale della libreria, potete aggiungerla alla soluzione che contiene la vostra Windows Store app. Fate clic, perciò, con il tasto destro in Solution Explorer sulla soluzione e scegliete Add -> Existing Project.
Dovrete aggiungere il progetto:
- FBWinSDK\FBSDK-UWP\FBSDK-UWP\FBSDK-UWP.vcxproj nel caso in cui stiate sviluppando una Universal Windows app per Windows 10. In tal caso, il progetto compilerà solo con Visual Studio 2015 e l'SDK di Windows 10 installata.
- FBWinSDK\FBWinSDK\FBWinSDK.Windows\FBWinSDK.Windows.vcxproj nel caso in cui stiate sviluppando una Windows Store app per Windows 8.1.
- FBWinSDK\FBWinSDK\FBWinSDK.WindowsPhone\FBWinSDK.WindowsPhone. vcxproj nel caso in cui stiate sviluppando una Windows Store app per Windows Phone 8.1
A questo punto, dovreste avere una soluzione in Visual Studio molto simile alla seguente:
L'ultimo passaggio necessario è aggiungere un riferimento, nel progetto principale dell'applicazione, alla libreria: fate clic con il tasto destro sul progetto, scegliete Add reference e andate a cercare alla voce Projects l'elemento di nome Facebook.
La configurazione è completata. Ora è necessario procedere alla configurazione dell'applicazione sul portale sviluppatori di Facebook.
Registrare l'applicazione Facebook
Se ricordate quanto descritto nel primo post dedicato alla vecchia libreria Facebook .NET, l'integrazione di un'applicazione con Facebook richiede la configurazione della stessa su un portale apposito gestito dal social network. Ad ogni applicazione web, desktop o mobile, infatti, deve corrispondere un'applicazione sul portale di Facebook: ciò è necessario per gestire la fase di autenticazione, nonchè i vari permessi per accedere alle funzionalità offerte dal social network.
L'utilizzo di questa nuova libreria non fa eccezione a questa regola: dovrete, perciò, seguire la stessa procedura descritta nel post originale, al fine di ottenere un Package SID, da includere poi alla voce Windows Store ID nella configurazione dell'applicazione sul portale sviluppatori di Facebook. Dato che la procedura rimane invariata, non riporterò nuovamente qui i passaggi.
Unica eccezione: se siete in fase di testing e, per il momento, non avete intenzione di pubblicare l'applicazione, avete la possibilitè di ottenere un Package SID di test senza dover iniziare il procedimento di pubblicazione sullo Store. Tale SID si ottiene tramite una API del Windows Runtime, ovvero:
string SID = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
Vi basta, perciò, includere la riga di codice precedente nella vostra applicazione e recuperare il valore della variabile SID (mettendo un breakpoint, mostrandola a schermo, stampandola nella console di debug, ecc.). Tale SID andrà poi inserito, come descritto nel post originale, all'interno della sezione Settings dell'applicazione sul portale Facebook, alla voce Windows Store ID. E' importante ricordarsi che bisogna rimuovere il protocollo ms-app:/// dal valore ottenuto. Se, ad esempio, il metodo precedente vi restituisce il valore:
ms-app://s-1-15-2-2031376880-2039615047-2889735989-2649504141-752107641-3656655002-2863893494/
L'ID da inserire nel portale Facebook sarà il seguente:
s-1-15-2-2031376880-2039615047-2889735989-2649504141-752107641-3656655002-2863893494
Una volta completata questa procedura e configurata l'applicazione Facebook, siamo pronti per "sporcarci le mani" e scrivere un po' di codice.
Effettuare il login
Effettuare il login è un'operazione molto semplice con la nuova libreria, grazie alla classe FBSession che rappresenta una sessione di Facebook. Per iniziare la procedura di autenticazione ci servono alcune informazioni:
- Il Package SID, che abbiamo recuperato in precedenza
- L'AppId di Facebook, che possiamo recuperare dal portale sviluppatori di Facebook nella pagina principale della Dashboard (vedi immagine seguente).
I permessi di Facebook che abbiamo intenzione di utilizzare. Facebook, infatti, utilizza un sistema di permessi per definire che tipo di interazioni con il social network può effettuare un'applicazione. Si va da quelli base (come recuperare le informazioni sull'utente collegato o la lista degli amici) a quelli più avanzati (come fare il like di una pagina, pubblicare un post o una foto sulla timeline dell'utente, ecc.). A questo indirizzo trovate l'elenco di tutti i permessi disponibili: https://developers.facebook.com/docs/facebook-login/permissions/v2.4#reference E' importante sottolinare però che, come comportamento predefinito, Facebook fornisce ad un'applicazione solo una serie di permessi base, ovvero:
- email, per accedere alla mail con cui è registrato l'utente
- public_profile, per accedere alle informazioni pubbliche del profilo dell'utente
- user_friends, per accedere all'elenco degli amici che stanno utilizzando anch'essi la vostra applicazione
Qualsiasi altro permesso (come publish_actions, che vi da la possibilità di pubblicare contenuti sulla timeline dell'utente), richiede che la vostra applicazione Facebook superi una fase di revisione, nella quale dovrete dettagliare le motivazioni e i casi d'uso per i quali avete la necessità di usare questi permessi. Si tratta di un processo di validazione gestito da Facebook e indipendente dalla certificazione dell'applicazione Windows sullo Store. Trovate maggiori dettagli all'indirizzo https://developers.facebook.com/docs/apps/review
Ecco un esempio di codice completo di login:
private async void OnLoginClicked(object sender, RoutedEventArgs e)
{
string SID = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
string AppId = "858381294217135";
FBSession session = FBSession.ActiveSession;
session.FBAppId = AppId;
session.WinAppId = SID;
session.AddPermission("public_profile");
FBResult result = await session.LoginAsync();
if (result.Succeeded)
{
//user is logged in
}
}
Innanzitutto si recupera un riferimento alla sessione corrente, tramite la proprietà ActiveSession della classe FBSession. Dopodichè, il SID e l'AppId di Facebook vengono valorizzati, rispettivamente, usando le proprietà WinAppId e FBAppId. Infine, i permessi vengono aggiunti con il metodo AddPermission() , che richiede come parametro l'identificativo del permesso, secondo la tabella già segnalata in precedenza. Nell'esempio, richiediamo il permesso di tipo public_profile, che ci da accesso alle informazioni pubbliche dell'utente.
Il login viene effettuato chiamando il metodo LoginAsync() : a questo punto, l'applicazione mostrerà un flyout (il cui contenuto è gestito direttamente da Facebook) in cui l'utente dovrà inserire le proprie credenziali, come nell'immagine seguente.
Una volta che l'utente ha completato l'operazione, vi verrà restituto un oggetto di tipo FBResult con l'esito dell'operazione. Nello specifico, tramite la proprietà Succeded potrete scoprire se l'operazione è andata a buon fine oppure no (ed, eventualmente, scoprire tramite la proprietà ErrorInfo cosa è andato storto).
Mostrare il profilo dell'utente
La classe FBSession contiene una proprietà di nome User che, una volta che il login è stato completato con successo, viene valorizzata con le informazioni sull'utente collegato. La maggior parte delle proprietà esposte sono di facile comprensione e vi permettono di recuperare le informazioni del profilo Facebook che l'utente ha scelto di rendere pubbliche, come Name (il nome e cognome) , Gender (il sesso), Location (la sua posizione), ecc.
Una funzionalità interessante è che la libreria contiene un controllo già pronto per mostrare l'immagine del profilo dell'utente. Il controllo si chiama ProfilePictureControl ed è incluso nel namespace Facebook, che dovete dichiarare nell'intestazione della pagina, come nell'esempio seguente:
<Page
x:Class="Windows10.MainPage"
xmlns:facebook="using:Facebook"
mc:Ignorable="d">
<facebook:ProfilePictureControl x:Name="Profile" Width="300" Height="300" />
</Page>
Una volta inserito il controllo nella pagina, potrete mostrare l'immagine del profilo semplicemente valorizzando la proprietà UserId del controllo con l'id Facebook dell'utente, che potete recuperare dalla classe FBUser vista in precedenza. Ecco un esempio completo di login che, in caso di successo, mostra alcune informazioni dell'utente, inclusa l'immagine del profilo:
private async void OnLoginClicked(object sender, RoutedEventArgs e)
{
string SID = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
string AppId = "858381294217135";
session = FBSession.ActiveSession;
session.FBAppId = AppId;
session.WinAppId = SID;
session.AddPermission("public_profile");
FBResult result = await session.LoginAsync();
if (result.Succeeded)
{
FBUser user = session.User;
UserName.Text = user.Name;
UserId.Text = user.Id;
Profile.UserId = user.Id;
}
}
Mostrare delle dialog
Facebook offre il concetto di dialog, ovvero dei flyout che la vostra applicazione può mostrare per demandare al social network alcune operazioni che, normalmente, richiederebbero per motivi di sicurezza dei permessi avanzati.
L'SDK di Facebook supporta due tipologie di dialog:
- Feed dialog, per pubblicare un contento sulla timeline dell'utente. Si richiama con il metodo ShowFeedDialog().
- Request dialog, per invitare altre persone ad usare la vostra applicazione (questa funzionalità è disponibile solo se la vostra applicazione, sul portale di Facebook, è stata inserita nella categoria Games). Si richiama con il metodo ShowRequestsDialog().
Entrambe le tipologie di dialog sfruttano lo stesso approccio:
- Si definiscono i parametri di configurazione, tramite la classe PropertySet
- Si chiama il metodo dell'SDK che mostra la dialog, passando i parametri definiti nel punto precedente
- Anche in questo caso, una volta che l'utente ha terminato di interagire con la dialog viene restituito un oggetto di tipo FBResult, che ci permette di determinare l'esito dell'operazione.
Nell'esempio seguente utilizziamo il metodo ShowFeedDialog() per consentire all'utente la pubblicazione di un link sulla sua timeline:
private async void OnPostClicked(object sender, RoutedEventArgs e)
{
FBSession session = FBSession.ActiveSession;
if (session.LoggedIn)
{
PropertySet parameters = new PropertySet();
parameters.Add("title", "MSDN Italy blog");
parameters.Add("link", "http://blogs.msdn.com/b/italy/");
parameters.Add("description", "Il blog ufficiale di MSDN Italia");
FBResult result = await session.ShowFeedDialog(parameters);
string message;
if (result.Succeeded)
{
message = "Succeded";
}
else
{
message = "Failed";
}
MessageDialog dialog = new MessageDialog(message);
await dialog.ShowAsync();
}
}
Dato che, in questo caso, presumiamo che l'utente abbia già fatto login, non ripetiamo nuovamente tutta la procedura vista in precedenza. Ci limitiamo, per scrupolo e per evitare errori imprevisti, a recuperare un riferimento alla sessione corrente (tramite la proprietà ActiveSession della classe FBSession) e a verificare che la proprietà LoggedIn sia uguale a true.
Nell'esempio possiamo vedere il funzionamento della classe PropertySet: si tratta semplicemente di un contenitore di coppie chiave / valore, all'interno del quale inserire i vari parametri necessari per la richiesta. Nello specifico, per consentire la pubblicazione di un link, ci servono tre parametri:
- title, con il nome del sito
- link, con l'URL del sito
- description, con una descrizione testuale
L'oggetto di tipo PropertySet viene poi passato come parametro al metodo ShowFeedDialog() che si fa carico di mostrare all'utente la schermata di condivisione, come nell'immagine seguente.
Una volta che l'utente ha completato la condivisione, siamo in grado di determinare l'esito dell'operazione. Un caso tipico di errore è la chiusura, da parte dell'utente, della finestra di dialogo o la pressione del pulsante Cancel per annullare l'operazione.
Interagire con le Graph API
Uno degli utilizzi più frequenti dell'SDK di Facebook è l'interazione con le Graph API, ovvero un set di API REST che Facebook mette a disposizione per effettuare le operazioni più comuni con i servizi offerti dal social network e che trovate documentate all'indirizzo https://developers.facebook.com/docs/graph-api
Come per la maggior parte dei servizi moderni, si tratta di un insieme di API REST che comunicano sfruttando il formato JSON e i principali comandi del protocollo HTTP, come GET o POST. I vari endpoint delle Graph API sono dei normalissimi URL. Ad esempio, per accedere alle informazioni sul proprio profilo si usa l'endpoint /me e una chiamata di tipo GET. Oppure, se volessimo pubblicare un contenuto sulla timeline dell'utente, dobbiamo usare l'endpoint /{user-id}/feed e una chiamata di tipo POST.
La nuova SDK di Facebook offre una serie di metodi che semplificano l'integrazione con queste API e permettono di lavorare con classi e oggetti, anzichè direttamente con il formato JSON. Attenzione che, come ricordato in precedenza, molte di queste API richiedono dei permessi speciali da parte di Facebook, che sono ottenibili solo dopo aver superato un processo di review.
Per questo motivo, per il prossimo esempio, vi mostrerò un altro approccio per recuperare le informazioni sul profilo dell'utente: invece di usare la classe FBUser, recupereremo manualmente i dati tramite le Graph API. Ovviamente, si tratta di un esempio puramente didattico: nella realtà, è consigliato utilizzare la classe FBUser, molto più semplice e immediata. Questo approccio ci permette però di dimostrare in maniera semplice l'interazione con le Graph API senza la necessità di avere permessi speciali: è sufficiente, infatti, utilizzare il permesso public_profile per recuperare questa informazione.
Il punto di partenza è la creazione di una classe che rappresenti la risposta in JSON dell'API che vogliamo utilizzare. Potete fare riferimento alla documentazione delle Graph API: non è necessario che tutte le proprietà siano mappate, è sufficiente definire quelle che vi servono realmente. Ad esempio, nel nostro scenario, dobbiamo utilizzare l'endpoint /me per recuperare il profilo dell'utente collegato. In base alla documentazione, tale servizio ci restituisce un JSON con le proprietà descritte in questa pagina: https://developers.facebook.com/docs/graph-api/reference/user
Nel nostro caso, siamo interessati solamente al nome e all'id dell'utente: di conseguenza, è sufficiente creare una classe che abbia queste due proprietà. E' importante che abbiano lo stesso nome di quelle riportate nella documentazione, come nell'esempio seguente:
public class Profile
{
public string Name { get; set; }
public string Id { get; set; }
}
Tale classe ci servirà per gestire la deserializzazione del JSON, ovvero la procedura che si farà carico, in automatico, di convertire il JSON restituito dal servizio Facebook (che è un dato "piatto", di tipo testuale) in un oggetto che possiamo manipolare all'interno dell'applicazione.
Il passaggio successivo è quello di definire un metodo statico all'interno della classe, che riceverà in ingresso il JSON di risposta e restituirà l'oggetto deserializzato. Questo approccio è indispensabile per poter usare correttamente le API fornite dall'SDK di Facebook. Per aiutarci in questo compito, sfruttiamo la libreria JSON.NET, disponibile su NuGet e installabile facendo clic con il tasto destro sul vostro progetto e scegliendo la voce Manage NuGet Packages. L'identificativo della libreria è il seguente http://www.nuget.org/packages/Newtonsoft.Json/
Nota bene! L'ultima versione stabile della libreria è la 7.0.1 ma, quando utilizzata in una Universal Windows app, potrebbe darvi un errore di compilazione, lamentando la mancanza della libreria System.Runtime.Serialization. Il workaround, per il momento, è di fare un downgrade ed installare la versione 6.0.8.
Ecco come appare la definizione della classe Profile al termine del nostro lavoro:
public class Profile
{
public static Profile FromJson(string jsonText)
{
Profile profile = JsonConvert.DeserializeObject<Profile>(jsonText);
return profile;
}
public string Name { get; set; }
public string Id { get; set; }
}
Il metodo statico FromJson() non fa altro che ricevere in ingresso il dato JSON restituito da Facebook e di deserializzarlo, convertendolo in un oggetto di tipo Profile tramite il metodo DeserializeObject<T> della classe JsonConvert.
Ora che abbiamo definito questo metodo, possiamo utilizzarlo per interagire con le Graph API, come nell'esempio seguente:
private async void OnGetInfoClicked(object sender, RoutedEventArgs e)
{
string endpoint = "/me";
FBSingleValue value = new FBSingleValue(endpoint, null, Entities.Profile.FromJson);
FBResult result = await value.Get();
if (result.Succeeded)
{
Profile profile = result.Object as Profile;
string name = profile?.Name;
MessageDialog dialog = new MessageDialog(name);
await dialog.ShowAsync();
}
}
La comunicazione avviene tramite la classe FBSingleValue, che in fase di inizializzazione richiede tre parametri.
- L'endpoint delle Graph API da utilizzare (in questo caso, /me)
- Eventuali parametri di input, tramite un oggetto di tipo PropertySet (che abbiamo visto in precedenza). In questo caso, l'endpoint /me non richiede alcun parametro di configurazione, quindi possiamo passare null.
- Un riferimento al metodo statico che abbiamo definito in precedenza per effettuare la deserializzazione della risposta JSON.
Una volta inizializzato l'oggetto, la classe FBSingleValue espone un metodo asincrono per ogni principale comando HTTP. In questo caso, l'endpoint /me richiede una chiamata di tipo GET, perciò utilizziamo il metodo Get() : ci verrà nuovamente restituito un oggetto di tipo FBResult, con il risultato dell'operazione. Se avessi voluto invece, ad esempio, pubblicare un post sulla timeline dell'utente, sarebbe stata una chiamata di tipo POST: in questo caso, avremmo usato il metodo Post().
Se è andato tutto a buon fine, all'interno della proprietà Object troveremo la risposta del servizio già deserializzata: nel nostro caso, si tratta di un oggetto di tipo Profile. Nell'esempio, ci limitiamo a mostrare all'utente il nome dell'utente.
Nota bene: avrete notato, all'interno del codice, l'utilizzo della sintassi profile?.Name per recuperare il nome dell'utente. Si tratta di una delle nuove funzionalità introdotte in C# 6, che semplifica la gestione di potenziali valori nulli quando lavoriamo come un oggetto. Nell'esempio, il cast della proprietà Object al tipo Profile potrebbe fallire e, di conseguenza, la variabile profile essere uguale a null. In tal caso, la riga successiva darebbe un errore, perchè tenteremmo di accedere ad una proprietà di un oggetto non inizializzato. L'utilizzo del punto interrogativo dopo il nome della variabile fa sì che, in automatico, il codice non venga eseguito nel caso in cui questa sia nulla.
In conclusione
Nel corso di questo post abbiamo visto un'introduzione all'utilizzo della nuova libreria per integrare Facebook nelle vostre applicazioni. L'esempio mostrato nel corso del post è relativo ad una Universal Windows app per Windows 10, ma lo stesso approccio si può utilizzare all'interno di un'applicazione per Windows 8.1 e Windows Phone 8.1.
Potete scaricare il progetto di esempio per Windows 10 dal mio repository GitHub all'indirizzo: https://github.com/qmatteoq/FacebookSDKSample
Se, invece, volete contribuire allo sviluppo della libreria, segnalare eventuali problemi o leggere la documentazione ufficiale, potete fare riferimento al repository ufficiale: https://github.com/Microsoft/winsdkfb
Happy coding!