Sei uno sviluppatore .NET che ha sempre voluto fare un’applicazione mobile? O forse hai provato a costruire applicazioni mobili native con Android o iOS ma non ti piacevano i linguaggi? Bene, allora siete fortunati! Il mondo .NET è stato benedetto con Xamarin; un insieme di strumenti che ti permette di costruire applicazioni mobili per Android, iOS e Windows all’interno di Visual Studio.

Xamarin ha due gusti principali: Piattaforma Xamarin (Xamarin.iOS e Xamarin.Android) e Xamarin.Forms. Con Xamarin.Forms la maggior parte della vostra logica di business e l’interfaccia utente possono essere scritte all’interno di un progetto condiviso che produce applicazioni pienamente funzionanti su tutti e 3 i sistemi operativi iOS, Android e Windows (UWP). La piattaforma Xamarin, d’altra parte, è un lavoro molto specifico per la piattaforma ed è più simile alla scrittura di applicazioni native ma con C#.

In questo tutorial, guarderò più da vicino la piattaforma Xamarin e il set di strumenti del sistema operativo Android noto come Xamarin.Android. L’obiettivo generale è quello di permetterti di creare una semplice app nativa per Android con l’autenticazione utente di base inclusa.

Imposta Visual Studio e il tuo ambiente

Per seguire il tutorial avrai bisogno di una copia di Visual Studio, più il carico di lavoro ‘Sviluppo mobile con .NET’. Puoi abilitare questa funzione dalla prima installazione di Visual Studio o accedervi dalla voce di menu ‘Strumenti -> Ottieni strumenti e funzionalità…’:

Per testare ed eseguire la tua applicazione puoi scegliere se farlo con un emulatore Android in esecuzione sulla tua macchina di sviluppo o collegandoti direttamente a un dispositivo Android esistente. Non c’è un’opzione giusta qui e diversi sviluppatori preferiscono diversi fattori di forma. Se scegliete la prima opzione, dovrete assicurarvi, una volta selezionato il carico di lavoro, che nel pannello di destra (‘Installation details’) le caselle di controllo per Intel Hardware Accelerated Execution Manager e Google Android Emulator siano selezionate (come visto sopra).

Verifica il tuo ambiente Android in Visual Studio

Per verificare che tutto sia stato installato correttamente e sia stato configurato correttamente, vai a ‘Strumenti -> Opzioni -> Xamarin -> Impostazioni Android’ e controlla che i percorsi Java Development Kit Location e Android SDK Location siano validi (cioè abbiano il segno di spunta verde).cioè hanno un segno di spunta verde):

Se mancano entrambi dovrai installare manualmente il Java Development Kit o l’Android SDK rispettivamente.

Crea un’applicazione Xamarin

Inizia creando un nuovo progetto e seleziona il modello principale ‘Android App (Xamarin)’ (che si trova sotto il menu Android). Nella pagina successiva vorrai scegliere l’opzione ‘Single View App’ perché è un ottimo modello di partenza su cui lavorare.

Per quanto riguarda la versione minima di Android, questa è una scelta personale dello sviluppatore. C’è un compromesso tra l’essere in grado di accedere alle ultime e più grandi caratteristiche API nelle versioni più recenti e supportare i vostri clienti che hanno versioni più vecchie. Per aiutarvi a prendere questa decisione, Google pubblica i dati di distribuzione della versione della piattaforma che raccoglie come parte del loro cruscotto di distribuzione con una cadenza abbastanza regolare. La mia preferenza personale è tra 5.0 o 6.0 a seconda che si tratti di un’app per il consumo pubblico o di un’app commissionata solo per i telefoni aziendali (cioè probabilmente avranno gli ultimi aggiornamenti); in questo esempio ho scelto la seconda. Notate che questa versione differisce dalla Target Android Version, che dovrebbe essere sempre impostata sull’ultima versione dell’SDK rilasciata, poiché qualsiasi cosa di meno non sarà accettata nel Google Play store.

Una volta creato questo tutto ciò che rimane è importare i pacchetti NuGet richiesti. Per questo tutorial avrete bisogno di:

  • Xamarin.OpenId.AppAuth.Android – Per autenticare l’utente utilizzerete lo standard OpenID Connect (un miglioramento di OAuth 2.0). Il modo più semplice per implementare il codice client che rispetta questa specifica è utilizzando l’SDK client AppAuth per Android, e per fortuna Xamarin ha messo a disposizione un pacchetto di questa funzionalità da utilizzare.
  • System.IdentityModel.Tokens.Jwt – Il metodo di autenticazione qui utilizza token web JSON. Per estrarre i dati necessari da questi token avrai bisogno di questo pacchetto.

Inoltre, avrai bisogno anche di questi due pacchetti, poiché si basano su AppAuth:

  • Xamarin.Android.Support.v4
  • Xamarin.Android.Support.CustomTabs

Familiarizzare con il progetto Xamarin

Se non avete mai lavorato con Android prima, uno dei principi chiave da comprendere è il concetto di attività. Le attività sono componenti utilizzati per visualizzare la vostra interfaccia utente; nella loro forma più elementare, potete pensare alle attività come se fossero uguali alle pagine di un’applicazione tra cui l’utente può navigare. Un’attività nel codice è rappresentata da una classe, tuttavia come una pagina in ASP.NET puoi (e quasi sempre lo farai) associare un file di layout basato su XML (un file .axml) per un design visualizzabile. Tutti i nuovi progetti creano un file ‘MainActivity.cs’ e ‘activity_main.axml’ per iniziare come prima attività (cioè pagina) da eseguire all’apertura dell’applicazione. Questo può essere cambiato in qualsiasi altra attività utilizzando la proprietà MainLauncher = true all’interno dell’attributo Activity della classe.

Le risorse sono progettate per essere gestite all’interno della propria directory e seguono una convenzione di denominazione piuttosto rigida. Raccomando vivamente di memorizzare quante più risorse possibile in questa directory, poiché semplifica il riutilizzo di queste variabili per il vostro sviluppo continuo. Nella directory ‘values’ della directory Resources è dove troverete i file con scopi specifici:

  • Strings.xml – Ospita tutte le stringhe rivolte all’utente. Questo è particolarmente importante da usare perché ti permette di localizzare le tue stringhe per un pubblico globale.
  • Styles.xml – Dove troverai gli attributi per lo stile dei tuoi oggetti di design; pensalo come un file CSS.
  • Colors.xml – Un posto per memorizzare i riferimenti ai colori che usi più frequentemente come parte del tuo stile.
  • Dimens.xml – Come il nome potrebbe implicare, dove definisci le dimensioni impostate per il layout della tua app.

Le altre directory degne di nota non seguono alcuna convenzione di denominazione per i loro file, ma devono contenere determinati tipi di file:

  • Layout – Luogo per memorizzare i tuoi file .axml. Questi file definiscono i layout completi dell’attività, i componenti di layout che si generano e si popolano programmaticamente, i layout delle finestre di dialogo (avviso), ecc.
  • Menu – Dove troverai le definizioni dei menu e dei loro elementi. Questi sono file .xml che hanno menu come elemento principale e item elementi figli, che possono essere raggruppati con group elementi. I menu più comuni che incontrerai sono il menu di overflow (dal pulsante dei tre punti verticali) o il menu di navigazione (dal pulsante ‘hamburger’ della home).
  • Mipmap – Dove vuoi definire immagini che devono essere scalate a seconda della densità dello schermo, cioè quelle a cui fanno riferimento altre app, e non usate internamente. L’icona dell’app è il contenuto più comune che metteresti nelle directory mipmap.
  • Drawable – Non è standard in un modello di progetto predefinito, ma può essere creato da te. Questo è il posto in cui memorizzi le tue immagini/contenuti disegnabili da usare all’interno dell’applicazione, ad esempio splash screen, design personalizzato della barra di avanzamento, icone usate all’interno dell’applicazione, ecc.

Infine, se hai qualche file di contenuto grezzo che vuoi usare come parte della tua applicazione (ad esempio un file di testo o di font), allora la directory Assets è dove metterli. Come Assets questi file saranno distribuiti con la tua applicazione per potervi accedere con l’Asset Manager.

Per saperne di più su Assets e Resources e su come usarli, ci sono dei comodi file di testo ‘About’ in ogni directory di un progetto appena creato.

Aggiungi autenticazione utente a Xamarin con OpenID Connect

La maggior parte delle applicazioni di questi tempi richiedono una qualche forma di identificazione dell’utente per permettere allo sviluppatore di offrire esperienze su misura e a sua volta permettere all’utente di mantenere i propri dati attraverso dispositivi/installazioni. Oltre a questo c’è la questione del controllo degli accessi che potrebbe essere utile per autorizzare un sottoinsieme di utenti per funzionalità extra. Naturalmente questo può essere un compito abbastanza laborioso, soprattutto se siete nel business della creazione di applicazioni e avrete bisogno di un nuovo sistema per ogni singolo. Fortunatamente con Okta è possibile impostare un’applicazione in pochi minuti e poi tutto il duro lavoro è fatto per voi! Il servizio Okta è conforme a OAuth 2.0 ed è un OpenID Connect Provider certificato, quindi funziona perfettamente con il client SDK AppAuth per tutte le tue esigenze di autenticazione e autorizzazione.

Imposta la tua applicazione Okta

In primo luogo, dovresti impostare una nuova applicazione nel tuo account Okta per questo progetto. Se non ne hai ancora uno, è molto facile creare un nuovo account per sviluppatori senza limiti di tempo.

Una volta che questo è stato completato e hai effettuato l’accesso alla dashboard dello sviluppatore, prendi nota dell’URL Org perché ne avremo bisogno più tardi:

Dalla dashboard vai alla scheda ‘Applicazioni’ e da lì ‘Aggiungi applicazione’. Stai creando un’applicazione Android nativa, quindi è meglio scegliere il modello di piattaforma ‘Native’.

Da questa pagina aggiungi un nome per la tua applicazione e lascia tutto il resto come predefinito. Una volta salvato, prendi nota dei tuoi URI di reindirizzamento al login e dell’ID cliente, perché ti serviranno in seguito.

Per poter utilizzare questi tre valori da Okta con facilità in futuro, ti consiglio di metterli nella propria classe statica all’interno di una nuova directory per la logica di autenticazione:

public static class Configuration{ public const string ClientId = "{yourClientId}"; public const string LoginRedirectUri = "{yourRedirectUri}"; public const string OrgUrl = "https://{yourOktaDomain}";}

Creare il fornitore di autenticazione

Togliamo via il codice di base. Devi configurare l’applicazione per informarla del tuo schema URI di reindirizzamento. Lo schema è il tuo URI di reindirizzamento al login (nella forma standard di nome di dominio inverso) senza il percorso. Per esempio, dallo screenshot qui sopra il mio schema sarebbe ‘com.oktapreview.dev-123456’.

Il modo più semplice per farlo è inserire il seguente snippet del filtro intenzionale nel tuo file AndroidManifest.xml nella cartella Properties della tua soluzione. Aggiungi il seguente XML all’interno del tag Application e cambia il valore dello schema con il tuo:

<activity android:name="net.openid.appauth.RedirectUriReceiverActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="{yourRedirectRriScheme}" /> </intent-filter></activity>

Devi anche definire il modello per il risultato della tua autorizzazione con una classe semplice. Anche se non userò tutti i valori che ho scritto qui sotto all’interno del codice, mostrerò come popolarli per poterli usare dopo. Poiché questo fa parte del modello della vostra applicazione, create una cartella chiamata Models e aggiungete una classe AuthorizationResult.cs al suo interno. Poi, aggiungete il seguente codice:

public class AuthorizationResult{ public string AccessToken { get; set; } public string IdentityToken { get; set; } public bool IsAuthorized { get; set; } public string RefreshToken { get; set; } public string Scope { get; set; }}

Android non ha uno stato globale con cui lavorare, e quindi se volete passare valori semplici tra le attività, il modo migliore per farlo è con la funzionalità Extras sull’oggetto Intent. Un Intent è una classe predefinita in Android e un altro concetto fondamentale da capire. È l’astrazione di un’operazione da eseguire (cioè le tue ‘intenzioni’), e per navigare in avanti verso un’altra attività è necessario creare un’istanza di questa classe con quale attività ‘intendi’ andare. Le proprietà Extras sull’oggetto Intent sono in effetti solo un dizionario di chiavi per i valori dell’oggetto e vi si accede tramite Put e metodi Get tipizzati.

Mentre questi metodi mantengono l’uso relativamente chiaro e semplice, personalmente mi piace mantenere tutti gli accessi ad essi all’interno della propria classe (per essere precisi, una classe Extensions), per mantenere una migliore separazione degli interessi. Questo è estremamente utile in quanto non avete bisogno di accedere alle chiavi attraverso le classi e potete assicurare la sicurezza del tipo quando mettete e ricevete questi valori. Nel vostro fornitore di autorizzazioni vorrete: memorizzare il AuthState, essere in grado di controllare se è lì, e restituirlo se lo è. Create una nuova cartella chiamata Extensions nella root della soluzione. Poi aggiungete una nuova classe chiamata IntentExtensions.cs. Fai la classe public e static, poi aggiungi il seguente codice all’interno della classe:

public const string AuthStateKey = "authState";public static string GetAuthStateExtra(this Intent intent){ return intent.GetStringExtra(AuthStateKey);}public static bool HasAuthStateExtra(this Intent intent){ return intent.HasExtra(AuthStateKey);}public static void PutAuthStateExtra(this Intent intent, AuthState authState){ intent.PutExtra(AuthStateKey, authState.JsonSerializeString());}public static bool TryGetAuthStateFromExtra(this Intent intent, out AuthState authState){ authState = null; if (!intent.HasAuthStateExtra()) { return false; } try { authState = AuthState.JsonDeserialize(intent.GetAuthStateExtra()); } catch (JSONException) { return false; } return authState != null;}

Ora è il momento di definire il fornitore di autorizzazioni, AuthorizationProvider.cs nella cartella Authentication che hai creato prima per la classe Configuration.cs. Per prima cosa, rimuovi tutte le dichiarazioni using all’interno della classe appena creata, poi dichiara la configurazione come variabili static readonly:

private static readonly Uri ConfigurationEndpoint = Uri.Parse($"{Configuration.OrgUrl}/oauth2/default/.well-known/openid-configuration");private static readonly string Scopes = new { "openid", "profile", "email", "offline_access" };

L’endpoint di configurazione è uno standard in OpenID come endpoint di scoperta per trovare tutto ciò che è supportato. Notate qui che ho scritto questo usando il nome del provider “predefinito”. Se hai un provider diverso, vorrai cambiarlo qui. Notate anche che questo sta usando il gusto Android.Net della classe Uri, e non la versione System – dovrete aggiungere il primo ai vostri usi o qualificare completamente il tipo perché questo funzioni. La variabile Scopes, come ogni altro sistema OpenID, definisce ciò a cui siamo autorizzati ad accedere.

Poi dovresti dichiarare le tue variabili membro:

private AuthorizationRequest authorizationRequest;private PendingIntent completedIntent;private AuthState authorizationState;private readonly AuthorizationService authorizationService;private readonly Context context;private readonly TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();

Una rapida spiegazione su ciascuna:

  • La richiesta di autorizzazione e l’intento completato sono parametri creati per essere usati nella chiamata di autorizzazione. Li ho scritti come variabili globali qui per minimizzare la quantità di parametri di passaggio nei diversi metodi.
  • La variabile authorizationState come è chiamata definisce lo stato di autorizzazione corrente dato.
  • La variabile authorizationService contiene un’istanza del servizio di autorizzazione.
  • La variabile context qui è dell’attività chiamante, così potete fare riferimento ad essa quando necessario.
  • Infine, la taskCompletionSource ti permette di fare tutte queste chiamate in modo asincrono e di ritornare una volta completate.

Ora dovresti definire i valori di queste variabili readonly nel tuo costruttore, e dichiarare i metodi pubblici che il tuo codice chiamerà:

public AuthorizationProvider(Context context){ authorizationService = new AuthorizationService(context); this.context = context;}public async Task<AuthorizationResult> SignInAsync(){ ...}public void NotifyCallback(Intent intent){ ...}

Il metodo SignInAsync è come avrai capito un metodo asincrono per registrare un utente. Questo restituisce la classe AuthorizationResultche avete scritto prima. NotifyCallbackd’altra parte serve all’attività chiamante, una volta che è tornata dalla pagina di accesso esterna, per richiamare il fornitore di autorizzazioni e fargli sapere che ha finito. Il metodo di accesso è suddiviso in più subroutine e assomiglia a questo:

AuthorizationServiceConfiguration serviceConfiguration = await AuthorizationServiceConfiguration.FetchFromUrlAsync(ConfigurationEndpoint);BuildAuthorizationRequest(serviceConfiguration);BuildCompletedIntent(serviceConfiguration);return await RequestAuthorization();

In questo avete definito la configurazione del servizio, costruito la richiesta di autorizzazione e l’intento di chiamare una volta che l’autorizzazione è stata completata, e poi attendere la richiesta di autorizzazione. Per costruire la richiesta di autorizzazione è come segue:

private void BuildAuthorizationRequest(AuthorizationServiceConfiguration serviceConfiguration){ AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder( serviceConfiguration, Configuration.ClientId, ResponseTypeValues.Code, Uri.Parse(Configuration.LoginRedirectUri)); builder.SetScope(string.Join(" ", Scopes)); authorizationRequest = builder.Build();}

Il lavoro di questo metodo è quello di astrarre il lavoro AuthorizationRequest.Builder e creare la richiesta. Poi dovete costruire il Intent per una volta che l’operazione è completata:

private void BuildCompletedIntent(AuthorizationServiceConfiguration serviceConfiguration){ Intent intent = new Intent(context, typeof(MainActivity)); intent.PutAuthStateExtra(new AuthState()); completedIntent = PendingIntent.GetActivity(context, authorizationRequest.GetHashCode(), intent, 0);}

L'”intenzione” che volete eseguire qui è di tornare al vostro MainActivity con un nuovo AuthState allegato. Infine, in questo flusso, ci si occupa dell’esecuzione della richiesta:

private async Task<AuthorizationResult> RequestAuthorization(){ authorizationService.PerformAuthorizationRequest(authorizationRequest, completedIntent); await taskCompletionSource.Task; return new AuthorizationResult() { AccessToken = authorizationState?.AccessToken, IdentityToken = authorizationState?.IdToken, IsAuthorized = authorizationState?.IsAuthorized ?? false, RefreshToken = authorizationState?.RefreshToken, Scope = authorizationState?.Scope };}

Poiché PerformAuthorizationRequest è sincrono e ritorna nullo, il codice attende il membro taskCompletionSource, sapendo che sarà impostato solo una volta recuperata la risposta. A questo stesso punto sapete che lo stato di autorizzazione sarà popolato (se tutto è riuscito), e quindi potete restituire i loro valori come parte dell’AuthorizationResult.

Il secondo metodo pubblico NotifyCallback, come ho detto prima, è quello che volete che la classe MainActivity richiami, una volta che il vostro completedIntent di cui sopra è eseguito. In questo metodo volete verificare la risposta, aggiornare lo stato in modo appropriato, e se ha successo, eseguire una richiesta di scambio di token:

if (!intent.TryGetAuthStateFromExtra(out authorizationState)){ taskCompletionSource.SetResult(false); return;}AuthorizationResponse authorizationResponse = AuthorizationResponse.FromIntent(intent);AuthorizationException authorizationException = AuthorizationException.FromIntent(intent);authorizationState.Update(authorizationResponse, authorizationException);if (authorizationException != null){ taskCompletionSource.SetResult(false); return;}authorizationService.PerformTokenRequest(authorizationResponse.CreateTokenExchangeRequest(), ReceivedTokenResponse);

Qui potete vedere che nei casi di fallimento ho impostato il risultato di taskCompletionSource a false, e questo sbloccherà il metodo RequestAuthorization sopra. Inoltre, il metodo PerformTokenRequest prende un delegato, ReceivedTokenResponse, per essere eseguito una volta completato. Questo metodo è il seguente:

private void ReceivedTokenResponse(TokenResponse tokenResponse, AuthorizationException authorizationException){ authorizationState.Update(tokenResponse, authorizationException); taskCompletionSource.SetResult(true);}

A questo punto dovreste avere tutti i dati di autorizzazione di cui avete bisogno, e quindi potete aggiornare opportunamente lo stato (dove troverete i valori da restituire dal metodo sign in) e impostare il risultato per sbloccare il task taskCompletionSource.

Implementare l’autenticazione nella tua interfaccia Xamarin

Come pulizia, se lo desideri, sentiti libero di rimuovere tutti i riferimenti alla ‘Floating Action Bar’ (scritta anche come ‘FAB’) all’interno dei file di classe/axml dell’attività principale, in quanto sono inutili in questa fase.

Per permettere all’utente di registrarsi è ora necessario implementare questa funzionalità nella UI. Dato il design predefinito, il modo più intuitivo per farlo sarebbe quello di aggiungere una voce al menu di overflow nell’angolo in alto a destra. Puoi farlo modificando il file menu_main.xml nella cartella ‘Resources -> menu’, e aggiungendo questo elemento come figlio del tag menu:

<item android:id="@+id/action_signin" android:orderInCategory="100" android:title="@string/action_signin" app:showAsAction="never" />

Con questo codice hai creato una nuova opzione con un titolo da definire nel file delle risorse stringa. Come detto prima, in Android è una buona pratica mettere tutto il testo rivolto all’utente nel file delle risorse delle stringhe. Per dichiarare questi dati, modifica il file strings.xml nella cartella ‘Resources -> values’ e aggiungi queste righe:

<string name="action_signin">Sign In</string><string name="welcome_message_format">Hi, %1$s!</string>

Non solo ho dichiarato una stringa per il pulsante ‘Sign In’ qui, ma ho anche aggiunto sopra una stringa per un messaggio di benvenuto all’utente una volta che si è registrato. L’equivalente del codice C# di this string would be “Ciao, {0}!”`, dove il segnaposto è di tipo stringa.

Nota che con tutti gli aggiornamenti a questi file basati su Resources, la classe Resource.designer.cs sarà automaticamente rigenerata con nuovi ID per ogni oggetto che hai creato, a cui puoi fare riferimento nel tuo codice. Se questo non funziona per un particolare file, selezionalo in Solution Explorer e guarda la finestra Properties. Assicurati che la proprietà CustomTool sia impostata sul valore MSBuild:UpdateGeneratedFiles, poiché questo è probabilmente mancante e impedisce al file designer di riconoscerlo come risorsa.

Poi aggiungi un ProgressBar al file di layout esistente activity_main.axml:

<ProgressBar android:id="@+id/signin_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingBottom="12dp" android:visibility="gone" />

Questo ProgressBar (o spinner, come nel caso), ha un ID che puoi referenziare con il codice, ed è impostato per stare al centro dello schermo. La visibilità è impostata su gone per ora, ma una volta che il tuo codice di autorizzazione è in esecuzione puoi impostarlo su visible e informare l’utente che l’app è occupata.

Ora hai un pulsante per aprire l’autenticazione e uno spinner di progresso per informare l’utente che l’app è occupata, è il momento di usarli. All’interno della tua classe MainActivity aggiungi la seguente proprietà all’attributo Activity (sopra l’intestazione della classe):

LaunchMode = LaunchMode.SingleTask

Questa proprietà assicura che ci sia una sola istanza della classe MainActivity, e non ne aprirai continuamente di nuove. Una volta fatto questo, aggiungete una variabile membro statica per la AuthorizationProvder che avete scritto sopra e create un’istanza di essa all’interno dell’override esistente del metodo OnCreate. Notate che questo dovrebbe essere fatto dopo il codice esistente all’interno del metodo:

private static AuthorizationProvider authorizationProvider;protected override void OnCreate(Bundle savedInstanceState){ ... authorizationProvider = new AuthorizationProvider(this);}

In seguito, sovrascrivete il metodo OnNewIntent. Lo scopo di questo è quando viene creato un nuovo intento di questa classe (cioè quando la finestra esterna di accesso ritorna), si chiama il metodo NotifyCallback dal AuthorizationProvider. È incluso anche un rapido controllo per assicurarsi che sia il flusso previsto:

protected override void OnNewIntent(Intent intent){ base.OnNewIntent(intent); if (intent != null && intent.Data.Path.Equals("/callback", StringComparison.OrdinalIgnoreCase)) { authorizationProvider.NotifyCallback(intent); }}

Ora aggiungete il codice dietro la voce di menu che avete aggiunto. Nell’override esistente del metodo OnOptionsItemSelected, aggiungi una dichiarazione if con una chiamata a un nuovo metodo che gestirà il processo di iscrizione come segue:

if (id == Resource.Id.action_signin){ OnSignInAttempted(); return true;}

Questo nuovo metodo inizierà rendendo visibile il ProgressBar che hai aggiunto poco fa; per recuperare qualsiasi componente dal file di layout, usa il metodo generico FindViewById e inserisci l’ID del componente come argomento. Dopodiché, fate una chiamata al metodo SignInAsync e attendete il suo risultato. Una volta che la chiamata è tornata, il risultato viene verificato come autorizzato. Se questa autorizzazione è fallita per qualsiasi motivo, appare una finestra di dialogo di errore, e lo spinner di progresso scompare di nuovo. Lascerò il dettaglio del caso di successo per ora, dato che hai ancora bisogno di un posto dove andare in quel caso:

private async void OnSignInAttempted(){ ProgressBar signInProgress = FindViewById<ProgressBar>(Resource.Id.signin_progress); signInProgress.Visibility = ViewStates.Visible; AuthorizationResult authorizationResult = await authorizationProvider.SignInAsync(); if (!string.IsNullOrWhiteSpace(authorizationResult.AccessToken) && authorizationResult.IsAuthorized) { // Placeholder: Success case } else { // Display an error to the user AlertDialog authorizationErrorDialog = new AlertDialog.Builder(this) .SetTitle("Error!") .SetMessage("We were unable to authorize you.") .Create(); authorizationErrorDialog.Show(); signInProgress.Visibility = ViewStates.Gone; }}

Quando l’utente è autenticato dovresti reindirizzarlo alla pagina successiva della tua esperienza. Se ti ricordi prima ogni pagina è rappresentata da un’attività, e quindi hai bisogno di crearne una nuova ora.

Per iniziare, all’interno della cartella ‘Resources -> layout’ avrai bisogno di creare il nuovo file di layout di attività “activity_dashboard.axml”. Il modo più semplice per farlo è andare sull’opzione New Item… nel menu contestuale e selezionare il modello ‘Android Layout’. All’interno del tuo nuovo file di layout aggiungi un semplice componente TextView per visualizzare un testo come questo:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"> <TextView android:id="@+id/welcome_message" android:textAppearance="?android:attr/textAppearanceMedium" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /></LinearLayout>

In questo snippet hai un componente TextView con un ID referenziabile che è centrato al centro della pagina, di cui mostrerà un messaggio di benvenuto. Successivamente creiamo una classe di attività corrispondente ‘DashboardActivity’ per mezzo dell’opzione ‘New Item…’ nel menu contestuale del progetto nel solution explorer e selezionando il modello ‘Activity’. Per collegare questa classe al suo file di layout, devi chiamare la funzione SetContentView nel metodo generato OnCreate() (sotto l’invocazione del metodo base ereditato):

SetContentView(Resource.Layout.activity_dashboard);

Per personalizzare il tuo messaggio di benvenuto, dovrai passare il nome dell’utente alla tua nuova attività. Se vi ricordate prima il modo migliore per farlo era con Extras sull’intento, e avete creato una classe Extensions per gestire questo. Come prima, aggiungi nuovi metodi per ‘Put’ e ‘Get’ di un extra ‘name’ nel file IntentExtensions.cs che hai creato sopra:

private const string NameKey = "Name";public static void PutNameExtra(this Intent intent, string name){ intent.PutExtra(NameKey, name);}public static string GetNameExtra(this Intent intent){ return intent.GetStringExtra(NameKey);}

Ora usando questa funzionalità estesa, dopo la chiamata a SetContentView che hai fatto nel metodo OnCreate(), recupera il nome dell’utente e imposta opportunamente il testo del componente TextView:

string name = Intent.GetNameExtra();TextView welcomeMessage = FindViewById<TextView>(Resource.Id.welcome_message);welcomeMessage.Text = Resources.GetString(Resource.String.welcome_message_format, name);

In questo estratto, al recupero dell’istanza TextView il suo valore è impostato al tuo messaggio di benvenuto, che viene creato usando l’equivalente Android Resources di string.Format().

Con questo la vostra attività di dashboard è completa, e ora avete bisogno di chiamarla. Nel segnaposto per il caso di successo che ho lasciato aperto dal metodo OnSignInAttempted, puoi ottenere questo aggiungendo il seguente codice:

JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();JwtSecurityToken jsonToken = tokenHandler.ReadJwtToken(authorizationResult.IdentityToken);IEnumerable<Claim> claims = jsonToken?.Payload?.Claims;string name = claims?.FirstOrDefault(x => x.Type == "name")?.Value;Intent dashboardIntent = new Intent(this, typeof(DashboardActivity));dashboardIntent.PutNameExtra(name);StartActivity(dashboardIntent);Finish();

Il primo blocco legge il token e recupera il nome dell’utente (se esiste). Nel secondo viene creato un nuovo Intent per l’attività del dashboard, il nome dell’utente viene memorizzato in questo Intent usando il vostro metodo di estensione definito sopra, e poi l’attività viene avviata (cioè navigata). Per evitare che l’utente torni a questa pagina in seguito, il codice termina chiamando il metodo Finish().

Esegui la tua applicazione Android

Ora è il momento di lanciare la tua applicazione utilizzando il dispositivo scelto!

Se stai facendo il debug utilizzando l’emulatore, questo dovrebbe essere semplice come premere F5 che prima aprirà e caricherà l’emulatore, e poi il codice verrà distribuito in esso. Come nota a margine, non c’è bisogno di chiudere l’emulatore tra i tentativi di esecuzione/debug, in quanto ha solo bisogno di distribuire nuovamente l’applicazione.

Se si sta eseguendo il debug utilizzando un dispositivo che non è stato utilizzato per questo scopo prima, è necessario impostare il dispositivo prima. Fatelo abilitando le opzioni sviluppatore e, all’interno del nuovo menu, accendendo ‘Android debugging’ sotto l’intestazione ‘Debugging’. Dopo questo, basta collegare il dispositivo, accettare la finestra di dialogo sul dispositivo che conferma che questa è una connessione di debug sicura, e dovresti essere in grado di distribuire ed eseguire la tua app con F5. Nota che i dispositivi fisici hanno la precedenza rispetto all’emulatore e passeranno ad esso come opzione di debug predefinita quando sono collegati.

Una volta che la tua app è stata distribuita e caricata, sarai accolto dal modello di pagina singola predefinito. Apri il menu in alto a destra per accedere, e una volta inseriti i tuoi dati dovresti tornare a questa pagina con la barra di avanzamento che gira prima di essere automaticamente inviato alla pagina del dashboard con il tuo messaggio di benvenuto:

Impara di più su Xamarin, OpenID Connect e l’autenticazione sicura

Se hai seguito tutti questi passi ora hai un’applicazione Android di base costruita usando Xamarin.Android, con un’autenticazione utente completamente funzionante basata su OpenID e il servizio Okta. Da qui puoi facilmente espandere l’attività della dashboard per implementare le tue funzionalità.

Per vedere il codice completo di questo post vai alla nostra pagina GitHub.

Se questo tutorial ti ha stuzzicato l’appetito per lo sviluppo di Xamarin e vuoi saperne di più, ti consiglio vivamente di dare un’occhiata a questi altri articoli:

  • Aggiungi gestione dell’identità alla tua app Android
  • Aggiungi autenticazione alla tua app Xamarin.Forms con OpenID Connect
  • Costruisci un’app per iOS e Android con Xamarin

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.