Cum să faci o aplicație Android și iOS în C# pe un Mac

Publicat: 2022-03-11

A fost odată ca niciodată o companie care avea toate cele mai bune instrumente, iar scrierea de software pentru platforma lor a fost minunat. Dar încet, încet, au devenit indiferenți față de propriile lor probleme. Ei nu s-au alarmat când sistemele lor s-au prăbușit, ci au acceptat mai degrabă această stare a universului ca pe un fapt al vieții. Ei credeau că programele lor erau perfecte în ei înșiși, senine și elegante, scopul lor fiind evident.

O, băiete, dacă ar ști cât de greșit au...

Era bine întârziat când și-au dat seama de greșelile lor și CEO-ul lor a strigat să-i aducă înapoi pe toți dezvoltatorii care și-au părăsit platforma și au plecat. Compania era Microsoft și eu, unul, eram convins că soarta lor fusese pecetluită și că încet, dar sigur, vor pieri din fruntea peisajului tehnologic.

Sunt atât de fericit că am greșit!

În ultimii câțiva ani, Microsoft a scos câțiva ași din mânecă. Da, au dat peste cap Skype (încă îi urăsc pentru asta), au eșuat cu smartphone-urile și aproape au reușit cu tabletele. Dar, au făcut și niște lucruri cu adevărat uimitoare. Renunțând la abordarea de tip imperiu închis, au deschis .NET, s-au alăturat Fundației Linux, au lansat SQL Server pentru Linux și au creat acest nou instrument minunat numit Visual Studio pentru Mac.

Așa este, un adevărat Microsoft IDE nu pentru Windows, ci pentru Mac. Imaginează-ți asta!

Visual Studio pentru Mac

Scrierea primei aplicații pentru Android și iOS încrucișate folosind C# pe Mac

Puteți utiliza Visual Studio pentru Mac pentru a crea aproape orice tip de aplicație. Poate fi iOS, tvOS, Android, Mac, .NET Core sau chiar ASP.NET. Deoarece toți copiii cool scriu acum aplicații mobile, să vedem ce este nevoie în Visual Studio pentru Mac pentru a crea o aplicație C# care va rula pe Android și iOS.

Primul lucru pe care trebuie să-l faceți este să alegeți șablonul aplicației. Să începem cu o simplă „Aplicație cu vizualizare unică”.

Aplicație cu o singură vizualizare.

După completarea numelui pachetului și pornirea aplicației, Visual Studio va crea o soluție cu trei proiecte. Primul proiect va fi o bibliotecă partajată în care ar trebui să păstrați codul independent de platformă, iar celelalte două vor fi aplicații Android și iOS.

Noțiuni de bază.

Puteți utiliza meniul „Run” sau comenzile din bara de aplicații pentru a porni aplicația.

Bună lume, dă clic pe mine!

Înregistrare două clicuri.

Felicitări! Acum sunteți un dezvoltator iOS și Android, indiferent de faptul că nu ați scris niciodată o linie de cod Objective-C, Swift sau Java.

Cu toate acestea, nu am realizat prea multe încă cu aplicația noastră. Să facem lucrurile mai interesante și să încorporăm hărți și servicii de localizare.

Utilizarea hărților și a serviciilor de localizare

Rețineți că VS pentru Mac este încă în „Previzualizare” și nu există prea mult ajutor și documentație pe care o veți găsi despre utilizarea acestuia. Cel mai bun loc pentru referințe despre cum să faci lucrurile este încă documentația oficială Xamarin.

Visual Studio pentru Mac nu folosește aceeași soluție și structură de aplicație ca instrumentele Xamarin pe care este posibil să le fi văzut pe computer. În cele mai multe cazuri, va trebui să experimentați și să rezolvați câteva obstacole pentru ca exemplele lor să funcționeze. Să sperăm că Microsoft va rămâne la curent cu jocul lor și va oferi o colecție minunată de resurse MSDN odată ce versiunea finală a VS pentru Mac va fi lansată.

Se afișează locația curentă pe iOS

Accesarea resurselor dispozitivului mobil, cum ar fi locația curentă, necesită ca utilizatorii să acorde „manual” permisiuni aplicației dvs. pentru a utiliza aceste resurse. iOS folosește fișierul info.plist pentru a stoca aceste setări. VS pentru Mac oferă o interfață vizuală pentru editarea acestui fișier. Primul lucru pe care trebuie să-l facem este să adăugăm o valoare pentru setarea numită NSLocationWhenInUseUsageDescription .

Adăugarea de valoare pentru locație când se află în Descrierea utilizării.

Notă: VS va afișa un nume lung pentru „NSLocationWhenInUseUsageDescription” atunci când setați numele proprietății. Acest lucru este de așteptat și nu vă faceți griji pentru asta.

Aplicația noastră bootstrapped a fost creată cu un buton simplu care număra clicurile. Primul lucru pe care veți dori să-l faceți este să îl eliminați și să înlocuiți conținutul ecranului cu o hartă. Pentru a face acest lucru, căutați fișierul Main.storyboard în browserul de soluții și faceți dublu clic pe el pentru a-l deschide în editor.

Un storyboard este o reprezentare vizuală a interfeței de utilizator a unei aplicații, care arată ecrane de conținut și conexiunile dintre acele ecrane. Un storyboard este compus dintr-o secvență de scene, fiecare dintre acestea reprezentând un controler de vizualizare și vederile sale; Scenele sunt conectate prin obiecte segue, care reprezintă o tranziție între două controlere de vizualizare.

Storyboard-urile sunt introduse de Apple și adoptate și de Xamarin. Consultați documentația Apple sau documentația Xamarin pentru mai multe informații.

Eliminați butonul și adăugați o componentă Vizualizare hartă pe pagină.

Eliminați componenta Vizualizare hartă.

Asigurați-vă că denumiți corect componenta „mapView”.

Componenta de denumire Hartă View

Tot ce rămâne acum este să curățați fișierul ViewController.cs și să modificați metoda ViewDidLoad() pentru a se potrivi cu următoarele:

 using CoreLocation; public override void ViewDidLoad() { base.ViewDidLoad(); // Perform any additional setup after loading the view, typically from a nib. CLLocationManager locationManager = new CLLocationManager(); locationManager.RequestWhenInUseAuthorization(); mapView.ShowsUserLocation = true; }

Puteți folosi caracteristica „Remediere rapidă” pentru ca VS să adauge automat o referință la biblioteca CoreLocation sau o puteți adăuga manual.

După ce rulați aplicația iOS, ar trebui să vedeți solicitarea de a vă accesa locația. Odată ce permisiunea este acordată, harta dvs. se va încărca cu un punct albastru standard care arată unde vă aflați (sau unde pretindeți că vă aflați folosind simulatorul iOS :) ).

Permiteți utilizarea locației în aplicație.

Se afișează locația curentă pe Android

Din păcate, Google și Microsoft au decis să facă această sarcină simplă puțin mai complicată decât a fost cu iOS. Pentru a utiliza hărți în aplicația Android, va trebui să creați cheia API Google Maps și să o adăugați în fișierul AndroidManifest.xml .

Băieții Xamarin au creat un ghid destul de simplu pentru obținerea unei chei API Google Maps. Vă rugăm să urmați pașii din ghidul lor înainte de a continua. Când ați terminat, AndroidManifest.xml ar trebui să conțină o setare ca aceasta:

 <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR KEY" />

Acum sunteți gata să adăugați o hartă la aplicația dvs.

Lucrul grozav cu VS pentru Mac este că este alimentat de NuGet, la fel ca fratele său mai mare. Deoarece bibliotecile de gestionare a hărților nu sunt incluse în mod implicit, va trebui să instalați pachetul Xamarin.Forms.Maps .

Instalați Xamarin.Forms.Maps

Cu toate acestea, nu există nicio componentă „Vizualizare hartă” pe care să o puteți trage în „Activitate”. În schimb, adăugarea unei hărți pe ecran necesită modificarea manuală a fișierului Resources->layout->Main.axml. Puteți utiliza vizualizarea de designer pentru a șterge butonul creat anterior, dar apoi comutați la „Vizualizare cod” și adăugați următorul cod de fragment în LinearLayout :

 <fragment xmlns:andro android: android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.MapFragment" />

Ca și în cazul iOS, va trebui să configurați aplicația pentru a solicita permisiunile corespunzătoare. Pentru a face acest lucru, deschideți AndroidManifest.xml pentru editare și faceți clic pe butonul „Aplicație” din partea stângă jos a editorului. VS vă va arăta o interfață vizuală pentru setarea acestor valori. Există câteva dintre ele pe care va trebui să le activați, așa cum se arată mai jos.

Activarea permisiunilor.

Acum este timpul să scriem un cod real. Găsiți fișierul MainActivity.cs , deschideți-l pentru editare și efectuați următoarele modificări:

Adăugați referințe la spațiul de nume:

 using Android.Gms.Maps.Model; using Android.Gms.Maps; using Android.Locations; Make your MainActivity also a ILocationListener. public class MainActivity : Activity, ILocationListener Implement the ILocationListener methods within your MainActivity: public void OnProviderEnabled(string provider) {} public void OnProviderDisabled(string provider) {} public void OnStatusChanged(string provider, Availability status, Bundle extras) {} public void OnLocationChanged(Android.Locations.Location location) { LatLng latLng = new LatLng(location.Latitude, location.Longitude); CameraPosition.Builder builder = CameraPosition.InvokeBuilder(); builder.Target(latLng); builder.Zoom(15); builder.Bearing(155); builder.Tilt(10); CameraPosition cameraPosition = builder.Build(); CameraUpdate cameraUpdate = CameraUpdateFactory.NewCameraPosition(cameraPosition); MapFragment mapFrag = (MapFragment)FragmentManager.FindFragmentById(Resource.Id.map); GoogleMap map = mapFrag.Map; if (map != null) { map.MoveCamera(cameraUpdate); } }

Adăugați următoarele două variabile ca variabile la nivel de clasă:

 LocationManager locMgr; string locationProvider;

Și curățați metoda OnCreate() pentru a arăta astfel:

 protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.Main); locMgr = GetSystemService(LocationService) as LocationManager; Criteria locationCriteria = new Criteria(); locationCriteria.Accuracy = Accuracy.Coarse; locationCriteria.PowerRequirement = Power.Medium; locationProvider = locMgr.GetBestProvider(locationCriteria, true); locMgr.RequestLocationUpdates(locationProvider, 2000, 1, this); }

Apelând GetSystemService din cadrul OnCreate() , MainActivity va fi activat ca ILocationListener și, prin urmare, va putea gestiona toate evenimentele enumerate mai sus.

Rulați aplicația Android și ar trebui să obțineți harta poziționată în locația dvs., similar cu imaginea următoare.

Harta poziționată în Sarajevo.

Utilizarea bibliotecilor partajate pentru iOS și Android

Una dintre cele mai mari caracteristici ale VS pentru Mac este posibilitatea de a avea cod partajat între aplicațiile iOS și Android. În mod ideal, am putea avea toată logica de afaceri a aplicației într-o bibliotecă partajată, limitând orice cod specific iOS și Android la a face parte din interfața de utilizare.

Să creăm o clasă partajată care va efectua asincron o solicitare HTTP și va afișa conținutul într-o consolă de depanare.

Creați un nou fișier de clasă în biblioteca dvs. partajată, numit RestClient.cs cu următorul cod:

(Asigurați-vă că utilizați spațiul de nume corect din proiectul dvs.)

 using System; using System.Net; namespace testshared { public delegate void callback(string responseText); class ReqState { public ReqState(HttpWebRequest req, callback cb) { request = req; callback = cb; } public HttpWebRequest request { get; set; } public callback callback; } public class RestClient { public RestClient() {} public void FetchPage(string url, callback cb) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.BeginGetResponse(new AsyncCallback(FinishWebRequest), new ReqState(request, cb)); } private void FinishWebRequest(IAsyncResult result) { ReqState reqState = (result.AsyncState as ReqState); HttpWebResponse response = reqState.request.EndGetResponse(result) as HttpWebResponse; using (var reader = new System.IO.StreamReader(response.GetResponseStream())) { string responseText = reader.ReadToEnd(); reqState.callback(responseText); } } } }

Utilizarea Bibliotecii pe iOS

Modificați fișierul ViewController.cs din proiectul iOS pentru a se potrivi cu următorul cod:

(Asigurați-vă că utilizați spațiul de nume corect din proiectul dvs.)

 using System; using UIKit; using System.Diagnostics; namespace testshared.iOS { public partial class ViewController : UIViewController { RestClient rest = new RestClient(); public ViewController(IntPtr handle) : base(handle) {} public override void ViewDidLoad() { base.ViewDidLoad(); // Perform any additional setup after loading the view, typically from a nib. Button.AccessibilityIdentifier = "myButton"; Button.TouchUpInside += delegate { Button.SetTitle("Loading...", UIControlState.Normal); rest.FetchPage("http://www.google.com", doneCallback); }; } public void doneCallback(string content) { InvokeOnMainThread(() => { Debug.Write(content); Button.SetTitle("All Done", UIControlState.Normal); }); } public override void DidReceiveMemoryWarning() { base.DidReceiveMemoryWarning(); // Release any cached data, images, etc that aren't in use. } } }

Rulați aplicația iOS, faceți clic pe butonul și verificați fila „Ieșire aplicație” din Visual Studio. Ar trebui să afișeze ceva de genul:

Fila Ieșire aplicație.

Utilizarea Bibliotecii pe Android

Modificările necesare pe o aplicație Android sunt foarte asemănătoare cu cele necesare pe iOS. Modificați fișierul MainActivity.cs pentru a se potrivi cu următoarele:

(Asigurați-vă că utilizați spațiul de nume corect din proiectul dvs.)

 using Android.App; using Android.Widget; using Android.OS; namespace testshared.Droid { [Activity(Label = "testshared", MainLauncher = true, Icon = "@mipmap/icon")] public class MainActivity : Activity { RestClient rest = new RestClient(); protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.Main); // Get our button from the layout resource, // and attach an event to it Button button = FindViewById<Button>(Resource.Id.myButton); button.Click += delegate { button.Text = $"Loading..."; rest.FetchPage("http://www.google.com", doneCallback); }; } public void doneCallback(string content) { RunOnUiThread(() => { Button button = FindViewById<Button>(Resource.Id.myButton); button.Text = "All done"; System.Diagnostics.Debug.WriteLine(content); }); } } }

Notă: Arhitectura de sistem a ambelor platforme, Android și iOS, necesită ca toată interacțiunea UI să aibă loc pe firul principal al aplicației. Aceasta înseamnă că orice modificare a elementelor UI ar trebui să aibă loc și din firul principal. Aici RunOnUiThread și InvokeOnMainThread . Deoarece cererile HTTP au fost executate într-un fir separat și doneCallback() a fost apelat în afara firului principal, a trebuit să folosim aceste metode pentru a putea accesa butoanele și a schimba eticheta.

Dezvoltatorii C# preiau Android și iOS

Visual Studio pentru Mac mai are de rezolvat câteva riduri, dar de la prima vedere, sunt foarte încântat de viitorul său. Nevoia de aplicații mobile crește în fiecare zi și, cu Visual Studio pentru Mac, Microsoft a permis și mai mult unei armate de dezvoltatori C# extraordinari să satisfacă această nevoie.

Swift și Java/JVM au acum un nou concurent și foarte puternic în lupta pentru mediile noastre de dezvoltare a dispozitivelor mobile.
Înrudit: .NET Core - Going Wild și Open Source. Microsoft, ce ți-a luat atât de mult?!
Înrudit: Limbajul Dart: Când Java și C# nu sunt suficient de clare