Freigeben über


Erste Schritte mit nativer Bibliotheks-Interoperabilität

Dieser Artikel beschreibt die ersten Schritte mit der nativen Bibliotheks-Interoperabilität mit Maui.NativeLibraryInterop zur Vereinfachung des Setups.

In diesen Anweisungen werden die grundlegenden Schritte, wichtigen Entscheidungspunkte und Leitbeispiele zum Erstellen von Bindungen über die native Bibliotheks-Interoperabilität beschrieben. Weitere Anleitungen zu spezifischen API- und Implementierungsdetails finden Sie in der Dokumentation zu den nativen SDKs und Bibliotheken von Interesse.

Voraussetzungen

Installieren von Voraussetzungen:

Hinweis

Es ist möglich, das Android SDK und/oder die Xcode-Befehlszeilentools eigenständig zu installieren. Die Installation der Xcode-Befehlszeilentools wird jedoch in der Regel über Xcode abgewickelt. Ebenso wird die Android SDK-Installation in der Regel auch über Android Studio und/oder die .NET MAUI VS Code-Erweiterung gemäß der Dokumentation Erste Schritte mit .NET MAUI abgewickelt.

Erstellen einer neuen Bindung

Am einfachsten können Sie mit dem Erstellen einer neuen Bindung beginnen, indem Sie die Vorlage im Maui.NativeLibraryInterop-Repository klonen und dort Änderungen vornehmen. Um besser zu verstehen, wie Maui.NativeLibraryInterop derzeit aufgebaut ist, lesen Sie bitte die Übersichtsdokumentation.

Einrichten der .NET-Bindungsbibliotheken

Die Vorlage enthält Starter-Bindungsbibliotheken für .NET für Android und .NET für iOS.

Aktualisieren Sie die Bindungsbibliotheken, um die Zielplattformen und die .NET-Version in Ihrer .NET-App nach Bedarf widerzuspiegeln.

Hinweis

Beispiel: Wenn Sie nur eine iOS-Bindung mit .NET 9 erstellen möchten, können Sie Folgendes tun:

  1. Löschen Sie die Android-Bindungsbibliothek unter template/android/NewBinding.Android.Binding und
  2. Aktualisieren Sie das Zielframework unter template/macios/NewBinding.MaciOS.Binding/NewBinding.MaciOS.Binding.csproj auf net9.0-ios.

Einrichten der nativen Wrapperprojekte und -bibliotheken

Die Vorlage enthält auch Starter-Projekte für Android Studio und Xcode.

Aktualisieren Sie die nativen Projekte, um die Zielplattformen und -versionen in Ihrer .NET-App nach Bedarf widerzuspiegeln, und schließen Sie die nativen Bibliotheken von Interesse mit den folgenden Schritten ein.

Setup: iOS und Mac Catalyst

Das Xcode-Projekt befindet sich unter template/macios/native/NewBinding.

Aktualisieren Sie das Xcode-Projekt, um die Zielplattformen und -versionen widerzuspiegeln, so wie in Ihrer .NET-App unterstützt. Klicken Sie im Xcode-Projekt auf das Framework der obersten Ebene und führen Sie in Ziele > Allgemein Folgendes durch:

  1. Fügen Sie alle Supportziele nach Bedarf hinzu bzw. entfernen Sie diese.
  2. Passen Sie die iOS-Version nach Bedarf an.

Bringen Sie die native Bibliothek für iOS und/oder MacCatalyst in Ihr Xcode-Projekt ein, indem Sie die für Ihre Bibliothek und Ihre Anforderungen am besten geeignete Methode verwenden (z. B. CocoaPods, Swift Package Manager).

Setup: Android

Das Android Studio-Projekt befindet sich unter template/android/native.

Aktualisieren Sie das Android Studio-Projekt, um die in Ihrer .NET-App unterstützten Zielversionen widerzuspiegeln.

  1. Navigieren Sie zur Datei build.gradle.kts (:app)
  2. Aktualisieren Sie die compileSdk-Version nach Bedarf

Bringen Sie die native Android-Bibliothek über Gradle ein

  1. Fügen Sie die Paketabhängigkeit in den Abhängigkeitsblock der Datei build.gradle.kts (:app) ein.
  2. Fügen Sie in der Datei settings.gradle.kts dem Block dependencyResolutionManagement repositories das Repository hinzu.
  3. Synchronisieren Sie das Projekt mit Gradle-Dateien (über die Schaltfläche in der oberen rechten Ecke von Android Studio).

Erstellen der API-Schnittstelle

Erstellen Sie die API-Schnittstelle zwischen Ihren nativen Projekten und Ihren .NET-Bindungsprojekten mit den folgenden Schritten.

API-Definition: iOS und Mac Catalyst

Nehmen Sie auf der nativen Seite Aktualisierungen in template/macios/native/NewBinding/NewBinding/DotnetNewBinding.swift vor:

  1. Fügen Sie eine Import-Anweisung hinzu, um die soeben von Ihnen hinzugefügte native Bibliothek zu importieren.
  2. Schreiben Sie die API-Definitionen für die nativen Bibliotheks-APIs von Interesse.
  3. Stellen Sie sicher, dass das Xcode-Projekt erfolgreich kompiliert wird und Sie mit den APIs zufrieden sind.

Zurück auf der .NET-Seite sind wir nun bereit, mit der nativen Bibliothek zu interagieren:

  1. Führen Sie dotnet build aus template/macios/NewBinding.MaciOS.Binding aus, um zu testen, ob alles richtig angeschlossen und einsatzbereit ist. Bei erfolgreicher Ausführung finden Sie die generierten C#-Bindungen unter template/macios/native/NewBinding/bin/Release/net8.0-ios/sharpie/NewBinding/ApiDefinitions.cs.
  2. Aktualisieren Sie den Inhalt von template/macios/NewBinding.MaciOS.Binding/ApiDefinition.cs, indem Sie ihn durch den Inhalt von template/macios/native/NewBinding/bin/Release/net8.0-ios/sharpie/NewBinding/ApiDefinitions.cs ersetzen.
  3. Führen Sie dotnet build erneut aus template/macios/NewBinding.MaciOS.Binding aus.

API-Definition: Android

Nehmen Sie auf der nativen Seite Aktualisierungen in template/android/native/app/src/main/java/com/example/newbinding/DotnetNewBinding.java vor:

  1. Fügen Sie eine Import-Anweisung hinzu, um die soeben von Ihnen hinzugefügte native Bibliothek zu importieren.
  2. Schreiben Sie die API-Definitionen für die nativen Bibliotheks-APIs von Interesse.
  3. Stellen Sie sicher, dass das Android Studio-Projekt erfolgreich kompiliert wird und Sie mit den APIs zufrieden sind.

Zurück auf der .NET-Seite sind wir nun bereit, mit der nativen Bibliothek zu interagieren:

  1. Führen Sie dotnet build in template/android/NewBinding.Android.Binding aus, um zu testen, ob alles richtig angeschlossen und einsatzbereit ist. (Hinweis: Dieser Schritt erfordert, dass JDK 17 installiert ist)
  2. Verweisen Sie auf alle Android-Bindungsabhängigkeiten, indem Sie für jede Abhängigkeit den folgenden Code in template/sample/MauiSample.csproj hinzufügen. Ersetzen Sie {yourDependencyLibrary.aar} durch die erforderliche AAR-Datei für die Abhängigkeit, die Sie binden. (Hinweis: Verweise auf gradle/maven-Abhängigkeiten müssen häufig explizit erfolgen, da sie nicht automatisch in Ihre Bibliothek gebündelt werden. Die Datei wird so konfiguriert, dass Abhängigkeiten in einen Ordner „bin/outputs/deps“ kopiert werden, auf den Sie in Ihrer Anwendung verweisen können.)
<ItemGroup Condition="$(TargetFramework.Contains('android'))">
    <AndroidLibrary Include="..\android\native\newbinding\bin\Release\net8.0-android\outputs\deps\{yourDependencyLibrary.aar}">
        <Bind>false</Bind>
        <Visible>false</Visible>
    </AndroidLibrary>
</ItemGroup>

Hinweis

Sie können die Platzhalterklasse DotnetNewBinding umbenennen, um die umschlossene native Bibliothek besser widerzuspiegeln. Weitere Beispiele und Tipps zum Schreiben der API-Definitionen finden Sie weiter unten im Abschnitt Ändern einer vorhandenen Bindung.

Nutzen der APIs in Ihrer .NET-App

Die Vorlage enthält eine .NET MAUI-Beispiel-App unter template/sample/MauiSample, die auf die .NET-Bindungsprojekte verweist und die nativen Bibliotheken sofort einsatzbereit macht!

Wenn Sie jedoch ihre eigenen .NET MAUI-, .NET für Android-, .NET für iOS- und/oder .NET für Mac Catalyst-Apps verwenden möchten, können Sie dies tun, indem Sie Ihre .NET-App-Projektdateien ändern, um auf die Bindungsbibliotheken zu verweisen:

<!-- 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>

Ändern einer vorhandenen Bindung

Wenn die vorhandene API-Oberfläche die Funktionalität, die Sie in Ihrem eigenen Projekt benötigen, nicht verfügbar macht, ist es an der Zeit, Ihre eigenen Änderungen vorzunehmen!

iOS und Mac Catalyst

Innerhalb des Xcode-Projekts finden Sie eine oder mehrere Swift-Dateien, welche die öffentliche API-Oberfläche für die Bindung definieren. Die register-Methode für Firebase Messaging ist beispielsweise wie folgt definiert:

@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?)
        })
    }
    // ...
}

Hinweis

Native Wrapper-API-Typen, die von der .NET-Bindung verwendet werden, müssen als public deklariert und mit @objc(NameOfType) annotiert werden, und Methoden müssen ebenfalls public sein und können auch von ähnlichen @objc(methodName:parameter1:)-Anmerkungen profitieren, bei denen der Name und die Parameter angegeben werden, die dazu beitragen, die Bindung zu beeinflussen, die Objective Sharpie generieren wird.

Sie können in dieser Methode sehen, dass die öffentliche API-Oberfläche nur Typen verwendet, die .NET für iOS bereits kennt: NSData, String, NSError und ein Rückruf.

Im Firebase.MaciOS.Binding-Projekt enthält die Datei ApiDefinitions.cs die Bindungsdefinition für diese native Wrapper-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);
        // ...
    }

Angenommen, Sie möchten eine Methode zum Aufheben der Registrierung hinzufügen. Der Swift-Code sähe in etwa so aus:

@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?)
    })
}

Die andere Hälfte besteht darin, die Datei ApiDefinitions.cs im Bindungsprojekt zu aktualisieren, um diese neue Methode verfügbar zu machen. Es gibt zwei Möglichkeiten, wie Sie dies tun können:

  1. Sie können den erforderlichen Code manuell hinzufügen
  2. Wenn das Bindungsprojekt kompiliert wird, wird Objective Sharpie ausgeführt, und eine Datei ApiDefinitions.cs wird innerhalb des Ordners native/macios/bin/sharpie generiert (dieser Pfad variiert natürlich basierend auf dem Projekt, an dem Sie arbeiten). Sie können versuchen, die relevanten Änderungen aus dieser Datei zu finden und sie manuell herüber zu kopieren, oder Sie können versuchen, die gesamte Datei zu kopieren und sich den Diff anzusehen, um den Teil zu finden, den Sie benötigen.

In diesem Fall wären die Änderungen an ApiDefinitions.cs wie folgt:

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

Nachdem Sie diese Änderungen vorgenommen haben, können Sie das Bindungsprojekt neu kompilieren, und die neue API kann von Ihrem .NET MAUI-Projekt verwendet werden.

Hinweis

Bindungsprojekte für Mac/iOS verwenden keine Quellgeneratoren, so dass das Projektsystem und IntelliSense möglicherweise nicht über die neuen APIs Bescheid wissen, bis Sie das Bindungsprojekt neu kompiliert und die Projektmappe neu geladen haben, so dass die Projektreferenz die neuere Assembly aufnimmt. Ihr App-Projekt sollte trotz der IntelliSense-Fehler kompiliert werden.

Android

Innerhalb des Android Studio-Projekts finden Sie ein Modulverzeichnis, das eine Java-Datei enthält, welche die öffentliche API-Oberfläche für die Bindung definiert. Beispielsweise wird die initialize-Methode für Facebook wie folgt definiert:

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);
    }

    // ...
}

Sie können in dieser Methode sehen, dass die öffentliche API-Oberfläche nur Typen verwendet, die .NET für Android bereits kennt: Activity und Boolean.

Im Projekt Facebook.Android.Binding enthält die Datei Transforms/Metadata.xml nur einigen XML-Code, um zu beschreiben, wie der Java-Paketname (com.microsoft.mauifacebook) einem mehr C#-freundlichen Namespace (Facebook) zugeordnet wird. Im Allgemeinen sind Android-Bindungen zu diesem Zeitpunkt „automatischer“ als Mac/iOS, und Sie sollten nur selten Änderungen an diesen Transformationsdateien vornehmen müssen.

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

Angenommen, Sie möchten eine Methode zum Protokollieren eines Ereignisses hinzufügen. Der Java-Code sähe in etwa so aus:

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

Aufgrund dieser einfachen Änderung erfordert das Bindungsprojekt keine Aktualisierungen der Transforms/Metadata.xml oder anderen Dateien. Sie können das Binding-Projekt einfach neu kompilieren, und die neue API kann von Ihrem .NET MAUI-Projekt verwendet werden.

Hinweis

Bindungsprojekte für Android verwenden keine Quellgeneratoren, so dass das Projektsystem und IntelliSense möglicherweise nicht über die neuen APIs Bescheid wissen, bis Sie das Bindungsprojekt neu kompiliert und die Projektmappe neu geladen haben, so dass die Projektreferenz die neuere Assembly aufnimmt. Ihr App-Projekt sollte trotz der IntelliSense-Fehler kompiliert werden.