Pozivanje Platform Specific koda iz zajedničkog projekta - Xamarin.Forms

Pozivanje Platform Specific koda iz zajedničkog projekta - Xamarin.Forms

offline
  • Lead Developer ⠀ ⠀⠀⠀⠀⠀⠀ Go 5 Creative
  • Pridružio: 14 Feb 2008
  • Poruke: 12230

Tutorijal koristi primer iz ovog zvaničnog tutorijala.
Ja sam imao negde svoj primer napisan, ali se zagubio. Poenta je ista, samo se razlikuje funkcionalnost koda.

Xamarin.Forms nam omogućava da razvijamo nativne aplikacije za iOS, Android i UWP iz jednog zajedničkog C# projekta, bez brige da li će naš kod raditi na pojedinačnim platformama.

Zajednički projekat sadrži interfejs i kod koji radi na svim platformama.
Međutim, zajednički projekat nije svemoguć i neretko ćete biti u situaciji da morate da izvršite neki kod koji je specifičan za svaku platformu. To možete uraditi tako što ćete u pojedinačnim projektima pisati platform specific kod, koji će se izvršiti prilikom pokretanja aplikacije, pre inicijalizacije Xamarin.Forms interfejsa i njegovog koda. Odlično ako treba da izvučete neke podatke iz uređaja, recimo.

No, šta ako treba da pozovemo neku funkcionalnost koja nije podržana u zajedničkom projektu, u toku rada aplikacije, ili koristi kod koji se razlikuje na svakoj platformi?

U tom slučaju možemo da koristimo Dependency Injection, što je i tema ovog tutorijala.
Nakon što isti implementiramo, imaćemo mogućnost da funkcionalnost pozovemo iz zajedničkog projekta, a naš projekat će se pobrinuti da pronađe kod i izvrši isti.

Postupak počinje definisanjem interfejsa u zajedničkom projektu:

Desni klik na zajednički projekat -> Add -> New Item > Interface -> "IDeviceInfo"

public interface IDeviceInfo {     string GetUniqueIdentifier(); }

Dakle, ovo je klasični C# Interfejs.
Sada ćemo isti implementirati na pojedinačnim platformama.
Ovaj tutorijal se fokusira na iOS i Android platforme.

Desni klik na iOS projekat -> Add -> New Item -> Class -> "DeviceInfo"
Implementiramo interfejs u ovoj klasi :

class DeviceInfo : IDeviceInfo     {         public string GetUniqueIdentifier()         {             throw new NotImplementedException();         }     }

Sada možemo da pišemo kod koji je specifičan za iOS platformu :

 public string GetUniqueIdentifier()         {             return UIDevice.CurrentDevice.IdentifierForVendor.AsString();         }

Klasa sada izgleda ovako :

  class DeviceInfo : IDeviceInfo     {         public string GetUniqueIdentifier()         {             return UIDevice.CurrentDevice.IdentifierForVendor.AsString();         }     }

Kako imamo i Android projekat, isto ćemo uraditi i u njemu.

Desni klik na Android projekat -> Add -> New Item -> Class -> "DeviceInfo"

Postupak je apsolutno isti do koda koji je specifičan za Android platformu :

 return Android.Provider.Settings.Secure.GetString(Xamarin.Forms.Forms.Context.ContentResolver,                                                           Android.Provider.Settings.Secure.AndroidId);  

Finalna klasa izgleda ovako :

public class DeviceInfo : IDeviceInfo {     public string GetUniqueIdentifier()     {         return Android.Provider.Settings.Secure.GetString(Xamarin.Forms.Forms.Context.ContentResolver,                                                           Android.Provider.Settings.Secure.AndroidId);     } }

Dakle,

Deklarisali smo interfejs u zajedničkom projektu
Implementirali smo interfejs na svim pojedinačnim platformama
Napisali smo nativni kod za svaku platformu


Ostalo je još samo da registrujemo svaku klasu u pojedinačnim projektima sa Dependency Injection servisom.

U DeviceInfo klasi iOS i Android projekta, iznad Namespacea dodajemo :
[assembly: Xamarin.Forms.Dependency(typeof(DeviceInfo))]

Na kraju, ovako izgledaju obe klase :

Android :
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using MCTutorialDI.Droid; [assembly: Xamarin.Forms.Dependency(typeof(DeviceInfo))] namespace MCTutorialDI.Droid {     class DeviceInfo : IDeviceInfo     {         public string GetUniqueIdentifier()         {             return Android.Provider.Settings.Secure.GetString(Xamarin.Forms.Forms.Context.ContentResolver,                                                            Android.Provider.Settings.Secure.AndroidId);         }     } }

iOS:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Foundation; using MCTutorialDI.iOS; using UIKit; [assembly: Xamarin.Forms.Dependency(typeof(DeviceInfo))] namespace MCTutorialDI.iOS {     class DeviceInfo : IDeviceInfo     {         public string GetUniqueIdentifier()         {             return UIDevice.CurrentDevice.IdentifierForVendor.AsString();         }     } }


Samim tim, implementacija je gotova i možemo je jednostavno pozvati jednom linijom iz našeg zajedničkog projekta ovako :

DependencyService.Get<IDeviceInfo>().GetUniqueIdentifier();


Hajmo čas jedan brz primer upotrebe ovog koda iznad :

Izmenićemo MainPage naše aplikacije, tako da sadrži jedno dugme i Label.
Pritiskom dugmeta će se ispisati povratna informacija iz Native koda na specifičnoj platformi.

Dvoklik na MainPage.xaml u deljenom zajedničkom projektu, i dodajemo StackLayout koji sadrži Label i Button kontrole :

    <StackLayout>         <!-- Place new controls here -->         <Label x:Name="lblDeviceInfo" Text="Tap on the button bellow to get Device Info!"            HorizontalOptions="Center"            VerticalOptions="CenterAndExpand" />         <Button Clicked="Button_Clicked" Text="Get Device Info"/>           </StackLayout>

Obratiti pažnju:

Dali smo ime Label kontroli jer ćemo modifikovati njen tekst iz koda
Prilikom pravljenja dugmeta smo mu dodelili Click callback, koji je automatski kreiran u kodu stranice


Sačuvajte stranicu.
Kliknite na strelicu pored MainPage.xaml, kako bi proširili njen sadržaj a zatim dvoklikom otvorite MainPage.xaml.cs.

MainPage.xaml sadrži kod koji deklariše Interfejs.
MainPage.xaml.cs sadrži kod koji kontroliše interfejs i sve ostalo na toj stranici ili u aplikaciji.


U Clicked eventu dugmeta, koji je xaml trebao sam da napravi prilikom pisanja koda ako ste kliknuli na ponuđenu opciju, pišemo kod od ranije, s tim što ćemo odmah vrednost Text vrednost Label kontrole staviti na povratnu vrednost GetUniqueIdentifier-a :

    private void Button_Clicked(object sender, EventArgs e)         {           lblDeviceInfo.Text = DependencyService.Get<IDeviceInfo>().GetUniqueIdentifier();         }

Cela klasa izgleda ovako :

namespace MCTutorialDI {     // Learn more about making custom code visible in the Xamarin.Forms previewer     // by visiting https://aka.ms/xamarinforms-previewer     [DesignTimeVisible(true)]     public partial class MainPage : ContentPage     {         public MainPage()         {             InitializeComponent();         }         private void Button_Clicked(object sender, EventArgs e)         {           lblDeviceInfo.Text = DependencyService.Get<IDeviceInfo>().GetUniqueIdentifier();         }     } }

Pokrenite aplikaciju na svakom projektu pojedinačno i pipnite dugme.

U toku razvoja aplikacija ćete često morati da pišete platform specific kod.
Ako se zaglavite i niste sigurni šta i kako, bacite pogled na dokumentaciju za razvijanje aplikacija na Androidu, iOS-u. Bez obzira što je kod drugačiji i koristi drugi jezik, većina koda je "prevedena" u C# isto, tako da uz malo iskustva sa C#, malo guglanja i istraživanja, svaki nativni kod može da se prilagodi Xamarinu.

Ja sam konkretno koristio DI da pokupim informacije o kalendarima i korisnicima na Androidu i iOS-u. Obe platforme su imale svoj način na koji su obrađivale te podatke i to se u potpunosti razlikovalo. Mnogo mi je pomogla Android i iOS dokumentacija jer Xamarin i nije baš imao mnogo primera za ono što je meni bilo potrebno.

Ja sam još te podatke uvezao u Static klasu u zajedničkom projektu, tako da su mi uvek bili tu na raspolaganju za obradu. Nativni projekti već imaju pristup zajedničkom projektu, pa u većini slučajeva izvršenje koda prilikom pokretanja na platformi može da reši problem.



Registruj se da bi učestvovao u diskusiji. Registrovanim korisnicima se NE prikazuju reklame unutar poruka.
Ko je trenutno na forumu
 

Ukupno su 543 korisnika na forumu :: 30 registrovanih, 6 sakrivenih i 507 gosta   ::   [ Administrator ] [ Supermoderator ] [ Moderator ] :: Detaljnije

Najviše korisnika na forumu ikad bilo je 1567 - dana 15 Jul 2016 19:18

Korisnici koji su trenutno na forumu:
Korisnici trenutno na forumu: _Sale, A.R.Chafee.Jr., bobanrakidjic, borko_marjanovic, cole77, d.arsenal321, Dicus, Dorcolac, flash12, FOX2, goxin, ibssa, ivance95, joca83, Kaplar2, Marko Marković, matorigile, Milos ZA, Mlav, mocnijogurt, nradukic, ribar.ivan, Sasa Pavlovic, slonic_tonic, t84dar, Toni, Trpe Grozni, USSVoyager, yamato, zoranlik