Etes-vous un développeur .NET qui a toujours voulu faire une application mobile ? Ou peut-être avez-vous essayé de construire des applications mobiles natives avec Android ou iOS mais n’avez pas aimé les langages ? Eh bien, vous avez de la chance ! Le monde .NET a été béni avec Xamarin ; un ensemble d’outils qui vous permet de construire des applications mobiles pour Android, iOS et Windows dans Visual Studio.
Xamarin a deux saveurs principales : La plateforme Xamarin (Xamarin.iOS et Xamarin.Android) et Xamarin.Forms. Avec Xamarin.Forms, une grande majorité de votre logique d’entreprise et de l’interface utilisateur peut être écrite au sein d’un projet partagé qui produit des applications entièrement fonctionnelles sur les 3 systèmes d’exploitation iOS, Android et Windows (UWP). La plateforme Xamarin, d’autre part, est un travail très spécifique à la plateforme et s’apparente davantage à l’écriture d’applications natives mais avec C#.
Dans ce tutoriel, je vais examiner de plus près la plateforme Xamarin et la boîte à outils du système d’exploitation Android connue sous le nom de Xamarin.Android. L’objectif global est de vous permettre de créer une application Android native simple avec une authentification utilisateur de base incluse.
- Configurer Visual Studio et votre environnement
- Vérifier votre environnement Android dans Visual Studio
- Créer une application Xamarin
- Familiarisez-vous avec le projet Xamarin
- Ajouter l’authentification de l’utilisateur à Xamarin avec OpenID Connect
- Configurer votre application Okta
- Créer le fournisseur d’authentification
- Implémenter l’authentification dans votre interface Xamarin
- Lancer votre application Android
- En savoir plus sur Xamarin, OpenID Connect et l’authentification sécurisée
Configurer Visual Studio et votre environnement
Pour suivre le cours, vous aurez besoin d’une copie de Visual Studio, plus la charge de travail ‘Développement mobile avec .NET’. Vous pouvez activer cette fonctionnalité dès la première installation de Visual Studio ou y accéder à partir de l’élément de menu ‘Tools -> Get Tools and Features…’:
Lorsque vous testez et exécutez votre application, vous avez le choix de le faire soit avec un émulateur Android fonctionnant sur votre machine de développement, soit en vous connectant directement à un appareil Android existant. Il n’y a pas de bonne option ici et différents développeurs préfèrent différents facteurs de forme. Si vous choisissez la première option, vous devrez vous assurer, une fois la charge de travail sélectionnée, que dans le volet de droite ( » Détails de l’installation « ), les cases à cocher pour Intel Hardware Accelerated Execution Manager et Google Android Emulator sont sélectionnées (comme vu ci-dessus).
Vérifier votre environnement Android dans Visual Studio
Pour vérifier que tout s’est bien installé et a été configuré correctement, allez dans ‘Outils -> Options -> Xamarin -> Paramètres Android’ et vérifiez que vos chemins d’accès Java Development Kit Location et Android SDK Location sont valides (c. à d. qu’ils ont une coche verte):>.c’est-à-dire ont une coche verte):
Si l’un ou l’autre est manquant, vous devrez installer manuellement le kit de développement Java ou le SDK Android respectivement.
Créer une application Xamarin
Commencez par créer un nouveau projet et sélectionnez le modèle maître ‘Android App (Xamarin)’ (trouvé sous le menu Android). Sur la page suivante, vous voudrez choisir l’option ‘Single View App’ car c’est un excellent modèle de démarrage à partir duquel travailler.
En ce qui concerne la version minimale d’Android, c’est quelque chose qui relève de votre choix personnel en tant que développeur. Il y a un compromis ici entre la possibilité d’accéder aux dernières et meilleures fonctionnalités de l’API dans les nouvelles versions et le soutien de vos clients qui ont des versions plus anciennes. Pour vous aider à prendre cette décision, Google publie assez régulièrement les données relatives à la distribution des versions de la plate-forme qu’il collecte dans le cadre de son tableau de bord de distribution. Ma préférence personnelle va à la version 5.0 ou 6.0, selon qu’il s’agit d’une application destinée au grand public ou d’une application commandée pour les téléphones d’entreprise uniquement (c’est-à-dire qu’ils auront probablement les dernières mises à jour) ; dans cet exemple, j’ai opté pour la dernière version. Notez que cette version diffère de la version Android cible et que cela devrait toujours être défini à la dernière version publiée du SDK, car tout ce qui est moins ne sera pas accepté dans le magasin Google Play.
Une fois que vous avez créé cela, tout ce qui reste à faire est d’importer les paquets NuGet nécessaires. Pour ce tutoriel, vous aurez besoin :
- Xamarin.OpenId.AppAuth.Android – Pour authentifier l’utilisateur, vous utiliserez la norme OpenID Connect (une amélioration de OAuth 2.0). La façon la plus simple de mettre en œuvre un code client qui respecte cette spécification est d’utiliser le SDK client AppAuth pour Android, et utilement Xamarin a porté un paquet de cette fonctionnalité disponible pour que vous puissiez l’utiliser.
- System.IdentityModel.Tokens.Jwt – La méthode d’authentification ici utilise des jetons Web JSON. Pour extraire les données nécessaires de ces jetons, vous aurez besoin de ce paquet.
En outre, vous aurez besoin de ces deux paquets également car ils sont pris en charge par AppAuth:
- Xamarin.Android.Support.v4
- Xamarin.Android.Support.CustomTabs
Familiarisez-vous avec le projet Xamarin
Si vous n’avez jamais travaillé avec Android, l’un des principes clés à appréhender est le concept d’activité. Les activités sont des composants utilisés pour afficher votre interface utilisateur ; dans leur forme la plus basique, vous pouvez considérer que les activités sont équivalentes aux pages d’une application entre lesquelles l’utilisateur peut naviguer. Dans le code, une activité est représentée par une classe, mais comme une page en ASP.NET, vous pouvez (et vous le ferez presque toujours) lui associer un fichier de mise en page basé sur XML (un fichier .axml) pour obtenir une conception affichable. Tous les nouveaux projets créent un fichier ‘MainActivity.cs’ et ‘activity_main.axml’ comme première activité (c’est-à-dire page) à exécuter à l’ouverture de l’application. Cela peut être changé en n’importe quelle autre Activity par l’utilisation de la propriété MainLauncher = true
dans l’attribut Activity
de la classe.
Les ressources sont conçues pour être gérées dans leur propre répertoire et suivent une convention de nommage assez stricte. Je recommande fortement de stocker autant de vos ressources que possible dans ce répertoire car cela simplifie la réutilisation de ces variables pour votre développement continu. Dans le répertoire ‘values’ du répertoire Resources, c’est là que vous trouverez des fichiers avec des objectifs spécifiques:
- Strings.xml – Héberge toutes les chaînes de caractères face à l’utilisateur. Celui-ci est particulièrement important à utiliser car il vous permet de localiser vos chaînes pour un public mondial.
- Styles.xml – Où vous trouverez les attributs pour styliser vos objets de conception ; pensez-y comme un fichier CSS.
- Colors.xml – Un endroit pour stocker les références aux couleurs que vous utilisez le plus fréquemment dans le cadre de votre style.
- Dimens.xml – Comme son nom l’indique, c’est là que vous définissez les dimensions définies pour la mise en page de votre application.
Les autres répertoires notables ne suivent pas de convention de dénomination pour leurs fichiers, mais ils doivent contenir certains types de fichiers :
- Layout – Emplacement pour stocker vos fichiers .axml. Ces fichiers définissent les mises en page complètes de l’activité, les composants de mise en page que vous générez et remplissez par programme, les mises en page des boîtes de dialogue (alerte), etc.
- Menu – Où vous trouverez les définitions des menus et de leurs éléments. Ce sont des fichiers .xml qui ont
menu
comme élément racine etitem
éléments enfants, dont les élémentsgroup
peuvent être regroupés. Les menus les plus courants que vous rencontrerez sont le menu de débordement (à partir du bouton des trois points verticaux) ou le menu de navigation (à partir du bouton ‘hamburger’ de l’accueil). - Mipmap – Où vous voulez définir les images qui doivent être mises à l’échelle en fonction de la densité de l’écran, c’est-à-dire celles référencées par d’autres apps, et non utilisées en interne. L’icône de l’app est le contenu le plus commun que vous mettrez dans les répertoires mipmap.
- Drawable – Pas standard dans un modèle de projet par défaut, mais peut être créé vous-même. C’est là que vous stockez vos images/contenu dessinable à utiliser dans l’application, par exemple l’écran d’accueil, les conceptions de barres de progression personnalisées, les icônes utilisées dans l’application, etc.
Enfin, si vous avez des fichiers de contenu brut que vous voulez utiliser dans le cadre de votre application (par exemple un fichier texte ou de police), alors le répertoire Assets est l’endroit où les placer. En tant qu’actifs, ces fichiers seront déployés avec votre application pour que vous puissiez y accéder avec le gestionnaire d’actifs.
Pour en savoir plus sur les actifs et les ressources et sur la façon de les utiliser, il existe des fichiers texte » À propos » pratiques dans chaque répertoire d’un projet nouvellement créé.
Ajouter l’authentification de l’utilisateur à Xamarin avec OpenID Connect
La plupart des applications de nos jours nécessitent une forme d’identification de l’utilisateur pour permettre au développeur d’offrir des expériences sur mesure et, à son tour, permettre à l’utilisateur de conserver ses données à travers les appareils/installations. En plus de cela, il y a la question du contrôle d’accès qui pourrait être utile pour autoriser un sous-ensemble d’utilisateurs pour des fonctionnalités supplémentaires. Naturellement, cela peut être une tâche assez laborieuse, surtout si vous créez des applications et que vous avez besoin d’un nouveau système pour chacune d’entre elles. Heureusement, avec Okta, vous pouvez configurer une application en quelques minutes et tout le travail est fait pour vous ! Le service Okta est conforme à OAuth 2.0 et un fournisseur OpenID Connect certifié, et fonctionne donc parfaitement avec le SDK client AppAuth pour tous vos besoins d’authentification et d’autorisation.
Configurer votre application Okta
D’abord, vous devez configurer une nouvelle application dans votre compte Okta pour ce projet. Si vous n’en avez pas encore, il est très facile de créer un nouveau compte développeur gratuit pour toujours.
Une fois que c’est terminé et que vous vous êtes connecté au tableau de bord du développeur, prenez note de l’URL Org car nous en aurons besoin plus tard :
Depuis le tableau de bord, allez dans l’onglet ‘Applications’ et de là ‘Ajouter une application’. Vous créez une application Android native, il est donc préférable de choisir le modèle de plateforme ‘Native’.
De cette page, ajoutez un nom pour votre application et laissez tout le reste par défaut. Une fois enregistré, prenez note de vos URI de redirection de connexion et de votre ID client car vous en aurez besoin ensuite.
Pour que vous puissiez utiliser ces trois valeurs d’Okta avec facilité à l’avenir, je recommanderais de les mettre dans leur propre classe statique dans un nouveau répertoire pour la logique d’authentification :
public static class Configuration{ public const string ClientId = "{yourClientId}"; public const string LoginRedirectUri = "{yourRedirectUri}"; public const string OrgUrl = "https://{yourOktaDomain}";}
Créer le fournisseur d’authentification
Débarrassons-nous du code passe-partout. Vous devez configurer l’application pour l’informer de votre schéma d’URI de redirection. Le schéma est votre URI de redirection de connexion (sous forme de nom de domaine inversé standard) sans le chemin. Par exemple, à partir de la capture d’écran ci-dessus, mon schéma serait ‘com.oktapreview.dev-123456’.
La façon la plus simple de le faire est d’insérer le snippet de filtre d’intention ci-dessous dans votre fichier AndroidManifest.xml
dans le dossier Properties
de votre solution. Ajoutez le XML suivant dans la balise Application
et changez la valeur du schéma par la vôtre:
<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>
Vous devez également définir le modèle pour le résultat de votre autorisation avec une classe simple. Bien que je n’utiliserai pas toutes les valeurs que j’ai écrites ci-dessous dans le code, je montrerai comment les remplir pour que vous puissiez les utiliser ensuite. Comme cela fait partie du modèle de votre application, créez un dossier appelé Models
et ajoutez une classe AuthorizationResult.cs
à l’intérieur. Ensuite, ajoutez le code suivant :
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 n’a pas d’état global avec lequel vous pouvez travailler, et donc si vous voulez passer des valeurs simples entre les activités, la meilleure façon de le faire est avec la fonctionnalité Extras
sur l’objet Intent
. Un Intent
est une classe prédéfinie dans Android et un autre concept de base à comprendre. C’est l’abstraction d’une opération à effectuer (c’est-à-dire vos » intentions « ), et pour naviguer vers une autre activité, vous devez créer une instance de cette classe avec l’activité vers laquelle vous avez » l’intention » d’aller. Les propriétés Extras sur l’objet Intent
sont en fait juste un dictionnaire de clés pour les valeurs de l’objet et sont accessibles par des méthodes Put
et typées Get
.
Bien que ces méthodes gardent l’utilisation relativement claire et facile, j’aime personnellement garder tout accès à eux dans leur propre classe (pour être précis, une classe d’extensions), pour maintenir une meilleure séparation des préoccupations. C’est extrêmement utile car vous n’avez pas besoin d’accéder aux clés à travers les classes et vous pouvez assurer la sécurité des types lorsque vous mettez et récupérez ces valeurs. Dans votre fournisseur d’autorisation, vous voudrez : stocker le AuthState
, être capable de vérifier s’il est là, et le retourner s’il l’est. Créez un nouveau dossier appelé Extensions
à la racine de la solution. Ajoutez ensuite une nouvelle classe appelée IntentExtensions.cs
. Faites la classe public
et static
, puis ajoutez le code suivant à l’intérieur de la 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;}
Maintenant il est temps de définir le fournisseur d’autorisation, AuthorizationProvider.cs
dans le dossier Authentication
que vous avez créé avant pour la classe Configuration.cs
. Tout d’abord, supprimez toutes les déclarations using
à l’intérieur de la classe nouvellement créée, puis déclarez la configuration comme des variables 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" };
Le point de terminaison de la configuration est un standard dans OpenID comme le point de terminaison de la découverte pour trouver tout ce qui est supporté. Notez ici que j’ai écrit ceci en utilisant le nom du fournisseur ‘par défaut’. Si vous avez un fournisseur différent, vous voudrez changer cela ici. Notez également que nous utilisons la version Android.Net
de la classe Uri, et non la version System
– vous devrez ajouter la première à vos utilisations ou qualifier complètement le type pour que cela fonctionne. La variable Scopes, comme tout autre système OpenID, définit ce à quoi nous sommes autorisés à accéder.
Puis vous devez déclarer vos variables membres:
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>();
Une explication rapide sur chacun:
- La demande d’autorisation et l’intention complétée sont des paramètres créés pour être utilisés lors de l’appel d’autorisation. Je les ai écrits comme des variables globales ici pour minimiser la quantité de passage de paramètres dans les différentes méthodes.
- La variable authorizationState comme elle est nommée définit l’état d’autorisation actuel donné.
- La variable authorizationService contient une instance du service d’autorisation.
- La variable contextuelle ici est de l’activité appelante, donc vous pouvez la référencer si nécessaire.
- Enfin, la taskCompletionSource vous permet de faire tous ces appels de manière asynchrone et de revenir une fois terminé.
Maintenant, vous devez définir les valeurs de ces variables en lecture seule dans votre constructeur, et déclarer les méthodes publiques que votre code appellera :
public AuthorizationProvider(Context context){ authorizationService = new AuthorizationService(context); this.context = context;}public async Task<AuthorizationResult> SignInAsync(){ ...}public void NotifyCallback(Intent intent){ ...}
La méthode SignInAsync est comme vous l’avez deviné une méthode asynchrone pour signer un utilisateur. Elle renvoie la classe AuthorizationResult
que vous avez écrite plus tôt. La classe NotifyCallback
d’autre part est destinée à l’activité appelante, une fois qu’elle est revenue de la page de signature externe, pour rappeler le fournisseur d’autorisation et lui faire savoir que c’est fait. La méthode d’inscription a été décomposée en plusieurs sous-programmes et ressemble à ceci :
AuthorizationServiceConfiguration serviceConfiguration = await AuthorizationServiceConfiguration.FetchFromUrlAsync(ConfigurationEndpoint);BuildAuthorizationRequest(serviceConfiguration);BuildCompletedIntent(serviceConfiguration);return await RequestAuthorization();
Vous avez défini la configuration du service, construit la demande d’autorisation et l’intention d’appeler une fois l’autorisation terminée, puis attendu la demande d’autorisation. Pour construire la demande d’autorisation est comme suit:
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();}
Le travail de cette méthode est d’abstraire le AuthorizationRequest.Builder
travail et de créer la demande. Ensuite, vous devez construire le Intent
pour une fois l’opération terminée:
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 »intention’ que vous voulez exécuter ici est de retourner à votre MainActivity
avec un nouvel AuthState attaché. Enfin, dans ce flux, il faut s’occuper de l’exécution de la requête:
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 };}
Comme PerformAuthorizationRequest
est synchrone et renvoie void, le code attend le membre taskCompletionSource
, sachant qu’il ne sera jamais défini qu’une fois la réponse récupérée. À ce même moment, vous savez que l’état d’autorisation sera rempli (si tout a réussi), et donc vous pouvez retourner leurs valeurs dans le cadre de l’AuthorizationResult.
La deuxième méthode publique NotifyCallback
, comme je l’ai mentionné auparavant, est ce que vous voulez que la classe MainActivity
rappelle, une fois que votre completedIntent
ci-dessus est exécutée. Dans cette méthode, vous voulez vérifier la réponse, mettre à jour l’état de manière appropriée, et en cas de succès, effectuer une demande d’échange de jetons :
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);
Ici vous pouvez voir que dans les cas d’échec, j’ai mis le résultat de taskCompletionSource à false, et cela débloquera la méthode RequestAuthorization
ci-dessus. De plus, la méthode PerformTokenRequest
prend en charge un délégué, ReceivedTokenResponse
, qui sera exécuté une fois qu’elle sera terminée. Cette méthode est la suivante:
private void ReceivedTokenResponse(TokenResponse tokenResponse, AuthorizationException authorizationException){ authorizationState.Update(tokenResponse, authorizationException); taskCompletionSource.SetResult(true);}
À ce stade, vous devriez avoir toutes les données d’autorisation dont vous avez besoin, et vous pouvez donc mettre à jour l’état de manière appropriée (où vous trouverez les valeurs à retourner de la méthode d’inscription) et définir le résultat pour débloquer la tâche taskCompletionSource
.
Implémenter l’authentification dans votre interface Xamarin
En guise de nettoyage si vous le souhaitez, n’hésitez pas à supprimer toutes les références à la » barre d’action flottante » (également écrite sous le nom de » FAB « ) au sein des fichiers de classe/axml de l’activité principale, car elles constituent un bloat inutile à ce stade.
Pour permettre à l’utilisateur de se connecter, vous devez maintenant implémenter cette fonctionnalité dans l’interface utilisateur. Compte tenu de la conception par défaut, la façon la plus intuitive de le faire serait d’ajouter un élément au menu de débordement dans le coin supérieur droit. Vous pouvez le faire en éditant le fichier menu_main.xml
dans le dossier ‘Resources -> menu’, et en ajoutant cet élément comme enfant de la balise menu
:
<item android:id="@+id/action_signin" android:orderInCategory="100" android:title="@string/action_signin" app:showAsAction="never" />
Avec ce code, vous avez créé une nouvelle option avec un titre à définir dans le fichier de ressources string. Comme mentionné précédemment, sous Android, il est préférable de placer tout le texte destiné à l’utilisateur dans le fichier de ressources string. Pour déclarer ces données, éditez le fichier strings.xml
dans le dossier ‘Resources -> values’ et ajoutez ces lignes:
<string name="action_signin">Sign In</string><string name="welcome_message_format">Hi, %1$s!</string>
Non seulement j’ai déclaré une chaîne pour le bouton ‘Sign In’ ici, mais j’ai aussi ajouté au-dessus une chaîne pour un message de bienvenue à l’utilisateur une fois qu’il a signé. L’équivalent du code C# de this string would be
« Salut, {0} ! »`, où le placeholder est de type string.
Notez qu’avec toutes les mises à jour de ces fichiers basés sur les ressources, la classe Resource.designer.cs sera automatiquement régénérée avec de nouveaux ID pour chaque objet que vous avez créé, qui peuvent être référencés dans votre code. Si cela ne fonctionne pas pour un fichier particulier, sélectionnez-le dans l’explorateur de solutions et regardez la fenêtre des propriétés. Assurez-vous que la propriété CustomTool
est définie sur la valeur MSBuild:UpdateGeneratedFiles
, car elle est probablement manquante et empêche le fichier du concepteur de la reconnaître comme une ressource.
Ajouter ensuite un ProgressBar
au fichier de mise en page activity_main.axml
existant:
<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" />
Ce ProgressBar
(ou spinner, selon le cas), a un ID que vous pouvez référencer avec du code, et est configuré pour se situer autour du centre de l’écran. La visibilité est définie sur gone pour l’instant, mais une fois que votre code d’autorisation est en cours d’exécution, vous pouvez le rendre visible et informer l’utilisateur que l’application est occupée.
Maintenant que vous avez un bouton pour ouvrir l’authentification et un spinner de progression pour informer l’utilisateur que l’application est occupée, il est temps de les utiliser. Dans votre classe MainActivity
, ajoutez la propriété suivante à l’attribut Activity
(au-dessus de l’en-tête de la classe):
LaunchMode = LaunchMode.SingleTask
Cette propriété garantit qu’il n’y a qu’une seule instance de la classe MainActivity
, et que vous ne continuez pas à en ouvrir de nouvelles. Une fois que vous avez fait cela, ajoutez une variable membre statique pour la AuthorizationProvder
que vous avez écrite ci-dessus et créez une instance de celle-ci dans la surcharge existante de la méthode OnCreate
. Notez que cela doit être fait après le code existant dans la méthode :
private static AuthorizationProvider authorizationProvider;protected override void OnCreate(Bundle savedInstanceState){ ... authorizationProvider = new AuthorizationProvider(this);}
Puis, surchargez la méthode OnNewIntent
. Le but de ceci est quand une nouvelle intention de cette classe est créée (c’est-à-dire quand la fenêtre d’inscription externe revient), vous appelez la méthode NotifyCallback
à partir de la AuthorizationProvider
. Également inclus dans ceci est une vérification rapide pour s’assurer que c’est le flux attendu:
protected override void OnNewIntent(Intent intent){ base.OnNewIntent(intent); if (intent != null && intent.Data.Path.Equals("/callback", StringComparison.OrdinalIgnoreCase)) { authorizationProvider.NotifyCallback(intent); }}
Maintenant ajoutez le code derrière l’élément de menu que vous avez ajouté. Dans la surcharge existante de la méthode OnOptionsItemSelected
, ajoutez une déclaration if
avec un appel à une nouvelle méthode qui gérera le processus d’inscription comme suit:
if (id == Resource.Id.action_signin){ OnSignInAttempted(); return true;}
Cette nouvelle méthode commencera par rendre visible le ProgressBar
que vous avez ajouté il y a quelques instants ; pour récupérer n’importe quel composant du fichier de disposition, utilisez la méthode générique FindViewById
et entrez l’ID du composant comme argument. Après cela, faites un appel à la méthode SignInAsync
et attendez son résultat. Une fois l’appel retourné, le résultat est alors vérifié comme étant autorisé. Si cette autorisation a échoué pour une raison quelconque, une boîte de dialogue d’erreur apparaît, et la roue de progression disparaît à nouveau. Je vais laisser le détail du cas de réussite pour le moment car vous avez toujours besoin de quelque part où aller dans cette instance:
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; }}
Lorsque l’utilisateur est authentifié, vous devez le rediriger vers la page suivante de votre expérience. Si vous vous souvenez précédemment, chaque page est représentée par une activité, et vous devez donc en créer une nouvelle maintenant.
Pour commencer, dans le dossier ‘Resources -> layout’, vous devrez créer le nouveau fichier de mise en page d’activité « activity_dashboard.axml ». La façon la plus simple de le faire est d’aller à l’option Nouvel élément… dans le menu contextuel et de sélectionner le modèle ‘Android Layout’. Dans votre nouveau fichier de mise en page, ajoutez un simple composant TextView pour afficher du texte comme ceci:
<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>
Dans cet extrait, vous avez un composant TextView
avec un ID référençable qui est centré au milieu de la page, dont le message de bienvenue sera affiché. Créez ensuite une classe d’activité correspondante ‘DashboardActivity’ en utilisant l’option ‘New Item…’ du menu contextuel du projet dans l’explorateur de solutions et en sélectionnant le modèle ‘Activity’. Pour lier cette classe à son fichier de mise en page, vous devez appeler la fonction SetContentView dans la méthode générée OnCreate()
(sous l’invocation de la méthode de base héritée):
SetContentView(Resource.Layout.activity_dashboard);
Pour personnaliser votre message de bienvenue, vous voudrez passer le nom de l’utilisateur à votre nouvelle activité. Si vous vous souvenez plus tôt, la meilleure façon de le faire était avec Extras sur l’intention, et vous avez créé une classe d’extensions pour gérer cela. Comme précédemment, ajoutez de nouvelles méthodes pour ‘Put’ et ‘Get’ d’un extra ‘name’ dans le fichier IntentExtensions.cs
que vous avez créé ci-dessus :
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);}
Maintenant en utilisant cette fonctionnalité étendue, après l’appel à SetContentView
que vous avez fait dans la méthode OnCreate()
, récupérez le nom de l’utilisateur et définissez le texte du composant TextView
de manière appropriée :
string name = Intent.GetNameExtra();TextView welcomeMessage = FindViewById<TextView>(Resource.Id.welcome_message);welcomeMessage.Text = Resources.GetString(Resource.String.welcome_message_format, name);
Dans cet extrait, lors de la récupération de l’instance TextView
, sa valeur est fixée à votre message de bienvenue, dont la création se fait à l’aide de l’équivalent Android Resources de string.Format()
.
Avec cela, votre activité de tableau de bord est terminée, et vous devez maintenant l’appeler. Dans le placeholder du cas de succès que j’ai laissé ouvert à partir de la méthode OnSignInAttempted
, vous pouvez y parvenir en ajoutant le code suivant :
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();
Le premier bloc lit le token et récupère le nom de l’utilisateur (s’il existe). Dans le second, une nouvelle Intent
est créée pour l’activité du tableau de bord, le nom de l’utilisateur est stocké dans cette Intent
en utilisant votre méthode d’extension définie ci-dessus, puis l’activité est lancée (c’est-à-dire qu’on y navigue). Pour empêcher l’utilisateur de naviguer à nouveau vers cette page par la suite, le code se termine en appelant la méthode Finish()
.
Lancer votre application Android
Maintenant, il est temps de lancer votre application en utilisant votre appareil choisi !
Si vous déboguez en utilisant l’émulateur, cela devrait être aussi simple que d’appuyer sur F5 de ce qui va d’abord ouvrir et charger l’émulateur, puis le code se déploiera vers lui. Comme une note latérale, vous n’avez pas besoin de fermer l’émulateur entre les tentatives d’exécution / débogage, car il a seulement besoin de redéployer l’application.
Si vous déboguez en utilisant un appareil qui n’a pas été utilisé à cette fin avant, vous aurez besoin de configurer l’appareil en premier. Faites-le en activant les options du développeur et, dans le nouveau menu, en activant ‘Android debugging’ sous l’en-tête ‘Debugging’. Ensuite, il suffit de brancher l’appareil, d’accepter la boîte de dialogue sur votre appareil confirmant qu’il s’agit d’une connexion de débogage sécurisée, et vous devriez pouvoir déployer et exécuter votre application avec F5. Notez que les appareils physiques ont une priorité plus élevée que l’émulateur et passeront à celui-ci comme option de débogage par défaut lorsqu’ils sont branchés.
Une fois que votre app a été déployée et chargée, vous serez accueilli par le modèle de page unique par défaut. Ouvrez le menu dans le coin supérieur droit pour vous connecter, et une fois que vous avez entré vos détails, vous devriez revenir à cette page avec la barre de progression tournante avant d’être automatiquement envoyé à la page du tableau de bord avec votre message de bienvenue :
En savoir plus sur Xamarin, OpenID Connect et l’authentification sécurisée
Si vous avez suivi toutes ces étapes, vous avez maintenant une application Android de base construite avec Xamarin.Android, avec une authentification utilisateur entièrement fonctionnelle basée sur OpenID et le service Okta. À partir de là, vous pouvez facilement développer l’activité du tableau de bord pour mettre en œuvre votre fonctionnalité.
Pour voir le code de ce post dans son intégralité, rendez-vous sur notre page GitHub.
Si ce tutoriel a aiguisé votre appétit pour le développement Xamarin et que vous souhaitez en apprendre davantage, alors je vous suggère fortement de jeter un coup d’œil à ces autres excellents articles :
- Ajouter la gestion d’identité à votre application Android
- Ajouter l’authentification à votre application Xamarin.Forms avec OpenID Connect
- Construire une application pour iOS et Android avec Xamarin
.