Xamarin

mobile-developmentcross-platformC#.NETMicrosoftend-of-support

Mobile Platform

Xamarin

Overview

Xamarin was a .NET-based cross-platform mobile development framework acquired by Microsoft. It enabled developers to build native applications for iOS, Android, and Windows using C#. Originated from the Mono project in 2011 and acquired by Microsoft in 2016, Xamarin reached end of support on May 1, 2024, with migration to .NET MAUI being recommended as the successor. It allowed building native apps for each platform from a single C# codebase with full access to platform-specific APIs.

Details

Xamarin was a comprehensive framework for developing cross-platform mobile applications using .NET and C#. It consisted of three main components: Xamarin.iOS, Xamarin.Android, and Xamarin.Forms, each supporting different approaches to cross-platform development.

Xamarin.iOS and Xamarin.Android wrapped each platform's native APIs in C#, providing complete access to platform-specific features. While developers needed to design UI for each platform separately, they could share business logic and data access layers.

Xamarin.Forms provided a higher level of abstraction, generating UI for multiple platforms from a single XAML-based UI code. This significantly improved code sharing and reduced development time.

The development environment utilized Visual Studio and Visual Studio for Mac, providing integrated debugging, profiling, and designer tools. Cloud services like Xamarin Test Cloud and Xamarin Insights were also available.

Currently, Xamarin support has ended, and .NET MAUI is recommended for new projects. Existing Xamarin applications require migration to .NET MAUI.

Pros and Cons

Pros (Past Tense)

  • C# and Managed Code: Leveraged existing .NET developer skills with benefits of type safety and memory management
  • Native Performance: Achieved high performance through native compilation
  • Full Platform API Access: Complete access to all platform APIs without limitations
  • Code Sharing: Shared business logic, data layers, and some UI code, improving development efficiency
  • Visual Studio Integration: Productive development environment with powerful IDE support
  • Large Ecosystem: Leveraged rich ecosystem of NuGet packages and .NET libraries
  • Enterprise Ready: Robust features suitable for large-scale application development
  • Microsoft Support: Official support and continuous improvements from Microsoft

Cons

  • End of Support: Support ended on May 1, 2024, cannot be used for new development
  • App Size: Tended to have larger app sizes due to runtime inclusion
  • Learning Curve: Required understanding of Xamarin-specific concepts in addition to platform-specific knowledge
  • UI Customization Limits: Xamarin.Forms had limitations for advanced UI customization
  • Third-Party Libraries: Creating bindings for native libraries was complex
  • Performance Overhead: Inferior to native apps in some scenarios
  • Designer Tool Limitations: XAML designer functionality was limited

Reference Pages

Code Examples

Basic Xamarin.Forms Project Structure (Legacy)

// App.xaml.cs - Application entry point
using Xamarin.Forms;

namespace MyXamarinApp
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new NavigationPage(new MainPage());
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

Xamarin.Forms XAML Page (Legacy)

<!-- MainPage.xaml -->
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyXamarinApp.MainPage"
             Title="Home">
    
    <StackLayout Padding="20">
        <Label Text="Welcome to Xamarin Application!"
               FontSize="Large"
               HorizontalOptions="Center" />
        
        <Entry x:Name="nameEntry"
               Placeholder="Enter your name"
               Margin="0,20,0,0" />
        
        <Button Text="Submit"
                Clicked="OnSubmitClicked"
                BackgroundColor="#2196F3"
                TextColor="White"
                Margin="0,10,0,0" />
        
        <ListView x:Name="itemsList"
                  Margin="0,20,0,0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding Name}"
                              Detail="{Binding Description}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

Code Behind (Legacy)

// MainPage.xaml.cs
using System;
using System.Collections.ObjectModel;
using Xamarin.Forms;

namespace MyXamarinApp
{
    public partial class MainPage : ContentPage
    {
        private ObservableCollection<Item> items;

        public MainPage()
        {
            InitializeComponent();
            
            items = new ObservableCollection<Item>();
            itemsList.ItemsSource = items;
        }

        private async void OnSubmitClicked(object sender, EventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(nameEntry.Text))
            {
                await DisplayAlert("Greeting", $"Hello, {nameEntry.Text}!", "OK");
                
                items.Add(new Item
                {
                    Name = nameEntry.Text,
                    Description = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")
                });
                
                nameEntry.Text = string.Empty;
            }
        }
    }

    public class Item
    {
        public string Name { get; set; }
        public string Description { get; set; }
    }
}

Platform-Specific Code (Legacy)

// Platform-specific implementation using DependencyService
// IDeviceService.cs - Shared interface
public interface IDeviceService
{
    string GetDeviceId();
    void ShowToast(string message);
}

// iOS Implementation - iOS/DeviceService.cs
[assembly: Dependency(typeof(MyXamarinApp.iOS.DeviceService))]
namespace MyXamarinApp.iOS
{
    public class DeviceService : IDeviceService
    {
        public string GetDeviceId()
        {
            return UIDevice.CurrentDevice.IdentifierForVendor.ToString();
        }

        public void ShowToast(string message)
        {
            var alert = UIAlertController.Create(null, message, 
                UIAlertControllerStyle.Alert);
            
            UIApplication.SharedApplication.KeyWindow.RootViewController
                .PresentViewController(alert, true, null);
            
            NSTimer.CreateScheduledTimer(2.0, (timer) =>
            {
                alert.DismissViewController(true, null);
            });
        }
    }
}

// Android Implementation - Android/DeviceService.cs
[assembly: Dependency(typeof(MyXamarinApp.Droid.DeviceService))]
namespace MyXamarinApp.Droid
{
    public class DeviceService : IDeviceService
    {
        public string GetDeviceId()
        {
            return Android.Provider.Settings.Secure.GetString(
                Android.App.Application.Context.ContentResolver,
                Android.Provider.Settings.Secure.AndroidId);
        }

        public void ShowToast(string message)
        {
            Toast.MakeText(Android.App.Application.Context, 
                message, ToastLength.Short).Show();
        }
    }
}

// Usage example
var deviceService = DependencyService.Get<IDeviceService>();
string deviceId = deviceService.GetDeviceId();
deviceService.ShowToast("Device ID: " + deviceId);

Migration to .NET MAUI Example

// .NET MAUI equivalent code
// MauiProgram.cs - New entry point
using Microsoft.Extensions.Logging;
using Microsoft.Maui.Controls.Hosting;
using Microsoft.Maui.Hosting;

namespace MyMauiApp
{
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });

#if DEBUG
            builder.Logging.AddDebug();
#endif
            // Register services
            builder.Services.AddSingleton<IDeviceService, DeviceService>();

            return builder.Build();
        }
    }
}

// MainPage.xaml - .NET MAUI version
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyMauiApp.MainPage"
             Title="Home">
    
    <VerticalStackLayout Padding="20" Spacing="10">
        <Label Text="Welcome to .NET MAUI Application!"
               FontSize="Large"
               HorizontalOptions="Center" />
        
        <Entry x:Name="nameEntry"
               Placeholder="Enter your name" />
        
        <Button Text="Submit"
                Clicked="OnSubmitClicked"
                BackgroundColor="#2196F3"
                TextColor="White" />
        
        <CollectionView x:Name="itemsCollection">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Frame Padding="10" Margin="5">
                        <VerticalStackLayout>
                            <Label Text="{Binding Name}" 
                                   FontAttributes="Bold" />
                            <Label Text="{Binding Description}" 
                                   FontSize="Small" />
                        </VerticalStackLayout>
                    </Frame>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </VerticalStackLayout>
</ContentPage>

Migration Notes

// Important: Key changes from Xamarin.Forms to .NET MAUI
// 1. Namespace changes:
//    Xamarin.Forms.* → Microsoft.Maui.*
// 2. DependencyService → Dependency Injection (DI)
// 3. Device.BeginInvokeOnMainThread → MainThread.BeginInvokeOnMainThread
// 4. MessagingCenter → WeakReferenceMessenger
// 5. Unified project structure (multi-targeting)
// 6. New handler architecture

// Migration tool usage example:
// dotnet tool install -g upgrade-assistant
// upgrade-assistant upgrade <project-path>