共用方式為


開始使用原生連結庫 Interop

本文說明如何使用 Maui.NativeLibraryInterop 開始使用原生連結庫 Interop 來簡化設定。

這些指示概述透過原生連結庫 Interop 建立系結的基本步驟、關鍵決策點和指引範例。 如需特定 API 和實作詳細數據的進一步指引,請參閱相關原生 SDK 和連結庫的檔。

必要條件

安裝必要條件:

注意

可以獨立方式安裝 Android SDK 和/或 Xcode 命令行工具 。 不過,Xcode 命令行工具安裝通常是透過 Xcode 來處理。 同樣地, Android SDK 安裝通常是透過 Android Studio 和 /或 .NET MAUI VS Code 擴充 功能,根據 .NET MAUI 用戶入門 文件來處理。

建立新的系結

若要開始建立新的系結,最簡單的方式是在Maui.NativeLibraryInterop存放庫中複製範本,並從該處進行修改。 若要進一步瞭解 Maui.NativeLibraryInterop 目前設定方式的完整範圍,請參閱概觀文件

設定 .NET 系結連結庫

範本 包含適用於 Android 的入門 .NET 和適用於 iOS 系結連結庫的 .NET。

更新系結連結庫,以反映 .NET 應用程式中所需的目標平臺和 .NET 版本。

注意

例如:如果您的目標是只使用 .NET 9 建立 iOS 系結,您可以:

  1. 刪除範本/android/NewBinding.Android.Binding的 Android 系結連結庫,以及
  2. 更新 template/macios/NewBinding.MaciOS.Binding/NewBinding.MaciOS.Binding.maciOS.Binding.csproj 中的目標架構,以設定為 net9.0-ios

設定原生包裝函式專案和連結庫

範本 也包含入門 Android Studio 專案和 Xcode 專案。

更新原生專案,以視需要在 .NET 應用程式中反映目標平臺和版本,並在下列步驟中包含感興趣的原生連結庫。

設定:iOS 和 Mac Catalyst

Xcode 項目位於 template/macios/native/NewBinding。

更新 Xcode 專案,以反映 .NET 應用程式中支援的目標平臺和版本。 在 Xcode 專案中,按兩下最上層架構,然後在 [目標一般] 中>:

  1. 視需要新增/移除任何 支援目的地
  2. 視需要調整 iOS 版本。

透過任何最適合您連結庫和需求的方法,將 iOS 和/或 MacCatalyst 的原生連結庫帶入您的 Xcode 專案(例如 CocoaPods、Swift 封裝管理員)。

安裝程式:Android

Android Studio 專案位於 template/android/native

更新 Android Studio 專案,以反映 .NET 應用程式中支援的目標版本。

  1. 流覽至 build.gradle.kts (:app) 檔案
  2. compileSdk視需要更新版本

透過 gradle 引進 Android 原生連結庫

  1. 在 build.gradle.kts (:app) 檔案的相依性區塊中新增套件相依性。
  2. 將存放庫新增至 dependencyResolutionManagementrepositories settings.gradle.kts 檔案中的 區塊。
  3. 將專案與 gradle 檔案同步處理(透過 Android Studio 右上角的按鈕)。

建立 API 介面

使用下列步驟,在原生專案與 .NET 系結項目之間建立 API 介面。

API 定義:iOS 和 Mac Catalyst

在原生端,在 template/macios/native/NewBinding/NewBinding/DotnetNewBinding.swift進行更新:

  1. 新增 import 語句以匯入您剛才新增的原生連結庫。
  2. 為感興趣的原生連結庫 API 撰寫 API 定義。
  3. 請確定 Xcode 專案建置成功,且您對 API 感到滿意。

回到 .NET 端,我們現在已準備好與原生連結庫進行互操作性:

  1. dotnet buildtemplate/macios/NewBinding.MaciOS.Binding 執行,以測試所有專案都正確且正常運作。
  2. 使用 Objective Sharpie 生成 C# 系結以供 Swift API 更新:
    1. 流覽至 template/macios/NewBinding.MaciOS.Binding/bin/Debug/net9.0-ios/NewBinding.MaciOS.Binding.resources/NewBindingiOS.xcframework/ios-arm64/NewBinding.framework 在 MaciOS 系結項目輸出資料夾中。
    2. 執行 sharpie xcode -sdks,以取得系結命令的有效目標 SDK 值清單。 選取與你要在下一個指令中使用的平臺和版本相符合的值,例如 iphoneos18.0
    3. 針對系結專案所建立的 xcframework 中的標頭檔執行 sharpie bind
      sharpie bind --output=sharpie-out --namespace=NewBindingMaciOS --sdk=iphoneos18.0 --scope=Headers Headers/NewBinding-Swift.h
      
    4. 更新 template/macios/NewBinding.MaciOS.Binding/ApiDefinition.cs的內容,將其替換為 template/macios/NewBinding.MaciOS.Binding/bin/Debug/net9.0-ios/NewBinding.MaciOS.Binding.resources/NewBindingiOS.xcframework/ios-arm64/NewBinding.framework/sharpie-out/ApiDefinitions.cs的內容,並視需要進行調整(例如:命名)。
    5. 再次從 dotnet build 執行

另請參閱 objective-sharpie 文件,以瞭解更多有關此工具的資訊。

API 定義:Android

在原生端,在 範本/android/native/newbinding/src/main/java/com/example/newbinding/DotnetNewBinding.java中進行更新:

  1. 新增 import 語句以匯入您剛才新增的原生連結庫。
  2. 為感興趣的原生連結庫 API 撰寫 API 定義。
  3. 請確定 Android Studio 專案建置成功,且您滿意 API。

回到 .NET 端,我們現在已準備好與原生連結庫進行互操作性:

  1. dotnet buildtemplate/android/NewBinding.Android.Binding 執行,以測試所有專案都已正確插入並正常運作。 (注意:此步驟會要求您安裝 JDK 17)
  2. 藉由在本機 Android 專案中每個要綁定的 maven 相依項目,將 @(AndroidMavenLibrary) 項目新增到 template/sample/MauiSample.csproj 來參考任何 Android 綁定相依性。 這會啟用專案的 Java 相依性驗證,並導致後續組建產生遺漏相依性的建置警告或錯誤。 您可以新增 @(AndroidMavenLibrary)@(PackageReference) 元素,以滿足您所系結的原生程式庫的 Java 相依鏈結,從而解決這些警告/錯誤。 注意:Gradle/Maven 相依關係通常需要明確參考,因為它們不會自動納入到您的程式庫中。)
<ItemGroup Condition="$(TargetFramework.Contains('android'))">
    <AndroidMavenLibrary Include="{DependencyGroupId}:{DependencyName}" Version="{DependencyVersion}" Bind="false" />
</ItemGroup>

如需了解此流程的更多資訊,另請參閱 AndroidMavenLibrary 參考Java 相依性驗證 文檔。

注意

您可以重新命名佔位元元 DotnetNewBinding 類別,以更清楚地反映要包裝的原生連結庫。 如需撰寫 API 定義的更多範例和秘訣,請參閱下 一節:修改現有的系結

在您的 .NET 應用程式中取用 API

範本包含範本/範例/MauiSample.NET MAUI 範例應用程式,其會參考 .NET 系結專案,並讓原生連結庫立即可供使用!

如果您有興趣使用自己的 .NET MAUI、適用於 Android 的 .NET、適用於 iOS 的 .NET 和/或 .NET for Mac Catalyst 應用程式,不過,您可以修改 .NET 應用程式專案檔來參考系結連結庫:.

<!-- Reference to MaciOS Binding project -->
<ItemGroup Condition="$(TargetFramework.Contains('ios')) Or $(TargetFramework.Contains('maccatalyst'))">
    <ProjectReference Include="..\..\macios\NewBinding.MaciOS.Binding\NewBinding.MaciOS.Binding.csproj" />
</ItemGroup>

<!-- Reference to Android Binding project -->
<ItemGroup Condition="$(TargetFramework.Contains('android'))">
    <ProjectReference Include="..\..\android\NewBinding.Android.Binding\NewBinding.Android.Binding.csproj" />
</ItemGroup>

修改現有的系結

如果現有的 API 介面未公開您自己專案中所需的功能,是時候進行自己的修改了!

iOS 和 Mac Catalyst

在 Xcode 專案中,您會發現一或多個 Swift 檔案,這些檔案會定義系結的公用 API 介面。 例如, register Firebase Messaging 的 方法定義為:

@objc(MauiFIRMessaging)
public class MauiFIRMessaging : NSObject {

    @objc(register:completion:)
    public static func register(apnsToken: NSData, completion: @escaping (String?, NSError?) -> Void) {
        let data = Data(referencing: apnsToken);
        Messaging.messaging().apnsToken = data
        Messaging.messaging().token(completion: { fid, error in
            completion(fid, error as NSError?)
        })
    }
    // ...
}

注意

.NET 系結將使用的原生包裝函式 API 類型必須宣告為 public ,而且必須使用 和 方法@objc(NameOfType)來表示public,而且也可以受益於指定名稱和參數的類似批注@objc(methodName:parameter1:),這有助於影響將產生哪些目標夏皮的系結。

您可以在此方法中看到,公用 API 介面只會使用 iOS 的 .NET 已經知道的類型:NSDataStringNSError 和回呼。

Firebase.MaciOS.Binding 專案中, ApiDefinitions.cs 檔案包含這個原生包裝函式 API 的系結定義:

using System;
using Foundation;

namespace Firebase
{
    // @interface MauiFIRMessaging : NSObject
    [BaseType (typeof(NSObject))]
    interface MauiFIRMessaging
    {
        [Static]
        [Export ("register:completion:")]
        [Async]
        void Register (NSData apnsToken, Action<string?, NSError?> completion);
        // ...
    }

假設您想要新增取消註冊的方法。 Swift 程式代碼看起來會像這樣:

@objc(unregister:)
public static func unregister(completion: @escaping (NSError?) -> Void) {
    // need delegate to watch for fcmToken updates
    Messaging.messaging().deleteToken(completion: { error in
        completion(error as NSError?)
    })
}

另一半是更新系結專案中的ApiDefinitions.cs檔案,以公開這個新方法。 有兩種方式可以解決此問題:

  1. 您可以手動新增必要的程式碼
  2. 建置系結項目之後,您可以運行 Objective Sharpie 工具來產生 ApiDefinitions.cs 檔案。 您可以嘗試尋找此檔案的相關變更,並手動複製這些變更,或嘗試複製整個檔案,並查看差異以尋找您需要的部分。

在此情況下,ApiDefinitions.cs的變更會是:

[Static]
[Export("unregister:")]
[Async]
void UnRegister(Action completion);

進行這些變更之後,您可以重建系結專案,而新的 API 將會準備好從 .NET MAUI 專案使用。

注意

Mac/iOS 的系結專案不會使用來源產生器,因此專案系統和 Intellisense 在重建系結專案之前,可能無法知道新的 API,並重載方案,讓專案參考挑選較新的元件。 不論 Intellisense 錯誤為何,您的應用程式專案仍應該編譯。

Android

在 Android Studio 專案中,您會發現模組目錄,其中包含定義系結之公用 API 介面的 Java 檔案。 例如, initialize Facebook 的 方法定義如下:

package com.microsoft.mauifacebook;

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;

import com.facebook.LoggingBehavior;
import com.facebook.appevents.AppEventsLogger;

public class FacebookSdk {

    static AppEventsLogger _logger;

    public static void initialize(Activity activity, Boolean isDebug) {
        Application application = activity.getApplication();

        if (isDebug) {
            com.facebook.FacebookSdk.setIsDebugEnabled(true);
        }

        com.facebook.FacebookSdk.addLoggingBehavior(LoggingBehavior.APP_EVENTS);

        AppEventsLogger.activateApp(application);

        _logger = AppEventsLogger.newLogger(activity);
    }

    // ...
}

您可以在此方法中看到,公用 API 介面只會使用適用於 Android 的 .NET 已經知道的類型: ActivityBoolean

在 Facebook.Android.Binding 一般而言,Android 系結比目前 Mac/iOS 更「自動」,您很少需要對這些轉換檔案進行變更。

<metadata>
    <attr path="/api/package[@name='com.microsoft.mauifacebook']" name="managedName">Facebook</attr>
</metadata>

假設您想要新增方法來記錄事件。 Java 程式代碼看起來會像這樣:

public static void logEvent(String eventName) {
    _logger.logEvent(eventName);
}

從這個簡單的變更中,系結專案不需要更新 Transforms/Metadata.xml 或其他檔案。 您只要重建系結專案,新的 API 就會準備好從 .NET MAUI 專案使用。

注意

Android 的系結專案不會使用來源產生器,因此專案系統和 Intellisense 在重建系結專案之前,可能不知道新的 API,並重載方案,讓專案參考挑選較新的元件。 不論 Intellisense 錯誤為何,您的應用程式專案仍應該編譯。