วิธีสร้างแอพ 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 for Mac เพื่อสร้างแอปพลิเคชันได้แทบทุกประเภท อาจเป็น iOS, tvOS, Android, Mac, .NET Core หรือแม้แต่ ASP.NET ในขณะที่เด็กๆ เจ๋งๆ ทุกคนกำลังเขียนแอปบนอุปกรณ์เคลื่อนที่ มาดูสิ่งที่ต้องใช้ใน Visual Studio สำหรับ Mac เพื่อสร้างแอปพลิเคชัน C# ที่จะทำงานบน Android และ iOS

สิ่งแรกที่คุณต้องทำคือเลือกเทมเพลตแอปพลิเคชัน เริ่มต้นด้วย "แอป Single View" ง่ายๆ

แอพมุมมองเดียว

หลังจากกรอกชื่อแพ็คเกจและบูตแอพของคุณแล้ว Visual Studio จะสร้างโซลูชันที่มีสามโปรเจ็กต์ โปรเจ็กต์แรกจะเป็นไลบรารีที่ใช้ร่วมกันซึ่งคุณควรเก็บโค้ดที่ไม่ขึ้นกับแพลตฟอร์ม และอีกสองรายการจะเป็นแอป Android และ iOS

เริ่มต้นใช้งาน

คุณสามารถใช้เมนู "เรียกใช้" หรือคำสั่งในแถบแอปพลิเคชัน เพื่อเริ่มแอปของคุณ

สวัสดีชาวโลก คลิกฉัน!

บันทึกการคลิกสองครั้ง

ยินดีด้วย! ตอนนี้คุณเป็นนักพัฒนา iOS และ Android ไม่ว่าคุณจะไม่เคยเขียนโค้ด Objective-C, Swift หรือ Java

แอปของเรายังไม่ประสบความสำเร็จมากนัก มาทำให้สิ่งต่าง ๆ น่าสนใจยิ่งขึ้นและรวมแผนที่และบริการตำแหน่งเข้าด้วยกัน

การใช้แผนที่และบริการตำแหน่ง

โปรดทราบว่า VS สำหรับ Mac ยังอยู่ใน "ดูตัวอย่าง" และไม่มีความช่วยเหลือและเอกสารประกอบการใช้งานมากนัก สถานที่ที่ดีที่สุดสำหรับการอ้างอิงเกี่ยวกับวิธีการทำสิ่งต่าง ๆ ยังคงเป็นเอกสาร Xamarin อย่างเป็นทางการ

Visual Studio For Mac ไม่ได้ใช้โซลูชันและโครงสร้างแอปพลิเคชันเดียวกันกับเครื่องมือ Xamarin ที่คุณอาจเคยเห็นบนพีซี ในกรณีส่วนใหญ่ คุณจะต้องทดลองและหลีกเลี่ยงอุปสรรคสองสามอย่างเพื่อให้ตัวอย่างของพวกเขาทำงาน หวังว่า Microsoft จะคงอยู่เหนือเกมของพวกเขาและมอบคอลเลกชันทรัพยากร MSDN ที่ยอดเยี่ยมเมื่อเวอร์ชันสุดท้ายของ VS สำหรับ Mac ออกวางจำหน่าย

กำลังแสดงตำแหน่งปัจจุบันบน iOS

การเข้าถึงทรัพยากรของอุปกรณ์เคลื่อนที่ เช่น ตำแหน่งปัจจุบัน กำหนดให้ผู้ใช้ต้อง "ให้สิทธิ์" กับแอปของคุณด้วยตนเองเพื่อใช้ทรัพยากรเหล่านั้น iOS ใช้ไฟล์ info.plist เพื่อจัดเก็บการตั้งค่าเหล่านี้ VS for Mac มีอินเทอร์เฟซแบบภาพสำหรับแก้ไขไฟล์นี้ สิ่งแรกที่เราต้องทำคือเพิ่มค่าสำหรับการตั้งค่าชื่อ NSLocationWhenInUseUsageDescription

การเพิ่มมูลค่าตำแหน่งเมื่ออยู่ในคำอธิบายการใช้งาน

หมายเหตุ: VS จะแสดงชื่อยาวสำหรับ “NSLocationWhenInUseUsageDescription” เมื่อคุณตั้งชื่อคุณสมบัติ นี้เป็นที่คาดหวังและไม่ต้องกังวลกับมัน

แอปพลิเคชันที่บูตสแตรปของเราสร้างขึ้นด้วยปุ่มง่ายๆ ที่นับการคลิก สิ่งแรกที่คุณจะต้องทำคือลบมันและแทนที่เนื้อหาบนหน้าจอด้วยแผนที่ ในการดำเนินการนี้ ให้มองหาไฟล์ Main.storyboard ในเบราว์เซอร์โซลูชันแล้วดับเบิลคลิกเพื่อเปิดไฟล์ในตัวแก้ไข

กระดานเรื่องราวคือการแสดงภาพอินเทอร์เฟซผู้ใช้ของแอปพลิเคชัน โดยแสดงหน้าจอของเนื้อหาและการเชื่อมต่อระหว่างหน้าจอเหล่านั้น กระดานเรื่องราวประกอบด้วยลำดับของฉาก ซึ่งแต่ละฉากแสดงถึงตัวควบคุมการดูและมุมมองของมัน ฉากเชื่อมต่อกันด้วยวัตถุต่อเนื่อง ซึ่งแสดงถึงการเปลี่ยนแปลงระหว่างตัวควบคุมมุมมองสองตัว

สตอรี่บอร์ดได้รับการแนะนำโดย Apple และ Xamarin นำไปใช้เช่นกัน โปรดดูเอกสารประกอบของ Apple หรือเอกสารประกอบ Xamarin สำหรับข้อมูลเพิ่มเติม

นำปุ่มออกและเพิ่มองค์ประกอบมุมมองแผนที่ในหน้า

ลบองค์ประกอบมุมมองแผนที่

ตรวจสอบให้แน่ใจว่าได้ตั้งชื่อองค์ประกอบ "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 คุณจะต้องสร้างคีย์ Google Maps API และเพิ่มลงในไฟล์ AndroidManifest.xml

พวก Xamarin ได้สร้างคู่มือที่ค่อนข้างตรงไปตรงมาเพื่อรับคีย์ Google Maps API โปรดทำตามขั้นตอนในคำแนะนำก่อนที่จะดำเนินการต่อ เมื่อเสร็จแล้ว 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 ให้เป็นส่วนหนึ่งของ UI

มาสร้างคลาสที่ใช้ร่วมกันที่จะทำการร้องขอ 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 กำหนดให้การโต้ตอบ UI ทั้งหมดเกิดขึ้นในเธรดแอปพลิเคชันหลัก ซึ่งหมายความว่าการเปลี่ยนแปลงองค์ประกอบ UI ควรเกิดขึ้นจากภายในเธรดหลักเช่นกัน นั่นคือที่มา RunOnUiThread และ InvokeOnMainThread เนื่องจากคำขอ HTTP ถูกดำเนินการในเธรดที่แยกจากกัน และ doneCallback() ถูกเรียกนอกเธรดหลัก เราจึงต้องใช้วิธีการเหล่านี้เพื่อให้สามารถเข้าถึงปุ่มและเปลี่ยนป้ายกำกับได้

นักพัฒนา C# กำลังยึดครอง Android และ iOS

Visual Studio for Mac ยังมีรอยย่นอีกเล็กน้อยที่ต้องแก้ไข แต่จากการดูครั้งแรก ฉันรู้สึกตื่นเต้นมากเกี่ยวกับอนาคตของ Visual Studio สำหรับ Mac ความต้องการแอปพลิเคชั่นมือถือเพิ่มขึ้นทุกวัน และด้วย Visual Studio สำหรับ Mac Microsoft ได้เปิดใช้งานกองทัพนักพัฒนา C# ที่ยอดเยี่ยมเพื่อเติมเต็มความต้องการนี้

ตอนนี้ Swift และ Java/JVM มีคู่แข่งรายใหม่และแข็งแกร่งมากในการต่อสู้เพื่อสภาพแวดล้อมการพัฒนาอุปกรณ์เคลื่อนที่ของเรา
ที่เกี่ยวข้อง: .NET Core - Going Wild และ Open Source Microsoft อะไรทำให้คุณใช้เวลานานขนาดนี้!
ที่เกี่ยวข้อง: The Dart Language: เมื่อ Java และ C # ไม่คมชัดเพียงพอ