Oletko .NET-kehittäjä, joka on aina halunnut tehdä mobiilisovelluksen? Tai ehkä olet kokeillut natiivien mobiilisovellusten rakentamista Androidilla tai iOS:llä, mutta et ole pitänyt kielistä? No sitten olet onnekas! .NET-maailmaa on siunattu Xamarinilla; joukko työkaluja, joiden avulla voit rakentaa mobiilisovelluksia Androidille, iOS:lle ja Windowsille Visual Studiossa.

Xamarinilla on kaksi päämakua: Xamarin platform (Xamarin.iOS ja Xamarin.Android) ja Xamarin.Forms. Xamarin.Formsin avulla valtaosa liiketoimintalogiikasta ja käyttöliittymästä voidaan kirjoittaa yhteen jaettuun projektiin, joka tuottaa täysin toimivia sovelluksia kaikkiin kolmeen iOS-, Android- ja Windows-käyttöjärjestelmään (UWP). Xamarin-alusta taas on hyvin paljon alustakohtaista työtä ja muistuttaa enemmän natiivien sovellusten kirjoittamista, mutta C#:lla.

Tässä opetusohjelmassa tarkastelen tarkemmin Xamarin-alustaa ja Android-käyttöjärjestelmän työkalupakkia, joka tunnetaan nimellä Xamarin.Android. Yleisenä tavoitteena on, että voit luoda yksinkertaisen natiivin Android-sovelluksen, jossa on mukana käyttäjän perustodennus.

Visual Studion ja ympäristösi määrittäminen

Seuraavaksi tarvitset kopion Visual Studiosta sekä ’Mobiilikehitys .NET:llä’ -työkirjan. Voit joko ottaa tämän ominaisuuden käyttöön Visual Studion ensiasennuksen yhteydessä tai käyttää sitä ’Työkalut -> Hae työkalut ja ominaisuudet…’ -valikkokohdasta:

Testatessasi ja suorittaessasi sovellustasi voit valita, teetkö sen joko Android-emulaattorilla, joka pyörii kehityskoneellasi, vai suoraan olemassa olevaan Android-laitteeseen yhdistämällä. Tässä ei ole oikeaa vaihtoehtoa, ja eri kehittäjät suosivat eri muototekijöitä. Jos valitset ensin mainitun vaihtoehdon, sinun on varmistettava, että kun olet valinnut työmäärän, että oikeanpuoleisessa ruudussa (”Asennustiedot”) valintaruudut Intel Hardware Accelerated Execution Manager ja Google Android Emulator ovat valittuna (kuten yllä).

Varmista Android-ympäristösi Visual Studiossa

Varmistaaksesi, että kaikki on asennettu oikein ja konfiguroitu oikein, siirry kohtaan ’Työkalut -> Asetukset -> Xamarin -> Android-asetukset’ ja tarkista, että Java Development Kitin sijainti- ja Android SDK:n sijainti -polut ovat voimassa (i.eli niissä on vihreä rasti):

Jos jompikumpi puuttuu, joudut asentamaan Java Development Kitin tai Android SDK:n manuaalisesti.

Luo Xamarin-sovellus

Aloita luomalla uusi projekti ja valitse ’Android-sovellus (Xamarin)’-päämalli (löytyy Android-valikosta). Seuraavalla sivulla sinun kannattaa valita ’Single View App’ -vaihtoehto, koska se on loistava aloitusmalli, jonka pohjalta voit työskennellä.

Minimi-Android-version osalta tämä on jotain, joka riippuu henkilökohtaisesta valinnastasi kehittäjänä. Tässä on kompromissi sen välillä, että voit käyttää uusimpien versioiden uusimpia ja parhaita API-ominaisuuksia ja tukea asiakkaitasi, joilla on vanhemmat versiot. Päätöksenteon helpottamiseksi Google julkaisee alustaversioiden jakelutietoja, joita se kerää osana jakeluosoitettaan melko säännöllisesti. Henkilökohtainen valintani on 5.0 tai 6.0 riippuen siitä, onko kyseessä julkiseen käyttöön tarkoitettu sovellus vai vain yritysten puhelimiin tarkoitettu tilaussovellus (eli heillä on todennäköisesti uusimmat päivitykset); tässä esimerkissä olen valinnut jälkimmäisen. Huomaa, että tämä versio eroaa Target Android Version -versiosta, ja se tulisi aina asettaa uusimpaan julkaistuun SDK-versioon, sillä mitään pienempää versiota ei hyväksytä Google Play -kauppaan.

Kun olet luonut tämän, jäljelle jää vain tarvittavien NuGet-pakettien tuonti. Tätä opetusohjelmaa varten tarvitset:

  • Xamarin.OpenId.AppAuth.Android – Käyttäjän todentamiseen käytetään OpenID Connect -standardia (OAuth 2.0:n parannus). Helpoin tapa toteuttaa tätä spesifikaatiota noudattavaa asiakaskoodia on käyttää Androidin AppAuth-asiakas-SDK:ta, ja avuksi Xamarin on portannut tämän toiminnallisuuden sisältävän paketin käyttöösi.
  • System.IdentityModel.Tokens.Jwt – Tässä autentikointimenetelmässä käytetään JSON Web Tokens -tekniikkaa. Näistä tunnisteista tarvittavien tietojen poimimiseen tarvitset tätä pakettia.

Lisäksi tarvitset myös nämä kaksi pakettia, koska AppAuth tukeutuu niihin:

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

Tutustu Xamarin-projektiin

Jos et ole koskaan aiemmin työskennellyt Androidin parissa, yksi tärkeimmistä periaatteista, johon kannattaa tutustua, on Activityn käsite. Aktiviteetit ovat komponentteja, joita käytetään käyttöliittymän näyttämiseen; yksinkertaisimmillaan voit ajatella, että aktiviteetit vastaavat sovelluksen sivuja, joiden välillä käyttäjä voi navigoida. Koodissa aktiviteettia edustaa luokka, mutta kuten sivut ASP.NET:ssä, voit (ja melkein aina teetkin) liittää siihen XML-pohjaisen ulkoasutiedoston (.axml-tiedosto), jotta se voidaan näyttää. Kaikki uudet projektit luovat ”MainActivity.cs”- ja ”activity_main.axml”-tiedostot ensimmäiseksi Activityksi (eli sivuksi), joka suoritetaan sovelluksen avaamisen jälkeen. Tämä voidaan vaihtaa mihin tahansa muuhun Activityyn käyttämällä luokan Activity-attribuutin MainLauncher = true ominaisuutta.

Lähteet on suunniteltu käsiteltäviksi omassa hakemistossaan, ja ne noudattavat jonkin verran tiukkaa nimeämiskäytäntöä. Suosittelen lämpimästi tallentamaan mahdollisimman suuren osan resursseistasi tähän hakemistoon, koska se helpottaa näiden muuttujien uudelleenkäyttöä jatkuvassa kehityksessäsi. Resurssit-hakemiston ’values’-hakemistossa on tiedostoja, joilla on tietty käyttötarkoitus:

  • Strings.xml – Isännöi kaikkia käyttäjäkohtaisia merkkijonoja. Tätä on erityisen tärkeää käyttää, koska sen avulla voit lokalisoida merkkijonot globaalia yleisöä varten.
  • Styles.xml – Sieltä löydät muotoiluobjekteidesi muotoiluun tarvittavat attribuutit; ajattele sitä kuin CSS-tiedostoa.
  • Colors.xml – Paikka, johon voit tallentaa viittaukset väreihin, joita käytät useimmiten osana muotoilua.
  • Dimens.xml – Kuten nimestä voi päätellä, paikka, jossa määrittelet sovelluksesi ulkoasun asetetut mitat.

Muut merkittävät hakemistot eivät noudata mitään nimeämiskonventiota tiedostoilleen, mutta niiden on sisällettävä tiettyjä tiedostotyyppejä:

  • Layout – Sijainti .axml-tiedostojen säilyttämistä varten. Näissä tiedostoissa määritellään täydelliset toimintoasettelut, ohjelmallisesti luodut ja täytettävät asettelukomponentit, valintaikkunoiden (hälytyslaatikoiden) asettelut jne.
  • Menu – Sieltä löytyvät valikoiden ja niiden kohteiden määritelmät. Nämä ovat .xml-tiedostoja, joissa on menu juurielementtinä ja item lapsielementtejä, joista voidaan ryhmitellä group-elementeillä. Yleisimpiä valikoita, joihin törmäät, ovat ylivuotovalikko (kolmen pystysuoran pisteen painikkeesta) tai navigointivalikko (kotisivun ’hampurilaispainikkeesta’).
  • Mipmap – Jossa haluat määritellä kuvia, jotka on skaalattava näytön tiheyden mukaan, eli kuvia, joihin muut sovellukset viittaavat ja joita ei käytetä sisäisesti. Sovelluksen kuvake on yleisin sisältö, jonka laitat mipmap-hakemistoihin.
  • Drawable – Ei vakiona oletusprojektipohjassa, mutta voidaan luoda itse. Tänne tallennat sovelluksen sisällä käytettävät kuvat/piirrettävän sisällön, esim. aloitusnäytön, mukautetun edistymispalkin mallit, sovelluksen sisällä käytettävät kuvakkeet jne.

Viimeiseksi, jos sinulla on raakasisältötiedostoja, joita haluat käyttää osana sovellusta (esim. teksti- tai fonttitiedosto), Assets-hakemisto on paikka, johon ne sijoitetaan. Assets-tiedostoina nämä tiedostot otetaan käyttöön sovelluksesi mukana, jotta voit käyttää niitä Asset Managerin avulla.

Jos haluat lisätietoja Assets- ja Resurssi-tiedostoista ja niiden käytöstä, uuden luodun projektin jokaisessa hakemistossa on kätevät ”Tietoja”-tekstitiedostot.

Lisää käyttäjän tunnistautuminen Xamariniin OpenID Connectin avulla

Suurimmassa osassa sovelluksia tarvitaan nykyään jonkinlainen käyttäjän tunnistautumiskeino, jotta kehittäjä voi tarjota räätälöityjä käyttökokemuksia ja jotta käyttäjä voi vuorostaan säilyttää tietonsa eri laitteissa/asennuksissa. Tämän lisäksi on kysymys pääsynvalvonnasta, joka voi olla hyödyllistä valtuuttaa osajoukko käyttäjiä lisätoimintoja varten. Luonnollisesti tämä voi olla melko työläs tehtävä, varsinkin jos olet luomassa sovelluksia ja tarvitset uuden järjestelmän jokaista sovellusta varten. Onneksi Ocktan avulla voit perustaa sovelluksen muutamassa minuutissa, ja sen jälkeen kaikki kova työ on tehty puolestasi! Okta-palvelu on OAuth 2.0 -yhteensopiva ja sertifioitu OpenID Connect -palveluntarjoaja, joten se toimii täydellisesti AppAuth-asiakas-SDK:n kanssa kaikissa autentikointi- ja valtuutustarpeissasi.

Okta-sovelluksen perustaminen

Aluksi sinun pitäisi perustaa uusi sovellus Okta-tilillesi tätä projektia varten. Jos sinulla ei vielä ole sellaista, on todella helppoa luoda uusi ikuisesti ilmainen kehittäjätili.

Kun tämä on tehty ja olet kirjautunut sisään kehittäjän kojelaudalle, merkitse muistiin Org-URL, koska tarvitsemme sitä myöhemmin:

Kojelaudalta siirry ’Applications’ -välilehdelle ja sieltä ’Add Application’. Olet luomassa natiivia Android-sovellusta, joten kannattaa valita ’Native’-alustamalli.

Tältä sivulta lisää sovelluksellesi nimi ja jätä kaikki muu oletukseksi. Kun olet tallentanut muistiin Login redirect URI:t ja Client ID:n, koska tarvitset niitä seuraavaksi.

Sitten voit käyttää näitä kolmea Okta-arvoa helposti tulevaisuudessa, suosittelen laittamaan ne omaan staattiseen luokkaansa uuteen hakemistoon autentikointilogiikalle:

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

Luo autentikointipalveluntarjoaja

Hoidetaan boilerplate-koodi pois tieltä. Sinun on konfiguroitava sovellus ilmoittamaan sille uudelleenohjauksen URI-skeema. Skeema on kirjautumisen uudelleenohjauksen URI (vakiomuodossa käänteisenä verkkotunnuksena) ilman polkua. Esimerkiksi yllä olevan kuvakaappauksen perusteella järjestelmäni olisi ’com.oktapreview.dev-123456’.

Helpoisin tapa tehdä tämä on lisätä alla oleva intent-suodatinpätkä AndroidManifest.xml-tiedostoon ratkaisusi Properties-kansiossa. Lisää Application-tagin sisälle seuraava XML ja vaihda scheme-arvo omaksi:

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

Määritä myös valtuutuksen tuloksen malli yksinkertaisella luokalla. Vaikka en tule käyttämään kaikkia alla kirjoittamiani arvoja koodin sisällä, näytän, miten ne täytetään, jotta voit käyttää niitä jälkeenpäin. Koska tämä on osa sovelluksesi mallia, luo kansio nimeltä Models ja lisää sen sisään AuthorizationResult.cs-luokka. Lisää sitten seuraava koodi:

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

Androidissa ei ole globaalia tilaa, jonka kanssa voisit työskennellä, joten jos haluat välittää yksinkertaisia arvoja aktiviteettien välillä, paras tapa tehdä se on käyttää Extras-toiminnallisuutta Intent-objektissa. Intent on Androidissa ennalta määritelty luokka ja toinen keskeinen käsite, joka on ymmärrettävä. Se on suoritettavan toiminnon abstraktio (eli ”aikomuksesi”), ja siirtyäksesi eteenpäin toiseen aktiviteettiin sinun on luotava tämän luokan instanssi, jossa on se aktiviteetti, johon ”aiot” siirtyä. Intent-objektin Extras-ominaisuudet ovat itse asiassa vain sanakirja, jossa on avaimet objektin arvoihin, ja niitä käytetään Put ja tyypitetyillä Get-metodeilla.

Vaikka nämä metodit pitävät käytön suhteellisen selkeänä ja helppona, pidän henkilökohtaisesti siitä, että kaikki pääsy niihin pidetään omassa luokassaan (tarkemmin sanottuna extensions-luokassa) huolenaiheiden paremman erottelun säilyttämiseksi. Tämä on erittäin hyödyllistä, koska sinun ei tarvitse käyttää avaimia eri luokkien välillä ja voit varmistaa tyyppiturvallisuuden, kun laitat ja saat näitä arvoja. Valtuutuksen tarjoajassasi haluat: tallentaa AuthState:n, pystyä tarkistamaan, onko se siellä, ja palauttaa sen, jos se on siellä. Luo uusi kansio nimeltä Extensions ratkaisun juureen. Lisää sitten uusi luokka nimeltä IntentExtensions.cs. Tee luokasta public ja static ja lisää sitten luokan sisälle seuraava koodi:

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

Nyt on aika määritellä auktorisointipalvelun tarjoaja, AuthorizationProvider.cs kansioon Authentication, jonka loit aiemmin luokkaa Configuration.cs varten. Poista ensin kaikki using-lausekkeet vasta luodun luokan sisältä ja ilmoita sitten konfiguraatio static readonly-muuttujina:

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

Konfiguraation päätepiste on OpenID:ssä vakiona Discovery-päätepisteenä, josta löytyy kaikki tuettu. Huomaa tässä olen kirjoittanut, että tässä käytetään ’oletusarvoisen’ palveluntarjoajan nimeä. Jos sinulla on eri palveluntarjoaja, sinun on muutettava tämä tässä. Huomaa myös, että tässä käytetään Uri-luokan Android.Net-makua eikä System-versiota – sinun on lisättävä edellinen käyttöösi tai määriteltävä tyyppi täysin, jotta tämä toimii. Scopes-muuttuja, kuten muissakin OpenID-järjestelmissä, määrittelee, mihin meillä on valtuudet päästä käsiksi.

Seuraavaksi sinun tulee ilmoittaa jäsenmuuttujasi:

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

Lyhyt selitys kuhunkin:

  • Auktorisointipyyntö (authorization request) ja valmistunut aikomus (completed intent) ovat parametreja, jotka on luotu käytettäväksi valtuutuskutsun tekemistä varten. Olen kirjoittanut ne tässä globaaleiksi muuttujiksi minimoidakseni parametrien välittämisen eri metodeihin.
  • AuthorizationState-muuttuja nimensä mukaisesti määrittelee tämänhetkisen annetun auktorisointitilan.
  • AuthorizationService-muuttuja sisältää auktorisointipalvelun instanssin.
  • Konteksti-muuttuja tässä on kutsuvasta aktiviteetista, joten voit viitata siihen tarvittaessa.
  • Loppujen lopuksi taskCompletionSource mahdollistaa kaikkien näiden kutsujen tekemisen asynkronisesti ja paluun, kun ne on saatu valmiiksi.

Nyt sinun tulee määritellä näiden lukukelpoisten muuttujien arvot konstruktorissasi ja ilmoittaa julkiset metodit, joita koodisi kutsuu:

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

SignInAsync-metodi on, kuten olet ehkä arvannutkin, epäsynkroninen menetelmä, jolla voit rekisteröidä käyttäjän sisään. Tämä palauttaa aiemmin kirjoittamasi AuthorizationResult-luokan. NotifyCallback taas on sitä varten, että kutsuva aktiviteetti, kun se on palannut ulkoiselta sisäänkirjautumissivulta, kutsuu takaisin auktorisointipalvelun tarjoajalle ja ilmoittaa sille, että se on valmis. Kirjautumismenetelmän olen pilkkonut useisiin aliohjelmiin, ja se näyttää tältä:

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

Tässä olet määrittänyt palvelun konfiguraation, rakentanut valtuutuspyynnön ja aikomuksen kutsua, kun valtuutus on suoritettu, ja sitten odotat valtuutuspyyntöä. Valtuutuspyynnön rakentaminen tapahtuu seuraavasti:

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

Tämän metodin tehtävänä on abstrahoida AuthorizationRequest.Builder työ pois ja luoda pyyntö. Seuraavaksi sinun on rakennettava Intent sen jälkeen, kun operaatio on suoritettu:

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

Tässä vaiheessa haluamasi ”aikomus” on palata MainActivity:iin, johon on liitetty uusi AuthState. Viimeisenä tässä virrassa käsitellään pyynnön suorittamista:

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

Koska PerformAuthorizationRequest on synkroninen ja palaa tyhjänä, koodi odottaa taskCompletionSource jäsentä tietäen, että se asetetaan aina vasta, kun vastaus on haettu. Juuri tässä samassa vaiheessa tiedät, että valtuutustila täytetään (jos kaikki onnistui), joten voit palauttaa niiden arvot osana AuthorizationResultia.

Toinen julkinen metodi NotifyCallback, kuten aiemmin mainitsin, on se, jota haluat MainActivity-luokan kutsuvan takaisin, kun edellä mainittu completedIntent on suoritettu. Tässä metodissa haluat tarkistaa vastauksen, päivittää tilan asianmukaisesti ja jos se onnistuu, suorittaa tokeninvaihtopyynnön:

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

Tässä näet, että fail-tapauksissa asetin taskCompletionSource:n tuloksen arvoksi false, jolloin yllä oleva RequestAuthorization-metodi vapautuu. Lisäksi PerformTokenRequest-metodi ottaa sisäänsä delegaatin, ReceivedTokenResponse, joka suoritetaan, kun se on valmis. Tämä metodi on seuraava:

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

Tässä vaiheessa sinulla pitäisi olla kaikki tarvitsemasi valtuutustiedot, joten voit päivittää tilan asianmukaisesti (josta löydät kirjautumismetodista palautettavat arvot) ja asettaa tuloksen vapauttamaan tehtävän taskCompletionSource eston.

Toteuta todennus Xamarin-käyttöliittymässäsi

Puhdistustoimenpiteenä voit halutessasi poistaa kaikki viittaukset ”Floating Action Bar” (kirjoitetaan myös nimellä ”FAB”) pääaktiviteettiluokkien/axml-tiedostojen sisältä, sillä ne ovat tarpeetonta paisuttelua tässä vaiheessa.

Salliaksesi käyttäjälle kirjautumisen sinun on nyt toteutettava tämä toiminnallisuus käyttöliittymään. Kun otetaan huomioon oletussuunnittelu, intuitiivisin tapa tehdä tämä olisi lisätä kohde oikeassa yläkulmassa olevaan ylivuotovalikkoon. Voit tehdä tämän muokkaamalla menu_main.xml-tiedostoa kansiossa ’Resources -> menu’ ja lisäämällä tämän kohteen menu-tagin lapseksi:

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

Tällä koodilla olet luonut uuden vaihtoehdon, jonka otsikko määritetään merkkijonon resurssitiedostossa. Kuten aiemmin mainittiin, Androidissa on paras käytäntö laittaa kaikki käyttäjälle suunnattu teksti string resources -tiedostoon. Voit ilmoittaa nämä tiedot muokkaamalla strings.xml-tiedostoa kansiossa ’Resources -> values’ ja lisäämällä nämä rivit:

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

Ei tässä ole ainoastaan ilmoitettu merkkijonoa ’Kirjaudu sisään’ -painiketta varten, vaan olen myös lisännyt yläpuolelle merkkijonon tervetuliaisviestiä varten, joka lähetetään käyttäjälle sen jälkeen, kun hän on kirjautunut sisään. Se vastaa C#-koodia this string would be ”Hei, {0}!”`, jossa paikanvaraaja on tyypiltään merkkijono.

Huomaa, että kaikkien näihin Resursseihin perustuviin tiedostoihin tehtävien päivitysten yhteydessä Resource.designer.cs-luokka luodaan automaattisesti uudestaan jokaiselle luomallesi objektille uusilla tunnuksilla, joihin voidaan viitata koodissasi. Jos tämä ei toimi tietyssä tiedostossa, valitse se Solution Explorerissa ja katso Properties-ikkunaa. Varmista, että CustomTool-ominaisuus on asetettu arvoon MSBuild:UpdateGeneratedFiles, koska tämä todennäköisesti puuttuu ja estää suunnittelijatiedostoa tunnistamasta sitä resurssiksi.

Seuraavaksi lisää ProgressBar olemassa olevaan activity_main.axml-asettelutiedostoon:

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

Tällä ProgressBar:lla (tai pyörittimellä) on tunnus, johon voit viitata koodilla, ja se on asetettu istumaan ruudun keskipisteen ympärille. Näkyvyys on toistaiseksi poissa, mutta kun auktorisointikoodisi on käynnissä, voit asettaa sen näkyväksi ja ilmoittaa käyttäjälle, että sovellus on varattu.

Nyt sinulla on painike auktorisoinnin avaamiseen ja edistymiskehrääjä, joka ilmoittaa käyttäjälle, että sovellus on varattu, on aika käyttää niitä. Lisää MainActivity-luokkasi Activity-attribuuttiin (luokan otsikon yläpuolella) seuraava ominaisuus:

LaunchMode = LaunchMode.SingleTask

Tämän ominaisuuden avulla varmistat, että MainActivity-luokasta on vain yksi instanssi, etkä avaa jatkuvasti uusia. Kun olet tehnyt tämän, lisää edellä kirjoittamallesi AuthorizationProvder-luokalle staattinen jäsenmuuttuja ja luo sen instanssi OnCreate-metodin olemassa olevaan ohitukseen. Huomaa, että tämä tulisi tehdä metodin sisällä olevan olemassa olevan koodin jälkeen:

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

Seuraavaksi ohita OnNewIntent-metodi. Tarkoitus on, että kun luodaan tämän luokan uusi intentti (eli kun ulkoinen kirjautumisikkuna palaa), kutsut NotifyCallback-metodia AuthorizationProvider:stä. Tähän sisältyy myös nopea tarkistus, jolla varmistetaan, että kyseessä on odotettu virtaus:

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

Lisää nyt lisäämäsi valikkokohdan taakse koodi. Lisää OnOptionsItemSelected-metodin olemassa olevaan ohitukseen if-lause, jossa on kutsu uudelle metodille, joka hoitaa sisäänkirjautumisprosessin seuraavasti:

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

Tämä uusi metodi aloittaa tekemällä hetki sitten lisäämäsi ProgressBar:n näkyväksi; jos haluat hakea minkä tahansa komponentin asettelutiedostosta, käytä geneeristä metodia FindViewById ja syötä argumentiksi komponentin ID. Tämän jälkeen kutsu SignInAsync-metodia ja odota sen tulosta. Kun kutsu on palannut, tulos tarkistetaan valtuutetuksi. Jos valtuutus jostain syystä epäonnistuu, näyttöön ilmestyy virhevalintaikkuna, ja etenemispyörä katoaa jälleen. Jätän onnistumistapauksen yksityiskohtaisen kuvaamisen toistaiseksi, koska siinä tapauksessa tarvitaan vielä jokin paikka, jonne mennä:

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

Kun käyttäjä on todennettu, sinun pitäisi ohjata hänet kokemuksesi seuraavalle sivulle. Jos muistat aiemmin, jokaista sivua edustaa aktiviteetti, joten sinun on nyt luotava uusi aktiviteetti.

Aloittaaksesi sinun on luotava ”Resources -> layout”-kansioon uusi aktiviteetin asettelutiedosto ”activity_dashboard.axml”. Helpoin tapa tehdä tämä on mennä kontekstivalikon New Item… -vaihtoehtoon ja valita ’Android Layout’ -malli. Lisää uuteen layout-tiedostoosi yksinkertainen TextView-komponentti näyttämään tekstiä seuraavasti:

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

Tässä pätkässä sinulla on TextView-komponentti, jolla on viitattavalla ID:llä varustettu komponentti, joka on keskitetty sivun keskelle ja josta näytetään tervetuloviesti. Seuraavaksi luodaan vastaava aktiviteettiluokka ’DashboardActivity’ Solution Explorerissa olevasta projektista kontekstivalikon ’New Item…’-valinnalla ja valitsemalla ’Activity’-malli. Linkittääksesi tämän luokan asettelutiedostoonsa sinun on kutsuttava SetContentView-funktiota luodussa OnCreate()-metodissa (perityn perusmetodin kutsun alla):

SetContentView(Resource.Layout.activity_dashboard);

Tervetuloviestin personoimiseksi sinun on syytä välittää käyttäjän nimi uuteen aktiviteettiin. Jos muistat aiemmin, paras tapa tehdä tämä oli tarkoituksen extrojen avulla, ja olet luonut extensions-luokan tätä varten. Kuten aiemmin, lisää uudet metodit ’Put’ ja ’Get’ ’name’-ekstran ’nimelle’ edellä luomassasi IntentExtensions.cs-tiedostossa:

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

Nyt tämän laajennetun toiminnallisuuden avulla, sen jälkeen, kun olet kutsunut SetContentView:n metodin OnCreate(), hae käyttäjän nimi ja aseta TextView-komponentin teksti sopivaksi:

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

Tässä otteessa TextView-instanssin hakemisen jälkeen sen arvoksi asetetaan tervetuliaisviestisi, jonka luomisessa käytetään Android-resurssien vastinetta string.Format().

Tämän jälkeen dashboard-aktiviteettisi on valmis, ja sinun on nyt kutsuttava sitä. Menetelmästä OnSignInAttempted auki jättämääni onnistumistapauksen paikanhaltijaan saat tämän aikaan lisäämällä seuraavan koodin:

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

Ensimmäinen lohko lukee tokenin ja hakee käyttäjän nimen (jos se on olemassa). Toisessa lohkossa luodaan uusi Intent dashboard-aktiviteettia varten, käyttäjän nimi tallennetaan tähän Intent käyttäen edellä määrittelemääsi laajennusmetodia, ja sitten aktiviteetti käynnistetään (eli siihen navigoidaan). Jotta käyttäjä ei voisi navigoida takaisin tälle sivulle jälkikäteen, koodi päättyy kutsumalla Finish()-metodia.

Käynnistä Android-sovellus

Nyt on aika käynnistää sovelluksesi valitsemallasi laitteella!

Jos debuggailet emulaattorilla, tämän pitäisi olla niinkin yksinkertaista kuin F5-näppäimen painallus, jolloin emulaattori avataan ja ladataan ensin, ja sen jälkeen koodi otetaan käyttöön siihen. Sivuhuomautuksena sinun ei tarvitse sulkea emulaattoria ajo-/debuggausyritysten välillä, sillä sen tarvitsee vain ottaa sovellus uudelleen käyttöön.

Jos debuggailet käyttämällä laitetta, jota ei ole aiemmin käytetty tähän tarkoitukseen, sinun on ensin määritettävä laite. Tee tämä ottamalla kehittäjäasetukset käyttöön ja kytkemällä uudessa valikossa ’Android debugging’ päälle ’Debugging’ -otsikon alta. Kytke laite tämän jälkeen laitteeseen, hyväksy laitteessa näkyvä valintaikkuna, jossa vahvistetaan, että kyseessä on turvallinen virheenkorjausyhteys, ja sinun pitäisi pystyä ottamaan sovellus käyttöön ja ajamaan sitä F5:llä. Huomaa, että fyysisillä laitteilla on korkeampi etuoikeus kuin emulaattorilla, ja ne siirtyvät siihen oletusarvoiseksi debuggausvaihtoehdoksi, kun ne on kytketty.

Kun sovelluksesi on otettu käyttöön ja ladattu, sinua tervehtii oletuksena oleva yhden sivun malli. Avaa oikeassa yläkulmassa oleva valikko kirjautuaksesi sisään, ja kun olet syöttänyt tietosi, sinun pitäisi palata tälle sivulle, jossa edistymispalkki pyörii, ennen kuin sinut lähetetään automaattisesti kojelautasivulle, jossa on tervetuliaisviestisi:

Opi lisää Xamarinista, OpenID Connectista ja turvallisesta todennuksesta

Jos olet seurannut kaikkia näitä vaiheita mukana, sinulla on nyt perus-Android-applikaatio, joka on rakennettu Xamarinin avulla.Android, jossa on täysin toimiva OpenID:hen ja Okta-palveluun perustuva käyttäjän todennus. Tästä voit helposti laajentaa kojelaudan toimintaa toteuttaaksesi toiminnallisuutesi.

Katsoaksesi tämän postauksen koodin kokonaisuudessaan siirry GitHub-sivullemme.

Jos tämä opetusohjelma on herättänyt ruokahalusi Xamarin-kehitykseen ja haluat oppia lisää, suosittelen lämpimästi tutustumaan näihin muihin loistaviin artikkeleihin:

  • Add Identity Management to Your Android App
  • Add Authentication to Your Xamarin.Forms App with OpenID Connect
  • Build an App for iOS and Android with Xamarin

Vastaa

Sähköpostiosoitettasi ei julkaista.