Platform Integration & Handlers

7 questions found

Use conditional compilation with platform symbols (ANDROID, IOS, MACCATALYST, WINDOWS) inside shared code, or split logic into files under Platforms/ that compile only for their target. Conditional compilation is fine for small snippets; partial classes/interfaces are cleaner for larger differences.
string GetPlatformName()
{
#if ANDROID
    return "Android";
#elif IOS
    return "iOS";
#else
    return "Other";
#endif
}
Real-world example A quick analytics tag reports the OS name using a small #if block rather than a whole new abstraction.

Common follow-ups: When prefer partial classes over #if? | What symbols are available?

Multi-targeting Conditional Compilation Project Structure
The former Xamarin.Essentials APIs are built into MAUI (Microsoft.Maui.Devices, .Storage, .Media, etc.). They give cross-platform access to device features—Geolocation, Connectivity, Preferences, SecureStorage, Battery, Sensors, Clipboard, Sharing—behind a unified API so you don't call native code directly for common tasks.
var location = await Geolocation.Default.GetLocationAsync();
bool online = Connectivity.Current.NetworkAccess == NetworkAccess.Internet;
Real-world example An app checks connectivity and reads GPS with two lines instead of separate Android and iOS location APIs.

Common follow-ups: Do Essentials need permissions? | Which namespace holds device APIs?

Device Features Permissions Platform Integration
Use PropertyMapper customization scoped by checking the view instance, or subclass the handler for that control and register it. AppendToMapping adds behavior after the default; ModifyMapping replaces a specific property's mapping. Guard native calls with platform #if.
#if IOS
Microsoft.Maui.Handlers.SwitchHandler.Mapper.AppendToMapping(
    "Tint", (h, v) => h.PlatformView.OnTintColor =
        UIKit.UIColor.SystemGreenColor);
#endif
Real-world example Product design wants iOS switches tinted brand-green; a single iOS-guarded mapper achieves it without touching Android.

Common follow-ups: AppendToMapping vs ModifyMapping? | How do you scope to one control instance?

Handlers Property Mapper Custom Controls
Through the control's Handler.PlatformView, cast to the native type for the current platform (guarded by #if). This lets you call native APIs the cross-platform surface doesn't expose. Access it after the handler is created (e.g., in HandlerChanged).
myEntry.HandlerChanged += (s, e) =>
{
#if ANDROID
    var native = (Android.Widget.EditText)myEntry.Handler.PlatformView;
    native.SetSelectAllOnFocus(true);
#endif
};
Real-world example A form selects all text when an Entry gains focus on Android by reaching the native EditText via the handler.

Common follow-ups: When is PlatformView available? | Why guard with #if?

Handlers Platform Integration Controls & Views
Use the Permissions API: check the status with CheckStatusAsync and request with RequestAsync for a permission type (e.g., LocationWhenInUse, Camera). Declare the permission in each platform manifest (AndroidManifest.xml, Info.plist). Handle Denied and Disabled states gracefully.
var status = await Permissions.CheckStatusAsync<Permissions.Camera>();
if (status != PermissionStatus.Granted)
    status = await Permissions.RequestAsync<Permissions.Camera>();
Real-world example Before opening the camera, the app checks and requests camera permission, showing a rationale if the user previously denied it.

Common follow-ups: Where do you declare permissions per platform? | How do you handle a denied result?

Permissions Device Features Platform Integration
Define an interface (IMyControl : IView), a cross-platform control implementing it, and a partial handler with platform-specific CreatePlatformView plus a PropertyMapper mapping your properties to native calls. Register the handler in MauiProgram via ConfigureMauiHandlers.
public partial class VideoHandler : ViewHandler<IVideo, PlatformVideoView>
{
    public static IPropertyMapper<IVideo, VideoHandler> Mapper =
        new PropertyMapper<IVideo, VideoHandler>(ViewMapper)
        { [nameof(IVideo.Source)] = MapSource };

    protected override PlatformVideoView CreatePlatformView() => new(Context);
}
Real-world example A team wraps each platform's native video player in one cross-platform Video control with a custom handler.

Common follow-ups: How do you register a custom handler? | What is CreatePlatformView?

Handlers Custom Controls Platform Integration
Define a shared interface, implement it per platform (Platforms folder partial classes), and register in DI. This keeps native calls isolated and testable via the interface, unlike scattering #if throughout business logic. It's the recommended pattern for features like biometric auth or platform-specific storage.
public interface IBiometricAuth { Task<bool> AuthenticateAsync(string reason); }
// Platforms/iOS/BiometricAuth.cs -> LAContext
// Platforms/Android/BiometricAuth.cs -> BiometricPrompt
builder.Services.AddSingleton<IBiometricAuth, BiometricAuth>();
Real-world example Face ID and Android BiometricPrompt sit behind one IBiometricAuth so the login view model calls a single method.

Common follow-ups: Why an interface over #if? | How does this help testing?

Platform Integration Dependency Injection Custom Controls