C# MAUI平台特定代码方法 C#如何调用Android和iOS原生API

8次阅读

不需要。MAui 6.0起已弃用microsoft.Maui.Controls.Handlers.Compatibility,应使用Microsoft.Maui.Platform(android)和Microsoft.Maui.Platforms.ios(iOS)中的扩展方法或自定义处理程序,在Platforms/Android或Platforms/iOS目录下编写平台专属代码,并通过依赖注入或DeviceInfo/MainThread等跨平台抽象桥接。

C# MAUI平台特定代码方法 C#如何调用Android和iOS原生API

Platform-agnostic调用原生API必须走Microsoft.Maui.Controls.Handlers.Compatibility吗?

不需要。MAUI 从 6.0 开始已弃用兼容层,所有平台特定代码应通过 Microsoft.Maui.Platform(Android)和 Microsoft.Maui.Platforms.iOS(iOS)中的扩展方法或自定义处理程序实现。直接引用旧兼容命名空间会导致编译失败或运行时异常。

正确路径是:在 Platforms/AndroidPlatforms/iOS 目录下编写平台专属代码,利用 MAUI 的依赖注入机制或 DeviceInfo / MainThread 等跨平台抽象做桥接。

Android端调用ActivityContext常见报错和绕过方式

在 Android 平台代码中,直接访问 CurrentActivityapplicationContext 时容易遇到 NULLReferenceException——尤其在启动早期(如 App.xaml.cs 构造函数中)或后台线程里。

  • MauiApplication.Current?.windows.FirstOrDefault()?.Handler?.MauiContext?.Context 是较稳妥的 Context 获取路径,但需确保窗口已初始化
  • 若需在 Activity 生命周期回调中操作(如 OnResume),应继承 Microsoft.Maui.MauiApplication 并重写 OnCreate,再通过 RegisterActivityLifecycleCallbacks 注册监听
  • 避免在非 UI 线程直接调用 Toast.MakeText 等 UI 方法;改用 MainThread.InvokeOnMainThreadAsync 包裹

iOS端访问UIApplicationUIViewController的时机陷阱

iOS 上最常踩的坑是过早访问 UIApplication.SharedApplication.KeyWindow?.RootViewController —— MAUI 启动完成前该值为 null,且 iOS 15+ 后 KeyWindow 已被弃用。

  • 推荐使用 MauiUIApplicationDelegate.Window(在 Platforms/iOS/AppDelegate.cs 中可安全获取)作为根视图控制器来源
  • 若需在页面级调用原生 API(如弹出 UIAlertController),应在 OnAppearing 中延迟一小段(await Task.Delay(1))再获取 UIViewController,或通过 IVisualElementRendererViewController 属性取当前页控制器
  • 注意:iOS 所有 UI 操作必须在主线程DispatchQueue.MainQueue.DispatchSync 是必需的,不能省略

如何安全暴露原生能力给共享项目(C#逻辑层)

不能让共享项目直接引用 Android.App.ActivityUIKit.UIViewController,否则破坏平台隔离。标准做法是定义接口 + 平台实现 + DI 注册。

例如定义 IFilePickerService 接口,然后:

  • Android 实现类中用 ActivityResultLauncher 启动文件选择器,并通过 TaskCompletionSource 封装异步方法
  • iOS 实现类中用 UIDocumentPickerViewController,在 DidPickDocumentAtUrls 回调中设置 TCS.SetResult
  • MauiProgram.CreateMauiApp() 中注册:builder.Services.AddSingleton()(平台项目中条件注册)

关键点:所有原生类型(IntentNSUrl)必须在平台实现内部转换为跨平台模型(如 String 路径或 stream),不泄露任何平台特有类型到共享层。

text=ZqhQzanResources