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:
- .NET 8.0 SDK
- .NET MAUI-Workload (über Visual Studio oder CLI
dotnet workload install maui
) - Android SDK
- Android Studio
- Objective-Sharpie (erforderlich für die automatisch zu generierenden C#-APIs)
- Xamarin.iOS (erforderlich, damit Objective-Sharpie funktioniert)
- Visual Studio oder Visual Studio Code
- Xcode
- Xcode-Befehlszeilentools (
xcode-select --install
)
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:
- Löschen Sie die Android-Bindungsbibliothek unter template/android/NewBinding.Android.Binding und
- 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:
- Fügen Sie alle Supportziele nach Bedarf hinzu bzw. entfernen Sie diese.
- 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.
- Navigieren Sie zur Datei build.gradle.kts (:app)
- Aktualisieren Sie die
compileSdk
-Version nach Bedarf
Bringen Sie die native Android-Bibliothek über Gradle ein
- Fügen Sie die Paketabhängigkeit in den Abhängigkeitsblock der Datei build.gradle.kts (:app) ein.
- Fügen Sie in der Datei settings.gradle.kts dem Block
dependencyResolutionManagement
repositories
das Repository hinzu. - 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:
- Fügen Sie eine Import-Anweisung hinzu, um die soeben von Ihnen hinzugefügte native Bibliothek zu importieren.
- Schreiben Sie die API-Definitionen für die nativen Bibliotheks-APIs von Interesse.
- 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:
- 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. - 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.
- 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:
- Fügen Sie eine Import-Anweisung hinzu, um die soeben von Ihnen hinzugefügte native Bibliothek zu importieren.
- Schreiben Sie die API-Definitionen für die nativen Bibliotheks-APIs von Interesse.
- 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:
- 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) - 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:
- Sie können den erforderlichen Code manuell hinzufügen
- 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.
.NET MAUI Community Toolkit