Wprowadzenie do międzyoperacyjności biblioteki natywnej
W tym artykule opisano, jak rozpocząć pracę z międzyoperacyjności biblioteki natywnej przy użyciu biblioteki Maui.NativeLibraryInterop, aby uprościć konfigurację.
Te instrukcje przedstawiają podstawowe kroki, kluczowe punkty decyzyjne i przykłady tworzenia powiązań za pośrednictwem międzyoperacyjności biblioteki natywnej. Aby uzyskać więcej wskazówek dotyczących konkretnego interfejsu API i szczegółów implementacji, zapoznaj się z dokumentacją natywnych zestawów SDK i bibliotek, które cię interesują.
Wymagania wstępne
Zainstaluj wymagania wstępne:
- Zestaw SDK platformy .NET 8.0
-
Obciążenie maUI platformy .NET (za pośrednictwem programu Visual Studio lub interfejsu wiersza polecenia
dotnet workload install maui
) - Android SDK
- Android Studio
-
Objective-Sharpie (używana do ręcznego generowania interfejsów API języka C#)
- Xamarin.iOS (wymagany do pracy w narzędziu Objective-Sharpie)
- Visual Studio lub Visual Studio Code
- Xcode
-
Narzędzia wiersza polecenia Xcode (
xcode-select --install
)
Uwaga
Istnieje możliwość zainstalowania zestawu SDK systemu Android i/lub narzędzi wiersza polecenia Xcode w autonomiczny sposób. Jednak instalacja narzędzi wiersza polecenia Xcode jest zwykle obsługiwana za pośrednictwem środowiska Xcode. Podobnie instalacja zestawu SDK systemu Android jest również zwykle obsługiwana za pośrednictwem programu Android Studio i/lub rozszerzenia programu .NET MAUI PROGRAMU VS Code zgodnie z dokumentacją dotyczącą programu .NET MAUI Getting Started.
Tworzenie nowego powiązania
Najprostszym sposobem rozpoczęcia tworzenia nowego powiązania jest sklonowanie szablonu w repozytorium Maui.NativeLibraryInterop i wprowadzenie tam modyfikacji. Aby lepiej zrozumieć pełny zakres sposobu konfigurowania aplikacji Maui.NativeLibraryInterop, przeczytaj więcej w dokumentacji przeglądu.
Konfigurowanie bibliotek powiązań platformy .NET
Szablon zawiera początkowe biblioteki powiązań platformy .NET dla systemów Android i .NET dla systemu iOS.
Zaktualizuj biblioteki powiązań, aby odzwierciedlały platformy docelowe i wersję platformy .NET zgodnie z potrzebami w aplikacji .NET.
Uwaga
Na przykład: Jeśli chcesz utworzyć tylko powiązanie systemu iOS przy użyciu platformy .NET 9, możesz wykonać następujące czynności:
- Usuń bibliotekę powiązań systemu Android na stronie template/android/NewBinding.Android.Binding i
- Zaktualizuj strukturę docelową w pliku template/macios/NewBinding.MaciOS.Binding/NewBinding.MaciOS.Binding.csproj , aby ustawić wartość
net9.0-ios
.
Konfigurowanie natywnych projektów i bibliotek otoki
Szablon zawiera również początkowe projekty programu Android Studio i projekty Xcode.
Zaktualizuj projekty natywne, aby odzwierciedlały platformy docelowe i wersje zgodnie z potrzebami w aplikacji .NET, i uwzględnij interesujące biblioteki natywne, wykonując następujące kroki.
Konfiguracja: iOS i Mac Catalyst
Projekt Xcode znajduje się w folderze template/macios/native/NewBinding.
Zaktualizuj projekt Xcode, aby odzwierciedlał platformy docelowe i wersje zgodnie z obsługą w aplikacji .NET. W projekcie Xcode kliknij platformę najwyższego poziomu i w obszarze Cele > ogólne:
- Dodaj/usuń wszystkie miejsca docelowe pomocy technicznej zgodnie z potrzebami .
- Dostosuj wersję systemu iOS zgodnie z potrzebami.
Wdróż bibliotekę natywną dla systemów iOS i/lub MacCatalyst w projekcie Xcode, za pomocą dowolnej metody, która działa najlepiej dla biblioteki i Twoich potrzeb (np. CocoaPods, Swift Menedżer pakietów).
Konfiguracja: Android
Projekt programu Android Studio znajduje się w folderze template/android/native.
Zaktualizuj projekt programu Android Studio, aby odzwierciedlał wersje docelowe obsługiwane w aplikacji .NET.
- Przejdź do pliku build.gradle.kts (:app)
- Zaktualizuj wersję zgodnie z
compileSdk
potrzebami
Wprowadzenie biblioteki natywnej systemu Android za pomocą narzędzia gradle
- Dodaj zależność pakietu w bloku zależności pliku build.gradle.kts (:app).
- Dodaj repozytorium do
dependencyResolutionManagement
repositories
bloku w pliku settings.gradle.kts . - Synchronizuj projekt z plikami gradle (za pomocą przycisku w prawym górnym rogu programu Android Studio).
Tworzenie interfejsu API
Utwórz interfejs API między projektami natywnymi i projektami powiązań platformy .NET, wykonując następujące kroki.
Definicja interfejsu API: iOS i Mac Catalyst
Po stronie natywnej wprowadź aktualizacje w pliku template/macios/native/NewBinding/NewBinding/DotnetNewBinding.swift:
- Dodaj instrukcję import, aby zaimportować właśnie dodaną bibliotekę natywną.
- Napisz interesujące cię definicje interfejsów API biblioteki natywnej.
- Upewnij się, że projekt Xcode zostanie pomyślnie skompilowany i będziesz zadowolony z interfejsów API.
Po stronie platformy .NET jesteśmy teraz gotowi do współdziałania z biblioteką natywną:
- Uruchom polecenie
dotnet build
z szablonu /macios/NewBinding.MaciOS.Binding , aby przetestować wszystko, co jest poprawnie podłączone i dobrze. - Użyj funkcji objective sharpie, aby wygenerować powiązania języka C# dla aktualizacji interfejsu API swift:
- Przejdź do template/macios/NewBinding.MaciOS.Binding/bin/Debug/net9.0-ios/NewBinding.MaciOS.Binding.resources/NewBindingiOS.xcframework/ios-arm64/NewBinding.framework w folderze wyjściowym projektów powiązań systemu MaciOS.
- Uruchom
sharpie xcode -sdks
, aby uzyskać listę prawidłowych wartości docelowego zestawu SDK dla powiązanego polecenia. Wybierz wartość, która jest zgodna z platformą i wersją docelową do użycia z następnym poleceniem, na przykładiphoneos18.0
. - Uruchom
sharpie bind
względem plików nagłówkowych w pliku xcframework utworzonym przez projekt powiązania:sharpie bind --output=sharpie-out --namespace=NewBindingMaciOS --sdk=iphoneos18.0 --scope=Headers Headers/NewBinding-Swift.h
- Zaktualizuj zawartość szablonu/macios/NewBinding.MaciOS.Binding/ApiDefinition.cs, zastępując zawartością template/macios/NewBinding.MaciOS.Binding/bin/Debug/net9.0-ios/NewBinding.MaciOS.Binding.resources/NewBindingiOS.xcframework/ios-arm64/NewBinding.framework/sharpie-out/ApiDefinitions.cs i dostosowując ją zgodnie z potrzebami (np. nazewnictwo).
- Uruchom ponownie
dotnet build
z szablonu/macios/NewBinding.MaciOS.Binding .
Zobacz również dokumentację objective-sharpie, aby dowiedzieć się więcej o tym narzędziu.
Definicja interfejsu API: Android
Po stronie natywnej wprowadź aktualizacje w szablonie /android/native/newbinding/src/main/java/com/example/newbinding/DotnetNewBinding.java:
- Dodaj instrukcję import, aby zaimportować właśnie dodaną bibliotekę natywną.
- Napisz interesujące cię definicje interfejsów API biblioteki natywnej.
- Upewnij się, że projekt programu Android Studio został pomyślnie skompilowany i że interfejsy API są zadowalające.
Po stronie platformy .NET jesteśmy teraz gotowi do współdziałania z biblioteką natywną:
- Uruchom polecenie
dotnet build
z szablonu /android/NewBinding.Android.Binding , aby przetestować wszystko, co jest poprawnie podłączone i dobrze. (Uwaga: ten krok będzie wymagał zainstalowania zestawu JDK 17) - Aby odwołać się do wszystkich powiązań zależności Androida, dodaj element
@(AndroidMavenLibrary)
do szablonu/przykładu/mauiSample.csproj dla każdej zależności maven powiązanej w natywnym projekcie Android. Umożliwi to weryfikację zależności języka Java dla projektu i spowoduje utworzenie kolejnych kompilacji w celu wygenerowania ostrzeżeń kompilacji lub błędów dotyczących brakujących zależności. Można rozwiązać te ostrzeżenia/błędy, dodając elementy@(AndroidMavenLibrary)
lub@(PackageReference)
, zgodnie z zaleceniem, aby spełnić łańcuch zależności języka Java dla biblioteki natywnej, którą wiążesz. (Uwaga: zależności Gradle lub Maven często wymagają jawnego wskazania, ponieważ nie są one automatycznie dołączane do bibliotek).
<ItemGroup Condition="$(TargetFramework.Contains('android'))">
<AndroidMavenLibrary Include="{DependencyGroupId}:{DependencyName}" Version="{DependencyVersion}" Bind="false" />
</ItemGroup>
Aby uzyskać więcej informacji na temat tego procesu, zobacz również dokumentację AndroidMavenLibrary oraz weryfikacji zależności Java.
Uwaga
Możesz zmienić nazwę klasy symbolu zastępczego DotnetNewBinding
, aby lepiej odzwierciedlać opakowaną bibliotekę natywną. Aby uzyskać więcej przykładów i wskazówek dotyczących pisania definicji interfejsu API, przeczytaj więcej w poniższej sekcji: Modyfikowanie istniejącego powiązania.
Korzystanie z interfejsów API w aplikacji .NET
Szablon zawiera przykładową aplikację .NET MAUI na stronie template/sample/MauiSample, która odwołuje się do projektów powiązań platformy .NET i natychmiast przygotowuje biblioteki natywne do użycia.
Jeśli interesuje Cię użycie własnych aplikacji .NET MAUI, .NET for Android, .NET for iOS i/lub .NET for Mac Catalyst, możesz to zrobić, modyfikując pliki projektu aplikacji .NET w celu odwołania się do bibliotek powiązań:
<!-- 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>
Modyfikowanie istniejącego powiązania
Jeśli istniejąca powierzchnia interfejsu API nie uwidacznia potrzebnych funkcji we własnym projekcie, nadszedł czas, aby wprowadzić własne modyfikacje.
Katalizator systemu iOS i Mac
W projekcie Xcode znajdziesz co najmniej jeden plik Swift, który definiuje publiczną powierzchnię interfejsu API dla powiązania. Na przykład register
metoda obsługi komunikatów firebase jest definiowana jako:
@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?)
})
}
// ...
}
Uwaga
Natywne typy interfejsów API otoki, które będą używane przez powiązanie platformy .NET, muszą być zadeklarowane public
jako @objc(NameOfType)
i muszą public
być również oznaczone, a także metody muszą mieć wartość , a także mogą korzystać z podobnych adnotacji@objc(methodName:parameter1:)
, w których określono nazwę i parametry, które pomagają wpłynąć na powiązanie, które będzie generowane przez cel sharpie.
W tej metodzie widać, że publiczna powierzchnia interfejsu API używa tylko typów, których platforma .NET dla systemu iOS już zna: NSData
, String
NSError
i wywołanie zwrotne.
W projekcie Firebase.MaciOS.Binding
plik ApiDefinitions.cs zawiera definicję powiązania dla tego natywnego interfejsu API otoki:
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);
// ...
}
Załóżmy, że chcesz dodać metodę do wyrejestrowania. Kod Swift będzie wyglądać mniej więcej tak:
@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?)
})
}
Druga połowa będzie aktualizować plik ApiDefinitions.cs w projekcie powiązania, aby uwidocznić tę nową metodę. Istnieją dwa sposoby, które można wykonać w tym celu:
- Możesz ręcznie dodać wymagany kod
- Po utworzeniu projektu powiązania możesz uruchomić narzędzie Objective Sharpie, aby wygenerować plik ApiDefinitions.cs. Możesz spróbować znaleźć odpowiednie zmiany z tego pliku i skopiować je ręcznie lub spróbować skopiować cały plik i przyjrzeć się różnicom, aby znaleźć potrzebną część.
W takim przypadku zmiany w ApiDefinitions.cs będą następujące:
[Static]
[Export("unregister:")]
[Async]
void UnRegister(Action completion);
Po wprowadzeniu tych zmian możesz ponownie skompilować projekt Wiązanie, a nowy interfejs API będzie gotowy do użycia z projektu .NET MAUI.
Uwaga
Tworzenie powiązań projektów dla komputerów Mac/iOS nie korzysta z generatorów źródłowych, dlatego system projektu i funkcja IntelliSense mogą nie wiedzieć o nowym interfejsie API, dopóki nie utworzysz projektu powiązania i ponownie załadowano rozwiązanie, aby odwołanie do projektu pobierało nowszy zestaw. Projekt aplikacji powinien być nadal kompilowany niezależnie od błędów funkcji IntelliSense.
Android
W projekcie programu Android Studio znajdziesz katalog modułu zawierający plik java, który umożliwia określenie publicznego obszaru interfejsu API dla powiązania. Na przykład metoda serwisu Facebook jest zdefiniowana initialize
w następujący sposób:
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);
}
// ...
}
W tej metodzie widać, że publiczna powierzchnia interfejsu API używa tylko typów, których platforma .NET dla systemu Android już zna: Activity
i Boolean
.
W projekcie Facebook.Android.BindingFacebook
Ogólnie rzecz biorąc, powiązania systemu Android są bardziej "automatyczne" niż mac/iOS w tym momencie i rzadko należy wprowadzać zmiany w tych plikach transformacji.
<metadata>
<attr path="/api/package[@name='com.microsoft.mauifacebook']" name="managedName">Facebook</attr>
</metadata>
Załóżmy, że chcesz dodać metodę rejestrowania zdarzenia. Kod java będzie wyglądać mniej więcej tak:
public static void logEvent(String eventName) {
_logger.logEvent(eventName);
}
W ramach tej prostej zmiany projekt powiązania nie wymaga aktualizacji przekształceń /Metadata.xml ani innych plików. Możesz po prostu ponownie skompilować projekt Binding (Powiązanie), a nowy interfejs API będzie gotowy do użycia z projektu .NET MAUI.
Uwaga
Tworzenie powiązań projektów dla systemu Android nie korzysta z generatorów źródłowych, dlatego system projektu i funkcja IntelliSense mogą nie wiedzieć o nowych interfejsach API, dopóki nie utworzysz projektu powiązania i ponownie załaduj rozwiązanie, aby odwołanie do projektu pobierało nowszy zestaw. Projekt aplikacji powinien być nadal kompilowany niezależnie od błędów funkcji IntelliSense.
.NET MAUI Community Toolkit