Jak zrobić aplikację na Androida i iOS w C# na Macu?

Opublikowany: 2022-03-11

Dawno, dawno temu była firma, która miała wszystkie najlepsze narzędzia, a pisanie oprogramowania na ich platformę było niesamowite. Ale powoli stali się obojętni na własne problemy. Nie przestraszyli się, gdy ich systemy uległy awarii, ale raczej zaakceptowali ten stan wszechświata jako fakt życia. Wierzyli, że ich programy są w sobie doskonałe, spokojne i eleganckie, a ich cel jest oczywisty.

O rany, gdyby tylko wiedzieli, jak bardzo się mylili…

Było to bardzo spóźnione, kiedy zdali sobie sprawę ze swoich błędów, a ich dyrektor generalny płakał, aby sprowadzić wszystkich programistów, którzy opuścili ich platformę i odpłynęli. Firmą był Microsoft i ja na przykład byłem przekonany, że ich los został przesądzony i że powoli, ale pewnie znikną z czołówki technologicznego krajobrazu.

Tak się cieszę, że się myliłem!

W ciągu ostatnich kilku lat Microsoft wyciągnął z rękawa kilka asów. Tak, popsuli Skype (wciąż ich za to nienawidzę), zawiedli ze smartfonami i prawie odnieśli sukces z tabletami. Ale zrobili też kilka naprawdę niesamowitych rzeczy. Rezygnując z podejścia do zamkniętego imperium, udostępnili platformę .NET typu open source, dołączyli do Linux Foundation, wydali SQL Server dla systemu Linux i stworzyli to wspaniałe nowe narzędzie o nazwie Visual Studio dla komputerów Mac.

Zgadza się, prawdziwy Microsoft IDE nie dla Windowsa, ale dla Maca. Wyobraź sobie, że!

Visual Studio dla komputerów Mac

Pisanie pierwszej aplikacji międzyplatformowej na Androida i iOS przy użyciu C# na Macu

Możesz użyć Visual Studio dla komputerów Mac, aby utworzyć prawie każdy typ aplikacji. Może to być iOS, tvOS, Android, Mac, .NET Core, a nawet ASP.NET. Ponieważ wszystkie fajne dzieciaki piszą teraz aplikacje mobilne, zobaczmy, czego potrzeba w Visual Studio dla komputerów Mac, aby utworzyć aplikację C#, która będzie działać w systemach Android i iOS.

Pierwszą rzeczą, którą musisz zrobić, to wybrać szablon aplikacji. Zacznijmy od prostej aplikacji „Single View”.

Aplikacja z pojedynczym widokiem.

Po wypełnieniu nazwy pakietu i uruchomieniu aplikacji Visual Studio utworzy rozwiązanie z trzema projektami. Pierwszy projekt będzie współdzieloną biblioteką, w której powinieneś przechowywać kod niezależny od platformy, a pozostałe dwa będą aplikacjami na Androida i iOS.

Pierwsze kroki.

Aby uruchomić aplikację, możesz użyć menu „Uruchom” lub poleceń na pasku aplikacji.

Witaj świecie, kliknij mnie!

Rejestrowanie dwóch kliknięć.

Gratulacje! Jesteś teraz programistą iOS i Android, niezależnie od tego, że nigdy nie napisałeś linii kodu Objective-C, Swift lub Java.

Jednak tak naprawdę nie osiągnęliśmy jeszcze wiele z naszą aplikacją. Uczyńmy rzeczy ciekawszymi i uwzględnijmy mapy i usługi lokalizacyjne.

Korzystanie z map i usług lokalizacyjnych

Pamiętaj, że VS dla komputerów Mac jest nadal w „Podglądzie” i nie ma zbyt wiele pomocy i dokumentacji, które można znaleźć na temat korzystania z niego. Najlepszym miejscem na odniesienia do tego, jak to zrobić, jest nadal oficjalna dokumentacja platformy Xamarin.

Visual Studio dla komputerów Mac nie używa tej samej struktury rozwiązania i aplikacji, co narzędzia Xamarin, które mogły być widoczne na komputerze PC. W większości przypadków będziesz musiał poeksperymentować i obejść kilka przeszkód, aby ich przykłady zadziałały. Miejmy nadzieję, że Microsoft pozostanie na szczycie swojej gry i zapewni niesamowitą kolekcję zasobów MSDN po wydaniu ostatecznej wersji VS dla komputerów Mac.

Pokazywanie aktualnej lokalizacji na iOS

Aby uzyskać dostęp do zasobów urządzenia mobilnego, takich jak bieżąca lokalizacja, użytkownicy muszą „ręcznie” przyznać Twojej aplikacji uprawnienia do korzystania z tych zasobów. iOS używa pliku info.plist do przechowywania tych ustawień. VS dla komputerów Mac zapewnia wizualny interfejs do edycji tego pliku. Pierwszą rzeczą, którą musimy zrobić, to dodać wartość dla ustawienia o nazwie NSLocationWhenInUseUsageDescription .

Dodanie wartości dla lokalizacji w opisie użycia.

Uwaga: VS wyświetli długą nazwę dla "NSLocationWhenInUseUsageDescription" podczas ustawiania nazwy właściwości. Jest to oczekiwane i nie martw się tym.

Nasza aplikacja do ładowania początkowego została stworzona za pomocą prostego przycisku, który liczył kliknięcia. Pierwszą rzeczą, którą będziesz chciał zrobić, to usunąć go i zastąpić zawartość ekranu mapą. W tym celu poszukaj pliku Main.storyboard w przeglądarce rozwiązań i kliknij go dwukrotnie, aby otworzyć go w edytorze.

Scenorys to wizualna reprezentacja interfejsu użytkownika aplikacji, pokazująca ekrany treści i połączenia między tymi ekranami. Scenorys składa się z sekwencji scen, z których każda reprezentuje kontroler widoku i jego widoki; sceny są połączone obiektami segue, które reprezentują przejście między dwoma kontrolerami widoku.

Scenorysy są wprowadzane przez Apple i przyjmowane również przez Xamarin. Aby uzyskać więcej informacji, zapoznaj się z dokumentacją Apple lub dokumentacją Xamarin.

Usuń przycisk i dodaj do strony komponent Widok mapy.

Usuń komponent widoku mapy.

Upewnij się, że nazwałeś poprawnie komponent „mapView”.

Nazywanie komponentu widoku mapy

Teraz pozostało tylko wyczyścić plik ViewController.cs i zmodyfikować ViewDidLoad() tak, aby odpowiadała następującym:

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

Możesz użyć funkcji „Szybka naprawa”, aby VS automatycznie dodał odwołanie do biblioteki CoreLocation lub możesz dodać ją ręcznie.

Po uruchomieniu aplikacji na iOS powinna pojawić się prośba o dostęp do Twojej lokalizacji. Gdy zezwolenie zostanie udzielone, twoja mapa załaduje się standardową niebieską kropką pokazującą, gdzie jesteś (lub gdzie udajesz, że jesteś, używając symulatora iOS :) ).

Zezwalaj na używanie lokalizacji w aplikacji.

Pokazywanie aktualnej lokalizacji na Androidzie

Niestety Google i Microsoft postanowili nieco bardziej skomplikować to proste zadanie niż miało to miejsce w przypadku iOS. Aby korzystać z map w aplikacji na Androida, musisz utworzyć klucz Google Maps API i dodać go do pliku AndroidManifest.xml .

Chłopaki z Xamarin stworzyli całkiem prosty przewodnik, jak uzyskać klucz API Map Google. Przed kontynuowaniem postępuj zgodnie z instrukcjami zawartymi w ich przewodniku. Gdy skończysz, plik AndroidManifest.xml powinien zawierać takie ustawienie:

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

Możesz teraz dodać mapę do swojej aplikacji.

Wspaniałą rzeczą w VS dla komputerów Mac jest to, że jest zasilany przez NuGet, podobnie jak jego starszy brat. Ponieważ biblioteki obsługi map nie są domyślnie dołączone, należy zainstalować pakiet Xamarin.Forms.Maps .

Zainstaluj Xamarin.Forms.Maps

Jednak nie ma komponentu „Widok mapy”, który można po prostu przeciągnąć do swojej „Aktywności”. Zamiast tego dodanie mapy do ekranu wymaga ręcznej zmiany pliku Resources->layout->Main.axml. Możesz użyć widoku projektanta, aby usunąć utworzony wcześniej przycisk, ale następnie przełącz się na „Widok kodu” i dodaj następujący kod fragmentu w swoim LinearLayout :

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

Podobnie jak w przypadku iOS, musisz skonfigurować swoją aplikację, aby prosiła o odpowiednie uprawnienia. Aby to zrobić, otwórz AndroidManifest.xml do edycji i kliknij przycisk „Aplikacja” w lewym dolnym rogu edytora. VS pokaże wizualny interfejs do ustawiania tych wartości. Jest kilka z nich, które musisz włączyć, jak pokazano poniżej.

Włączanie uprawnień.

Teraz nadszedł czas na napisanie prawdziwego kodu. Znajdź plik MainActivity.cs , otwórz go do edycji i wprowadź następujące zmiany:

Dodaj odniesienia do przestrzeni nazw:

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

Dodaj następujące dwie zmienne jako zmienne na poziomie klasy:

 LocationManager locMgr; string locationProvider;

I wyczyść metodę OnCreate() , aby wyglądała tak:

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

Wywołując GetSystemService z poziomu metody OnCreate() , MainActivity zostanie aktywowany jako ILocationListener i dzięki temu będzie w stanie obsłużyć wszystkie zdarzenia wymienione powyżej.

Uruchom aplikację na Androida i powinieneś ustawić mapę w Twojej lokalizacji, podobnie jak na poniższym obrazku.

Mapa umieszczona w Sarajewie.

Korzystanie z bibliotek udostępnionych dla systemów iOS i Android

Jedną z największych funkcji VS dla komputerów Mac jest możliwość współdzielenia kodu między aplikacjami na iOS i Androida. Idealnie byłoby, gdybyśmy mogli mieć całą logikę biznesową aplikacji we wspólnej bibliotece, ograniczając dowolny kod dla systemów iOS i Android do bycia częścią interfejsu użytkownika.

Stwórzmy współdzieloną klasę, która asynchronicznie wykona żądanie HTTP i wyświetli zawartość w konsoli debugowania.

Utwórz nowy plik klasy w bibliotece współdzielonej o nazwie RestClient.cs z następującym kodem:

(Upewnij się, że używasz prawidłowej przestrzeni nazw ze swojego projektu)

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

Korzystanie z Biblioteki na iOS

Zmodyfikuj plik ViewController.cs w projekcie iOS, aby dopasować następujący kod:

(Upewnij się, że używasz prawidłowej przestrzeni nazw ze swojego projektu)

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

Uruchom aplikację na iOS, kliknij przycisk i sprawdź zakładkę „Wyjście aplikacji” w Visual Studio. Powinien wyświetlać coś takiego:

Zakładka Dane wyjściowe aplikacji.

Korzystanie z Biblioteki na Androidzie

Zmiany potrzebne w aplikacji na Androida są bardzo podobne do tych wymaganych w iOS. Zmodyfikuj plik MainActivity.cs , aby odpowiadał następującym:

(Upewnij się, że używasz prawidłowej przestrzeni nazw ze swojego projektu)

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

Uwaga: architektura systemu obu platform, Androida i iOS, wymaga, aby wszystkie interakcje interfejsu użytkownika miały miejsce w głównym wątku aplikacji. Oznacza to, że wszelkie zmiany elementów interfejsu użytkownika powinny również nastąpić z poziomu głównego wątku. W tym miejscu pojawiają się RunOnUiThread i InvokeOnMainThread . Ponieważ żądania HTTP były wykonywane w osobnym wątku, a doneCallback() było wywoływane poza głównym wątkiem, musieliśmy użyć tych metod, aby móc uzyskać dostęp do przycisków i zmienić etykietę.

Programiści C# przejmują Androida i iOS

Visual Studio dla komputerów Mac ma jeszcze kilka zmarszczek do naprawienia, ale od pierwszego spojrzenia jestem bardzo podekscytowany jego przyszłością. Zapotrzebowanie na aplikacje mobilne rośnie każdego dnia, a dzięki Visual Studio dla komputerów Mac firma Microsoft dodatkowo umożliwiła armii świetnych programistów C# zaspokojenie tej potrzeby.

Swift i Java/JVM mają teraz nowego i bardzo silnego konkurenta w walce o nasze środowiska programistyczne dla urządzeń mobilnych.
Powiązane: .NET Core — szaleństwo i Open Source. Microsoft, co zajęło ci tak długo?!
Powiązane: Język Dart: kiedy Java i C# nie są wystarczająco ostre