Você é um desenvolvedor .NET que sempre quis fazer um aplicativo móvel? Ou talvez você tenha tentado construir aplicativos móveis nativos com Android ou iOS, mas não gostou das linguagens? Bem, então você está com sorte! O mundo .NET tem sido abençoado com Xamarin; um conjunto de ferramentas que permite a você construir aplicativos móveis para Android, iOS e Windows dentro do Visual Studio.

Xamarin tem dois sabores principais: Plataforma Xamarin (Xamarin.iOS e Xamarin.Android) e Xamarin.Forms. Com Xamarin.Forms uma grande maioria da sua lógica empresarial e interface de usuário pode ser escrita dentro de um projeto compartilhado que produz aplicativos totalmente funcionais em todos os 3 sistemas operacionais iOS, Android e Windows (UWP). A plataforma Xamarin, por outro lado, é muito trabalho específico da plataforma e é mais parecida com a escrita de aplicativos nativos, mas com C#.

Neste tutorial, eu estarei olhando mais de perto a plataforma Xamarin e o conjunto de ferramentas do sistema operacional Android conhecido como Xamarin.Android. O objetivo geral é permitir que você crie um aplicativo nativo simples para Android com autenticação básica de usuário incluída.

Configure o Visual Studio e seu ambiente

Para acompanhar, você precisará de uma cópia do Visual Studio, mais a carga de trabalho ‘Desenvolvimento móvel com .NET’. Você pode ativar esse recurso a partir da primeira instalação do Visual Studio ou acessá-lo a partir do menu ‘Tools -> Get Tools and Features…’ item:

Ao testar e executar seu aplicativo, você tem a opção de fazê-lo com um emulador Android rodando na sua máquina de desenvolvimento, ou conectando-se diretamente a um dispositivo Android existente. Não há opção certa aqui e diferentes desenvolvedores preferem diferentes fatores de forma. Se você escolher a opção anterior, você precisará garantir, uma vez selecionada a carga de trabalho, que no painel direito (‘Detalhes de instalação’) as caixas de seleção para o Intel Hardware Accelerated Execution Manager e Google Emulator Android estão selecionadas (como visto acima).

Verify Your Android Environment in Visual Studio

Para verificar tudo instalado corretamente e configurado corretamente, vá para ‘Tools -> Options -> Xamarin -> Android Settings’ e verifique se os caminhos de localização do Java Development Kit e do Android SDK Location são válidos (i.e. tenha uma marca verde):

Se algum deles estiver faltando você terá que instalar manualmente o Java Development Kit ou o Android SDK respectivamente.

Criar um aplicativo Xamarin

Comece criando um novo projeto e selecione o modelo mestre ‘Android App (Xamarin)’ (encontrado sob o menu do Android). Na página seguinte você vai querer escolher a opção ‘Single View App’, pois é um ótimo template inicial para trabalhar de.

Com respeito à versão mínima do Android, isto é algo que se deve à sua escolha pessoal como desenvolvedor. Há um trade-off aqui entre poder acessar as últimas e melhores funcionalidades da API em versões mais recentes e suportar seus clientes que têm versões mais antigas. Para ajudar você a tomar essa decisão, o Google publica os dados de distribuição de versões de plataforma que eles coletam como parte de seu painel de distribuição em uma cadência bastante regular. Minha preferência pessoal está entre 5.0 ou 6.0, dependendo se este é um aplicativo para consumo público ou um aplicativo comissionado apenas para telefones corporativos (ou seja, eles provavelmente terão as atualizações mais recentes); neste exemplo, eu fui com este último. Note que esta versão difere da versão Target Android e que deve ser sempre definida para a versão mais recente lançada do SDK, pois qualquer coisa a menos não será aceita na loja Google Play.

A partir do momento em que você criou esta versão, tudo o que resta é importar os pacotes NuGet necessários. Para este tutorial você precisará:

  • Xamarin.OpenId.AppAuth.Android – Para autenticar o usuário você estará usando o padrão OpenID Connect (um aprimoramento do OAuth 2.0). A maneira mais fácil de implementar o código do cliente que obedece a esta especificação é usando o cliente SDK AppAuth para Android, e de forma útil o Xamarin portou um pacote desta funcionalidade disponível para você usar.
  • System.IdentityModel.Tokens.Jwt – O método de autenticação aqui usa JSON Web Tokens. Para extrair os dados necessários destes tokens você vai precisar deste pacote.

Adicionalmente, você vai precisar destes dois pacotes assim como eles são confiados pelo AppAuth:

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

Familiarize-se com o Projeto Xamarin

Se você nunca trabalhou com o Android antes, um dos princípios fundamentais para se familiarizar é o conceito de uma Atividade. Atividades são componentes usados para exibir sua interface de usuário; em sua forma mais básica, você pode pensar em Atividades como sendo igual a páginas em um aplicativo que o usuário pode navegar entre elas. Uma Activity em código é representada por uma classe, no entanto como uma página em ASP.NET você pode (e quase sempre irá) associar um arquivo de layout baseado em XML (um arquivo .axml) com ele para um design exibível. Todos os novos projetos criam um arquivo ‘MainActivity.cs’ e ‘activity_main.axml’ para começar como a primeira Activity (ou seja, página) a ser executada ao abrir o aplicativo. Isto pode ser alterado para qualquer outra Activity através da utilização da propriedade MainLauncher = true dentro do atributo Activity da classe.

Recursos são desenhados para serem manuseados dentro do seu próprio directório e seguem uma convenção de nomenclatura um pouco estrita. Eu recomendo fortemente o armazenamento de tantos recursos quanto for possível neste diretório, pois isso simplifica a reutilização dessas variáveis para o seu desenvolvimento contínuo. No diretório ‘values’ do diretório Resources é onde você encontrará arquivos com propósitos específicos:

  • Strings.xml – Hospeda todos os usuários que enfrentam strings. Este é especialmente importante de usar pois permite que você localize suas cordas para uma audiência global.
  • Styles.xml – Onde você encontrará os atributos para estilizar seus objetos de design; pense nele como um arquivo CSS.
  • Colors.xml – Um lugar para armazenar referências às cores que você usa com mais freqüência como parte do seu estilo.
  • Dimens.xml – Como o nome pode implicar, onde você define dimensões definidas para o layout da sua aplicação.

Os outros diretórios notáveis não seguem nenhuma convenção de nomes para seus arquivos, mas devem conter certos tipos de arquivos:

  • Layout – Local para armazenar seus arquivos .axml. Estes arquivos definem layouts completos de atividades, componentes de layout que você programmaticamente gera e preenche, layouts de caixas de diálogo (alerta), etc.
  • Menu – Onde você encontrará definições de menus e seus itens. Estes são arquivos .xml que têm menu como elemento raiz e item elementos filhos, dos quais podem ser agrupados junto com group elementos. Os menus mais comuns que você encontrará são o menu overflow (a partir dos três botões de pontos verticais) ou o menu de navegação (a partir do botão ‘hambúrguer’ inicial).
  • Mipmap – Onde você quer definir imagens que precisam ser escaladas dependendo da densidade da tela, ou seja, aquelas referenciadas por outros aplicativos, e não utilizadas internamente. O ícone do aplicativo é o conteúdo mais comum que você colocaria nos diretórios mipmap.
  • Drawable – Não é padrão em um modelo de projeto padrão, mas pode ser criado você mesmo. Aqui é onde você armazena suas imagens/conteúdo desenhado para ser usado dentro da aplicação, por exemplo, tela splash, designs de barras de progresso personalizadas, ícones usados dentro da aplicação, etc.

Por último, se você tem algum arquivo de conteúdo bruto que você quer usar como parte da sua aplicação (por exemplo, um arquivo de texto ou fonte), então o diretório Assets é onde colocá-los. Como Ativos, esses arquivos serão implantados com seu aplicativo para você acessar com o Asset Manager.

Para saber mais sobre Ativos e Recursos e como usá-los, há arquivos de texto ‘Sobre’ práticos em cada diretório de um projeto recém-criado.

Adicionar autenticação de usuário ao Xamarin com OpenID Connect

A maioria dos aplicativos hoje em dia requer alguma forma de identificação de usuário para permitir que o desenvolvedor ofereça experiências sob medida e, por sua vez, permitir que o usuário mantenha seus dados entre dispositivos/instalações. Além disso, há a questão do controle de acesso que pode ser útil para autorizar um subconjunto de usuários para funcionalidades extras. Naturalmente, esta pode ser uma tarefa bastante trabalhosa, especialmente se você estiver no negócio de criar aplicativos e precisará de um novo sistema para cada um deles. Felizmente, com o Okta você pode configurar uma aplicação em poucos minutos e então todo o trabalho duro é feito para você! O serviço Okta é compatível com OAuth 2.0 e um OpenID Connect Provider certificado, e assim funciona perfeitamente com o SDK cliente AppAuth para todas as suas necessidades de autenticação e autorização.

Configure a sua aplicação Okta

Primeiro, você deve configurar uma nova aplicação na sua conta Okta para este projecto. Se você ainda não tem uma, é muito fácil criar uma nova conta de desenvolvedor para sempre.

Após isso estar completo e você ter entrado no painel do desenvolvedor, tome nota da URL Org, pois precisaremos disso mais tarde:

From the dashboard go to the ‘Applications’ tab and from there ‘Add Application’. Você está criando um aplicativo Android nativo, então é melhor escolher o modelo de plataforma ‘Nativo’.

A partir desta página adicione um nome para o seu aplicativo e deixe tudo o resto como padrão. Uma vez salvo, tome nota do seu Login redirecionar URIs e Client ID como você vai precisar destes em seguida.

Pode usar estes três valores do Okta com facilidade no futuro, eu recomendaria colocá-los em sua própria classe estática dentro de um novo diretório para a lógica de autenticação:

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

Criar o Provedor de Autenticação

Vamos tirar o código da placa de caldeira do caminho. Você precisa configurar o aplicativo para informá-lo do seu esquema de redirecionamento do URI. O esquema é o seu URI de redirecionamento de login (em forma de nome de domínio reverso padrão) sem o caminho. Por exemplo, da imagem de tela acima, meu esquema seria ‘com.oktapreview.dev-123456’.

A maneira mais fácil de fazer isso é inserir o snippet do filtro abaixo no seu arquivo AndroidManifest.xml na pasta Properties da sua solução. Adicione o seguinte XML dentro da tag Application e mude o valor do esquema para o seu:

<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>

Você também precisa definir o modelo para o resultado da sua autorização com uma classe simples. Enquanto eu não vou usar todos os valores que escrevi abaixo dentro do código, vou mostrar como preenchê-los para que você os utilize depois. Como isto faz parte do modelo da sua aplicação, crie uma pasta chamada Models e adicione uma classe AuthorizationResult.cs dentro dela. Depois, adicione o seguinte código:

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ão tem um estado global para você trabalhar, e então se você quiser passar valores simples entre atividades, a melhor maneira de fazer isso é com a funcionalidade Extras no objeto Intent. Um Intent é uma classe pré-definida no Android e outro conceito central para entender. É a abstração de uma operação a ser executada (ou seja, suas ‘intenções’), e para navegar para outra atividade você precisa criar uma instância desta classe com a qual a atividade para a qual você ‘pretende’ ir. As propriedades Extras no objeto Intent são na verdade apenas um dicionário de chaves para valores de objetos e são acessadas por Put e digitadas por Get métodos.

Embora esses métodos mantenham o uso relativamente claro e fácil eu pessoalmente gosto de manter todo o acesso a eles dentro de sua própria classe (para ser mais preciso, uma classe de extensões), para manter uma melhor separação de preocupações. Isto é extremamente útil, pois não é necessário acessar as chaves através das classes e pode garantir a segurança do tipo ao colocar e obter estes valores. Em seu provedor de autorização você estará querendo: armazenar o AuthState, ser capaz de verificar se ele está lá, e devolvê-lo se estiver. Crie uma nova pasta chamada Extensions na raiz da solução. Depois adicione uma nova classe chamada IntentExtensions.cs. Faça a classe public e static, depois adicione o seguinte código dentro da 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;}

Agora é hora de definir o provedor de autorização, AuthorizationProvider.cs na pasta Authentication que você criou antes para a classe Configuration.cs. Primeiro, remova todas as instruções using dentro da classe recém-criada, depois declare a configuração como static readonly variáveis:

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" };

O endpoint de configuração é um padrão no OpenID como o endpoint de descoberta para encontrar tudo o que é suportado. Note aqui que eu escrevi isto usando o nome ‘default’ do provedor. Se você tem um provedor diferente, você vai querer mudar isso aqui. Note também que isto está usando o sabor Android.Net da classe Uri, e não a versão System – você precisará adicionar o primeiro aos seus usos ou qualificar totalmente o tipo para que isto funcione. A variável Scopes, como qualquer outro sistema OpenID, define o que estamos autorizados a acessar.

Próximo você deve declarar suas variáveis de 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>();

Uma explicação rápida sobre cada:

  • A solicitação de autorização e a intenção completada são parâmetros criados para uso na chamada de autorização. Eu os escrevi aqui como variáveis globais para minimizar a quantidade de parâmetros passados em métodos diferentes.
  • A variável authorizationState como é nomeada define o estado atual da autorização.
  • A variável authorizationService contém uma instância do serviço de autorização.
  • A variável de contexto aqui é da atividade de chamada, para que você possa referenciá-la quando necessário.
  • Finalmente, a taskCompletionSource permite que você faça todas essas chamadas de forma assíncrona e depois retorne uma vez completada.

Agora você deve definir os valores dessas variáveis somente de leitura no seu construtor, e declarar os métodos públicos que seu código irá chamar:

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

O método SignInAsync é como você poderia ter adivinhado um método assíncrono para assinar um usuário. Isto retorna a classe AuthorizationResult que você escreveu anteriormente. NotifyCallback por outro lado, é para a atividade de chamada, uma vez que ela tenha retornado do sinal externo na página, para chamar de volta ao provedor de autorização e deixá-lo saber que está feito. O sinal no método eu quebrei em múltiplas sub-rotinas, e parece assim:

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

Nisto você definiu a configuração do serviço, construiu a solicitação de autorização e a intenção de chamar uma vez que a autorização tenha sido completada, e então aguardar a solicitação de autorização. Para construir a solicitação de autorização é o seguinte:

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();}

O trabalho deste método é abstrair os AuthorizationRequest.Builder trabalhar e criar a solicitação. A seguir você precisa construir o Intent para uma vez concluída a operação:

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

A ‘intenção’ que você quer realizar aqui é retornar ao seu MainActivity com um novo AuthState anexado. Por último, neste fluxo é para lidar com a execução do pedido:

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 };}

>

As PerformAuthorizationRequest é síncrona e retorna nula, o código aguarda o membro taskCompletionSource, sabendo que ele só será definido uma vez que uma resposta tenha sido recuperada. Neste mesmo ponto você sabe que o estado de autorização será preenchido (se tudo tiver sucesso), e assim você pode retornar seus valores como parte do resultado de autorização.

O segundo método público NotifyCallback, como mencionei antes, é o que você quer que a classe MainActivity chame de volta, uma vez que o seu acima completedIntent for executado. Neste método você quer verificar a resposta, atualizar o estado apropriadamente, e se bem sucedido, executar um pedido de troca de fichas:

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);

Aqui você pode ver nos casos de falha eu defino o resultado da tarefaCompletionSource como falso, e isso irá desbloquear o método RequestAuthorization acima. Além disso, o método PerformTokenRequest recebe um delegado, ReceivedTokenResponse, para ser executado uma vez que tenha sido completado. Este método é o seguinte:

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

Neste ponto você deve ter todos os dados de autorização necessários, e assim pode atualizar o estado apropriadamente (onde você encontrará os valores para retornar do sinal no método) e definir o resultado para desbloquear a tarefa taskCompletionSource.

Implement Authentication into Your Xamarin Interface

Como uma limpeza se assim o desejar, sinta-se à vontade para remover todas as referências à ‘Floating Action Bar’ (também escrita como ‘FAB’) dentro da classe de atividade principal/arquivosaxml uma vez que são bloqueios desnecessários neste estágio.

Para permitir que o usuário entre na UI você agora precisa implementar esta funcionalidade na UI. Dado o design padrão, a forma mais intuitiva de fazer isso seria adicionar um item ao menu de estouro no canto superior direito. Você pode fazer isso editando o arquivo menu_main.xml na pasta ‘Resources -> menu’, e adicionando este item como um filho do arquivo menu tag:

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

Com este código você criou uma nova opção com um título a ser definido no arquivo string resources. Como mencionado anteriormente no Android é a melhor prática para colocar todo o texto que o usuário enfrenta no arquivo de recursos de strings. Para declarar estes dados, edite o arquivo strings.xml na pasta ‘Resources -> values’ e adicione estas linhas:

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

Não só declarei uma string para o botão ‘Sign In’ aqui, mas também adicionei acima uma string para uma mensagem de boas vindas ao usuário uma vez que ele tenha entrado. O equivalente ao código C# de this string would be “Olá, {0}!”`, onde o espaço reservado é do tipo string.

Nota com todas as atualizações desses arquivos baseados em Recursos, a classe Resource.designer.cs será automaticamente regenerada com novos IDs para cada objeto que você criou, que podem ser referenciados dentro do seu código. Se isso não estiver funcionando para um determinado arquivo, então selecione-o no Solution Explorer e olhe na janela Propriedades. Certifique-se que a propriedade CustomTool esteja definida com o valor MSBuild:UpdateGeneratedFiles, pois provavelmente ela está faltando e impedindo que o arquivo de criação o reconheça como um recurso.

Próximo adicionar um ProgressBar ao existente activity_main.axml arquivo de layout:

<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" />

Este ProgressBar (ou spinner, como é o caso), tem um ID que você pode referenciar com o código, e está configurado para sentar-se ao redor do centro da tela. A visibilidade está configurada para desaparecer por enquanto, mas uma vez que o seu código de autorização esteja em execução você pode configurá-lo para visível e informar ao usuário que a aplicação está ocupada.

Agora você tem um botão para abrir autenticação e um spinner de progresso para informar ao usuário que a aplicação está ocupada, é hora de usá-los. Dentro da sua classe MainActivity adicione a seguinte propriedade ao atributo Activity (acima do cabeçalho da classe):

LaunchMode = LaunchMode.SingleTask

Esta propriedade assegura que existe apenas uma instância da classe MainActivity, e você não continua abrindo novas. Uma vez feito isso, adicione uma variável estática de membro para a AuthorizationProvder que você escreveu acima e crie uma instância dela dentro da sobreposição existente do método OnCreate. Note que isto deve ser feito após o código existente dentro do método:

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

Next, substitua o método OnNewIntent. O propósito disto é quando uma nova intenção desta classe é criada (ou seja, quando o sinal externo na janela retorna), você chama o método NotifyCallback a partir do método AuthorizationProvider. Também incluído nisto está uma verificação rápida para ter certeza que é o fluxo esperado:

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

Agora adicione o código por trás do item de menu que você adicionou. Na substituição existente do método OnOptionsItemSelected, adicione uma declaração if com uma chamada a um novo método que irá lidar com o sinal em processo da seguinte forma:

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

Este novo método irá começar tornando visível o ProgressBar que você adicionou momentos atrás; para recuperar qualquer componente do arquivo de layout, use o método genérico FindViewById e digite o ID do componente como seu argumento. Depois disso, faça uma chamada para o método SignInAsync e aguarde seu resultado. Uma vez que a chamada tenha retornado o resultado é então verificado como autorizado. Se esta autorização falhar por qualquer motivo, aparece um diálogo de erro e o spinner de progresso desaparece novamente. Vou deixar detalhando o caso de sucesso por enquanto, pois você ainda precisa de algum lugar para ir naquela instância:

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 o usuário estiver autenticado você deve redirecioná-los para a próxima página da sua experiência. Se você se lembrar antes, cada página é representada por uma Activity, e então você precisa criar uma nova agora.

Para começar, dentro da pasta ‘Resources -> layout’ você precisa criar o novo arquivo de layout de atividades “activity_dashboard.axml”. A maneira mais fácil de fazer isso é indo para a opção New Item… no menu de contexto e selecionando o modelo ‘Android Layout’. Dentro de seu novo arquivo de layout adicione um componente simples do TextView para exibir texto como este:

<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>

Neste trecho você tem um componente TextView com um ID de referência que está centrado no meio da página, do qual irá exibir uma mensagem de boas vindas. Em seguida, crie uma classe de atividade correspondente ‘DashboardActivity’ por meio da opção ‘New Item…’ no menu de contexto do projeto no explorador de soluções e selecionando o modelo ‘Activity’. Para ligar esta classe ao seu arquivo de layout, você precisa chamar a função SetContentView no método gerado OnCreate() (sob a invocação herdada do método base):

SetContentView(Resource.Layout.activity_dashboard);

Para personalizar sua mensagem de boas-vindas, você vai querer passar o nome do usuário para sua nova atividade. Se você se lembra antes, a melhor maneira de fazer isso foi com Extras na intenção, e você criou uma classe de extensões para lidar com isso. Como antes, adicione novos métodos para ‘Put’ e ‘Get’ de um ‘nome’ extra no arquivo IntentExtensions.cs criado acima:

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);}

Agora usando esta funcionalidade estendida, após a chamada para SetContentView você fez no método OnCreate(), recupere o nome do usuário e defina o texto do componente TextView apropriadamente:

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

Neste extrato, ao recuperar a instância TextView o seu valor é definido para a sua mensagem de boas-vindas, da qual é criado usando os Recursos do Android equivalente a string.Format().

Com isto a actividade do seu painel de instrumentos está completa, e agora precisa de lhe ligar. No espaço reservado para o caso de sucesso que deixei aberto a partir do método OnSignInAttempted, você pode conseguir isso adicionando o seguinte código:

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();

O primeiro bloco lê a ficha e recupera o nome do usuário (se ela existir). No segundo um novo Intent é criado para a atividade do painel, o nome do usuário é armazenado neste Intent usando seu método de extensão acima definido, e então a atividade é iniciada (ou seja, navegada para). Para evitar que o usuário navegue de volta a esta página depois, o código termina chamando o método Finish().

Executar seu aplicativo Android

Agora é hora de iniciar seu aplicativo usando o dispositivo escolhido!

Se você estiver depurando usando o emulador, isso deve ser tão simples quanto clicar em F5 do qual primeiro abrirá e carregará o emulador, e então o código será implantado nele. Como nota lateral, você não precisa fechar o emulador entre as tentativas de execução/debug, já que ele só precisa reimplantar o app.

Se você estiver depurando usando um dispositivo que não tenha sido usado para este propósito antes, você precisará configurar o dispositivo primeiro. Faça isso ativando as opções do desenvolvedor e dentro do novo menu, ligando ‘Debugging do Android’ sob o cabeçalho ‘Debugging’. Depois disso, basta conectar o dispositivo, aceitar a caixa de diálogo no seu dispositivo confirmando que esta é uma conexão segura de depuração, e você deve ser capaz de implantar e executar seu aplicativo com F5. Note que os dispositivos físicos têm maior precedência do que o emulador e mudarão para ele como opção padrão de depuração quando conectado.

Após a sua aplicação ter sido implantada e carregada, você será saudado pelo modelo padrão de página única. Abra o menu no canto superior direito para entrar, e uma vez que você tenha inserido seus detalhes você deve retornar a esta página com a barra de progresso girando antes de ser enviado automaticamente para a página do painel com sua mensagem de boas-vindas:

Saiba mais sobre Xamarin, OpenID Connect, e Autenticação Segura

Se você seguiu todos estes passos você agora tem uma aplicação básica Android construído usando Xamarin.Android, com autenticação de usuário totalmente funcional baseado em OpenID e no serviço Okta. A partir daqui você pode facilmente expandir na atividade do painel para implementar sua funcionalidade.

Para ver o código deste post de cabeça cheia na nossa página do GitHub.

Se este tutorial aguçou seu apetite para o desenvolvimento do Xamarin e você gostaria de aprender mais, então eu sugiro fortemente que você dê uma olhada nestes outros grandes artigos:

  • Adicionar Gerenciamento de Identidade ao seu aplicativo Android
  • Adicionar Autenticação ao seu aplicativo Xamarin.Forms com OpenID Connect
  • Build um aplicativo para iOS e Android com Xamarin

Deixe uma resposta

O seu endereço de email não será publicado.