Как сделать приложение для Android и iOS на C# на Mac

Опубликовано: 2022-03-11

Жила-была компания, у которой были все лучшие инструменты, и писать программы для их платформы было круто. Но постепенно они стали безразличны к собственным проблемам. Они не встревожились, когда их системы вышли из строя, а скорее приняли это состояние вселенной как факт жизни. Они верили, что их программы совершенны сами по себе, безмятежны и элегантны, а их цель очевидна.

О боже, если бы они только знали, как они ошибались…

Давно пора было, когда они осознали свои ошибки, и их генеральный директор заплакал, чтобы вернуть всех разработчиков, которые покинули свою платформу и уплыли. Это была компания Microsoft , и я, например, был убежден, что их судьба решена и что они медленно, но верно исчезнут с передовой технологического ландшафта.

Я так счастлив, что ошибся!

За последние несколько лет Microsoft вытащила несколько тузов из рукавов. Да, они испортили Skype (до сих пор ненавижу их за это), провалили со смартфонами и почти преуспели с планшетами. Но, они также сделали некоторые действительно удивительные вещи. Отказавшись от подхода закрытой империи, они открыли исходный код .NET, присоединились к Linux Foundation, выпустили SQL Server для Linux и создали новый замечательный инструмент под названием Visual Studio для Mac.

Правильно, настоящая Microsoft IDE не для Windows, а для Mac. Представь это!

Visual Studio для Mac

Написание вашего первого кроссплатформенного приложения для Android и iOS с использованием C# на Mac

Вы можете использовать Visual Studio для Mac для создания приложений практически любого типа. Это может быть iOS, tvOS, Android, Mac, .NET Core или даже ASP.NET. Поскольку все крутые ребята сейчас пишут мобильные приложения, давайте посмотрим, что нужно в Visual Studio для Mac, чтобы создать приложение C#, которое будет работать на Android и iOS.

Первое, что вам нужно сделать, это выбрать шаблон приложения. Начнем с простого «приложения с одним просмотром».

Приложение с одним видом.

После ввода имени пакета и начальной загрузки приложения Visual Studio создаст решение с тремя проектами. Первый проект будет общей библиотекой, в которой вы должны хранить независимый от платформы код, а два других будут приложениями для Android и iOS.

Начиная.

Вы можете использовать меню «Выполнить» или команды на панели приложений, чтобы запустить приложение.

Привет, мир, щелкни меня!

Регистрация двух кликов.

Поздравляем! Теперь вы разработчик iOS и Android, несмотря на то, что вы никогда не писали ни строчки кода на Objective-C, Swift или Java.

Однако мы еще не многого добились с нашим приложением. Давайте сделаем вещи более интересными и включим карты и сервисы определения местоположения.

Использование карт и служб определения местоположения

Имейте в виду, что VS для Mac все еще находится в «Предварительной версии», и вы не найдете много помощи и документации по его использованию. Лучшим местом для ссылок о том, как что-то делать, по-прежнему является официальная документация Xamarin.

Visual Studio для Mac не использует то же решение и структуру приложения, что и инструменты Xamarin, которые вы могли видеть на ПК. В большинстве случаев вам нужно будет поэкспериментировать и обойти несколько препятствий, чтобы заставить их примеры работать. Будем надеяться, что Microsoft останется на высоте и предоставит потрясающую коллекцию ресурсов MSDN после выпуска финальной версии VS для Mac.

Отображение текущего местоположения на iOS

Доступ к ресурсам мобильного устройства, таким как текущее местоположение, требует, чтобы пользователи «вручную» предоставляли вашему приложению разрешения на использование этих ресурсов. iOS использует файл info.plist для хранения этих настроек. VS для Mac предоставляет визуальный интерфейс для редактирования этого файла. Первое, что нам нужно сделать, это добавить значение для параметра с именем NSLocationWhenInUseUsageDescription .

Добавление значения для местоположения при описании использования.

Примечание. VS покажет длинное имя для «NSLocationWhenInUseUsageDescription», когда вы установите имя свойства. Это ожидаемо, и не беспокойтесь об этом.

Наше загрузочное приложение было создано с помощью простой кнопки, которая считала клики. Первое, что вам нужно сделать, это удалить его и заменить содержимое экрана картой. Для этого найдите файл Main.storyboard в обозревателе решений и дважды щелкните его, чтобы открыть в редакторе.

Раскадровка — это визуальное представление пользовательского интерфейса приложения, показывающее экраны содержимого и связи между этими экранами. Раскадровка состоит из последовательности сцен, каждая из которых представляет контроллер представления и его представления; сцены связаны объектами перехода, которые представляют собой переход между двумя контроллерами представления.

Раскадровки представлены Apple и приняты Xamarin. Дополнительные сведения см. в документации Apple или документации Xamarin.

Удалите кнопку и добавьте на страницу компонент Map View.

Удалите компонент представления карты.

Убедитесь, что вы правильно назвали свой компонент «mapView».

Наименование компонента «Просмотр карты»

Теперь осталось очистить файл ViewController.cs и изменить метод ViewDidLoad() , чтобы он соответствовал следующему:

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

Вы можете использовать функцию «Быстрое исправление», чтобы VS автоматически добавлял ссылку на библиотеку CoreLocation, или вы можете добавить ее вручную.

После запуска приложения для iOS вы должны увидеть запрос на доступ к вашему местоположению. Как только разрешение будет предоставлено, ваша карта загрузится со стандартной синей точкой, показывающей, где вы находитесь (или где вы притворяетесь, используя симулятор iOS :)).

Разрешить использование местоположения в приложении.

Отображение текущего местоположения на Android

К сожалению, Google и Microsoft решили немного усложнить эту простую задачу, чем это было с iOS. Чтобы использовать карты в приложении для Android, вам необходимо создать ключ API Карт Google и добавить его в файл AndroidManifest.xml .

Ребята из Xamarin создали довольно простое руководство по получению ключа API Карт Google. Пожалуйста, следуйте инструкциям в их руководстве, прежде чем продолжить. Когда вы закончите, ваш AndroidManifest.xml должен содержать такой параметр:

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

Теперь вы готовы добавить карту в свое приложение.

Отличительной особенностью VS для Mac является то, что он работает на NuGet, как и его старший брат. Поскольку библиотеки обработки карт не включены по умолчанию, вам потребуется установить пакет Xamarin.Forms.Maps .

Установите Xamarin.Forms.Maps

Однако нет компонента «Просмотр карты», который можно было бы просто перетащить в «Активность». Вместо этого для добавления карты на экран требуется вручную изменить файл Resources->layout->Main.axml. Вы можете использовать представление конструктора, чтобы удалить кнопку, созданную ранее, но затем переключиться на «Просмотр кода» и добавить следующий код фрагмента в свой LinearLayout :

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

Как и в случае с iOS, вам нужно будет настроить приложение, чтобы оно запрашивало соответствующие разрешения. Для этого откройте AndroidManifest.xml для редактирования и нажмите кнопку «Приложение» в нижней левой части редактора. VS покажет вам визуальный интерфейс для установки этих значений. Есть несколько из них, которые вам нужно включить, как показано ниже.

Включение разрешений.

Пришло время написать настоящий код. Найдите файл MainActivity.cs , откройте его для редактирования и внесите следующие изменения:

Добавьте ссылки на пространство имен:

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

Добавьте следующие две переменные в качестве переменных уровня класса:

 LocationManager locMgr; string locationProvider;

И очистите метод OnCreate() , чтобы он выглядел так:

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

При вызове GetSystemService из метода OnCreate() ваша MainActivity будет активирована как ILocationListener и, таким образом, сможет обрабатывать все перечисленные выше события.

Запустите приложение для Android, и вы должны установить карту в соответствии с вашим местоположением, как показано на следующем изображении.

Карта расположена в Сараево.

Использование общих библиотек для iOS и Android

Одной из замечательных особенностей VS для Mac является возможность совместного использования кода приложениями iOS и Android. В идеале мы могли бы иметь всю бизнес-логику приложения в общей библиотеке, ограничивая любой специфичный для iOS и Android код частью пользовательского интерфейса.

Давайте создадим общий класс, который будет асинхронно выполнять HTTP-запрос и отображать содержимое в консоли отладки.

Создайте новый файл класса в вашей общей библиотеке с именем RestClient.cs со следующим кодом:

(Убедитесь, что вы используете правильное пространство имен из вашего проекта)

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

Использование библиотеки на iOS

Измените файл ViewController.cs в проекте iOS, чтобы он соответствовал следующему коду:

(Убедитесь, что вы используете правильное пространство имен из вашего проекта)

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

Запустите приложение для iOS, нажмите кнопку и проверьте вкладку «Вывод приложения» в Visual Studio. Он должен отображать что-то вроде этого:

Вкладка «Вывод приложения».

Использование библиотеки на Android

Изменения, необходимые для приложения Android, очень похожи на изменения, необходимые для iOS. Измените файл MainActivity.cs , чтобы он соответствовал следующему:

(Убедитесь, что вы используете правильное пространство имен из вашего проекта)

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

Примечание . Системная архитектура обеих платформ, Android и iOS, требует, чтобы все взаимодействия с пользовательским интерфейсом происходили в основном потоке приложения. Это означает, что любое изменение элементов пользовательского интерфейса также должно происходить из основного потока. Вот тут-то и появляются RunOnUiThread и InvokeOnMainThread . Поскольку HTTP-запросы выполнялись в отдельном потоке, а doneCallback() вызывался вне основного потока, нам пришлось использовать эти методы, чтобы получить доступ к кнопкам и изменить метку.

Разработчики C# захватывают Android и iOS

В Visual Studio для Mac еще есть несколько недостатков, которые нужно исправить, но с первого взгляда я очень взволнован ее будущим. Потребность в мобильных приложениях растет с каждым днем, и с выпуском Visual Studio для Mac корпорация Майкрософт позволила армии отличных разработчиков C# удовлетворить эту потребность.

У Swift и Java/JVM появился новый и очень сильный конкурент в борьбе за наши среды разработки для мобильных устройств.
Связанный: .NET Core — безумие и открытый исходный код. Майкрософт, что так долго?!
Связанный: Язык Dart: когда Java и C # недостаточно четкие