Udostępnij za pośrednictwem


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:

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:

  1. Usuń bibliotekę powiązań systemu Android na stronie template/android/NewBinding.Android.Binding i
  2. 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:

  1. Dodaj/usuń wszystkie miejsca docelowe pomocy technicznej zgodnie z potrzebami .
  2. 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.

  1. Przejdź do pliku build.gradle.kts (:app)
  2. Zaktualizuj wersję zgodnie z compileSdk potrzebami

Wprowadzenie biblioteki natywnej systemu Android za pomocą narzędzia gradle

  1. Dodaj zależność pakietu w bloku zależności pliku build.gradle.kts (:app).
  2. Dodaj repozytorium do dependencyResolutionManagementrepositories bloku w pliku settings.gradle.kts .
  3. 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:

  1. Dodaj instrukcję import, aby zaimportować właśnie dodaną bibliotekę natywną.
  2. Napisz interesujące cię definicje interfejsów API biblioteki natywnej.
  3. 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ą:

  1. Uruchom polecenie dotnet build z szablonu /macios/NewBinding.MaciOS.Binding , aby przetestować wszystko, co jest poprawnie podłączone i dobrze.
  2. Użyj funkcji objective sharpie, aby wygenerować powiązania języka C# dla aktualizacji interfejsu API swift:
    1. 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.
    2. 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ład iphoneos18.0.
    3. 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
      
    4. 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).
    5. 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:

  1. Dodaj instrukcję import, aby zaimportować właśnie dodaną bibliotekę natywną.
  2. Napisz interesujące cię definicje interfejsów API biblioteki natywnej.
  3. 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ą:

  1. 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)
  2. 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ą publicbyć 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, StringNSError i wywołanie zwrotne.

W projekcie Firebase.MaciOS.Bindingplik 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:

  1. Możesz ręcznie dodać wymagany kod
  2. 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.