调用平台代码

浏览示例。 浏览示例

在 .NET 多平台应用 UI (.NET MAUI) 不提供任何用于访问特定平台 API 的 API 的情况下,可以编写自己的代码来访问所需的平台 API。 这需要了解 Apple 的 iOS 和 MacCatalyst APIGoogle 的 Android APIMicrosoft 的 Windows 应用 SDK API

可以使用条件编译或使用分部类和分部方法从跨平台代码调用平台代码。

条件编译

可以使用条件编译以面向不同的平台,从跨平台代码调用平台代码。

以下示例显示了 DeviceOrientation 枚举,该枚举将用于指定设备的方向:

namespace InvokePlatformCodeDemos.Services
{
    public enum DeviceOrientation
    {
        Undefined,
        Landscape,
        Portrait
    }
}

检索设备的方向需要编写平台代码。 这可以通过编写使用条件编译以面向不同平台的方法来实现:

#if ANDROID
using Android.Content;
using Android.Views;
using Android.Runtime;
#elif IOS
using UIKit;
#endif

using InvokePlatformCodeDemos.Services;

namespace InvokePlatformCodeDemos.Services.ConditionalCompilation
{
    public class DeviceOrientationService
    {
        public DeviceOrientation GetOrientation()
        {
#if ANDROID
            IWindowManager windowManager = Android.App.Application.Context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
            SurfaceOrientation orientation = windowManager.DefaultDisplay.Rotation;
            bool isLandscape = orientation == SurfaceOrientation.Rotation90 || orientation == SurfaceOrientation.Rotation270;
            return isLandscape ? DeviceOrientation.Landscape : DeviceOrientation.Portrait;
#elif IOS
            UIInterfaceOrientation orientation = UIApplication.SharedApplication.StatusBarOrientation;
            bool isPortrait = orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown;
            return isPortrait ? DeviceOrientation.Portrait : DeviceOrientation.Landscape;
#else
            return DeviceOrientation.Undefined;
#endif
        }
    }
}

在此示例中,为 Android 和 iOS 提供了该方法的平台 GetOrientation 实现。 在其他平台上, DeviceOrientation.Undefined 将返回。 或者,而不是返回 DeviceOrientation.Undefined ,可以引发一个 PlatformNotSupportedException 指定为实现提供的平台:

throw new PlatformNotSupportedException("GetOrientation is only supported on Android and iOS.");

DeviceOrientationService.GetOrientation然后,可以通过创建对象实例并调用其操作,从跨平台代码调用该方法:

using InvokePlatformCodeDemos.Services;
using InvokePlatformCodeDemos.Services.ConditionalCompilation;
...

DeviceOrientationService deviceOrientationService = new DeviceOrientationService();
DeviceOrientation orientation = deviceOrientationService.GetOrientation();

在生成时,生成系统使用条件编译将 Android 和 iOS 平台代码定向到正确的平台。

有关条件编译的详细信息,请参阅 条件编译

分部类和方法

.NET MAUI 应用项目包含 一个 Platform 文件夹,每个子文件夹表示 .NET MAUI 可以面向的平台:

平台文件夹屏幕截图。

每个目标平台的文件夹包含特定于平台的代码,这些代码在每个平台上启动应用,以及添加的任何其他平台代码。 在生成时,生成系统仅在为该特定平台生成时包含每个文件夹中的代码。 例如,在为 Android 生成时, 平台>Android 文件夹中的文件将内置到应用包中,但其他 平台 文件夹中的文件不会。 此方法使用一个名为“多目标”的功能从单个项目面向多个平台。

可以将多目标与分部类和分部方法结合使用,以从跨平台代码调用平台功能。 执行此操作的过程是:

  1. 将跨平台 API 定义为一个分部类,用于定义要在每个平台上调用的任何操作的部分方法签名。 有关详细信息,请参阅 定义跨平台 API
  2. 通过定义相同的分部类和相同的分部方法签名,同时提供方法实现,实现每个平台的跨平台 API。 有关详细信息,请参阅 每个平台实现 API
  3. 通过创建分部类的实例并根据需要调用其方法来调用跨平台 API。 有关详细信息,请参阅 调用跨平台 API

定义跨平台 API

若要从跨平台代码调用平台代码,第一步是将跨平台 API 定义为 分部类,该部分类 定义要在每个平台上调用的任何操作的部分 方法 签名。

以下示例显示了 DeviceOrientation 枚举,该枚举将用于指定设备的方向:

namespace InvokePlatformCodeDemos.Services
{
    public enum DeviceOrientation
    {
        Undefined,
        Landscape,
        Portrait
    }
}

以下示例演示可用于检索设备方向的跨平台 API:

namespace InvokePlatformCodeDemos.Services.PartialMethods
{
    public partial class DeviceOrientationService
    {
        public partial DeviceOrientation GetOrientation();
    }
}

分部类命名 DeviceOrientationService,其中包括一个名为 GetOrientation的分部方法。 此类的代码文件必须位于 “平台” 文件夹之外:

Services 文件夹中的 DeviceOrientationService 类屏幕截图。

每个平台实现 API

定义跨平台 API 后,必须通过定义相同的分部类和相同的分部方法签名在所有平台上实现该 API,同时提供方法实现。

平台实现应放置在正确的 平台 子文件夹中,以确保生成系统仅在为特定平台生成时尝试生成平台代码。 下表列出了平台实现的默认文件夹位置:

平台 文件夹
Android 平台>Android
iOS 平台>Ios
MacCatalyst 平台>MacCatalyst
Tizen 平台>Tizen
Windows 平台>窗户

重要

平台实现必须位于定义跨平台 API 的同一命名空间和同一类中。

以下屏幕截图显示了 DeviceOrientationServiceAndroidiOS 文件夹中的类:

“平台”文件夹中的 DeviceOrientationService 类屏幕截图。

或者,可以根据自己的文件名和文件夹条件(而不是使用 平台 文件夹)执行多目标。 有关详细信息,请参阅 配置多目标

Android

以下示例演示 Android 上方法的 GetOrientation 实现:

using Android.Content;
using Android.Runtime;
using Android.Views;

namespace InvokePlatformCodeDemos.Services.PartialMethods;

public partial class DeviceOrientationService
{
    public partial DeviceOrientation GetOrientation()
    {
        IWindowManager windowManager = Android.App.Application.Context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
        SurfaceOrientation orientation = windowManager.DefaultDisplay.Rotation;
        bool isLandscape = orientation == SurfaceOrientation.Rotation90 || orientation == SurfaceOrientation.Rotation270;
        return isLandscape ? DeviceOrientation.Landscape : DeviceOrientation.Portrait;
    }
}

iOS

以下示例演示 iOS 上方法的 GetOrientation 实现:

using UIKit;

namespace InvokePlatformCodeDemos.Services.PartialMethods;

public partial class DeviceOrientationService
{
    public partial DeviceOrientation GetOrientation()
    {
        UIInterfaceOrientation orientation = UIApplication.SharedApplication.StatusBarOrientation;
        bool isPortrait = orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown;
        return isPortrait ? DeviceOrientation.Portrait : DeviceOrientation.Landscape;
    }
}

调用跨平台 API

提供平台实现后,可以通过创建对象实例并调用其操作,从跨平台代码调用 API:

using InvokePlatformCodeDemos.Services;
using InvokePlatformCodeDemos.Services.PartialMethods;
...

DeviceOrientationService deviceOrientationService = new DeviceOrientationService();
DeviceOrientation orientation = deviceOrientationService.GetOrientation();

在生成时,生成系统将使用多目标将跨平台分部类与目标平台的分部类相结合,并将其构建到应用包中。

配置多目标

.NET MAUI 应用也可以基于自己的文件名和文件夹条件进行多目标化。 这样,便可以构建 .NET MAUI 应用项目,这样就不必将平台代码放入 Platform 文件夹的子文件夹中。

例如,标准多目标模式是将平台作为扩展包含在平台代码的文件名中。 可以配置生成系统,以基于以下模式将跨平台分部类与平台分部类组合在一起:

使用基于文件名的多目标的 DeviceOrientationService 类。

另一种标准多目标模式是将平台作为文件夹名称包含在内。 可以配置生成系统,以基于以下模式将跨平台分部类与平台分部类组合在一起:

使用基于文件夹的多目标的 DeviceOrientationService 类。

有关详细信息,请参阅 配置多目标