Condividi tramite


Introduzione all'interoperabilità di Native Library

Questo articolo illustra come iniziare a usare l'interoperabilità di Native Library usando Maui.NativeLibraryInterop per semplificare la configurazione.

Queste istruzioni illustrano i passaggi di base, i punti decisionali principali e gli esempi guida per la creazione di associazioni tramite l'interoperabilità di Native Library. Per altre indicazioni su informazioni specifiche sull'API e sull'implementazione, vedere la documentazione relativa agli SDK nativi e alle librerie di interesse.

Prerequisiti

Prerequisiti di installazione:

Nota

È possibile installare Android SDK e/o gli strumenti da riga di comando Xcode in modo autonomo. Tuttavia, l'installazione degli strumenti da riga di comando Xcode viene in genere gestita tramite Xcode. Analogamente, l'installazione di Android SDK viene in genere gestita anche tramite Android Studio e/o l'estensione .NET MAUI VS Code in base alla documentazione introduttiva di .NET MAUI.

Creare una nuova associazione

Il modo più semplice per iniziare a creare una nuova associazione consiste nel clonare il modello nel repository Maui.NativeLibraryInterop e apportare modifiche da questa posizione. Per comprendere meglio l'ambito completo della configurazione di Maui.NativeLibraryInterop, vedere la documentazione di panoramica.

Configurare le librerie di binding .NET

Il modello include .NET starter per Android e .NET per le librerie di associazione iOS.

Aggiornare le librerie di binding in modo da riflettere le piattaforme di destinazione e la versione .NET in base alle esigenze nell'app .NET.

Nota

Ad esempio: se si intende creare solo un'associazione iOS usando .NET 9, è possibile:

  1. Eliminare la libreria di binding Android in template/android/NewBinding.Android.Binding e
  2. Aggiornare il framework di destinazione in template/macios/NewBinding.MaciOS.Binding/NewBinding.MaciOS.Binding.csproj da impostare su net9.0-ios.

Configurare progetti e librerie wrapper nativi

Il modello include anche progetti Android Studio iniziali e progetti Xcode.

Aggiornare i progetti nativi in modo da riflettere le piattaforme e le versioni di destinazione in base alle esigenze nell'app .NET e includere le librerie native di interesse con i passaggi seguenti.

Installazione: iOS e Mac Catalyst

Il progetto Xcode si trova in template/macios/native/NewBinding.

Aggiornare il progetto Xcode in modo che rifletta le piattaforme e le versioni di destinazione supportate nell'app .NET. Nel progetto Xcode fare clic sul framework di primo livello e in Destinazioni > generali:

  1. Aggiungere/rimuovere qualsiasi destinazioni di supporto in base alle esigenze.
  2. Modificare la versione di iOS in base alle esigenze.

Inserire la libreria nativa per iOS e/o MacCatalyst nel progetto Xcode, tramite qualsiasi metodo funziona meglio per la libreria e le proprie esigenze (ad esempio CocoaPods, Swift Gestione pacchetti).

Configurazione: Android

Il progetto Android Studio si trova in template/android/native.

Aggiornare il progetto Android Studio per riflettere le versioni di destinazione supportate nell'app .NET.

  1. Passare al file build.gradle.kts (:app)
  2. Aggiornare la versione in base alle compileSdk esigenze

Inserire la libreria nativa Android tramite gradle

  1. Aggiungere la dipendenza del pacchetto nel blocco delle dipendenze del file build.gradle.kts (:app).
  2. Aggiungere il repository al dependencyResolutionManagement repositories blocco nel file settings.gradle.kts .
  3. Sincronizzare il progetto con i file gradle (tramite il pulsante nell'angolo superiore destro di Android Studio).

Creare l'interfaccia API

Creare l'interfaccia API tra i progetti nativi e i progetti di associazione .NET seguendo questa procedura.

Definizione API: iOS e Mac Catalyst

Sul lato nativo apportare aggiornamenti in template/macios/native/NewBinding/NewBinding/DotnetNewBinding.swift:

  1. Aggiungere un'istruzione import per importare la libreria nativa appena aggiunta.
  2. Scrivere le definizioni API per le API della libreria nativa di interesse.
  3. Assicurarsi che il progetto Xcode venga compilato correttamente e che le API siano soddisfatte.

Tornare sul lato .NET, è ora possibile interagire con la libreria nativa:

  1. Eseguire dotnet build da template/macios/NewBinding.MaciOS.Binding per verificare che tutto sia collegato correttamente e buona scelta. In caso di esito positivo, verranno visualizzate le associazioni C# generate in template/macios/native/NewBinding/bin/Release/net8.0-ios/sharpie/NewBinding/ApiDefinitions.cs.
  2. Aggiornare il contenuto di template/macios/NewBinding.MaciOS.Binding/ApiDefinition.cs sostituendolo con il contenuto di template/macios/native/NewBinding/bin/Release/net8.0-ios/sharpie/NewBinding/ApiDefinitions.cs.
  3. Eseguire dotnet build di nuovo da template/macios/NewBinding.MaciOS.Binding .

Definizione API: Android

Sul lato nativo apportare aggiornamenti in template/android/native/app/src/main/java/com/example/newbinding/DotnetNewBinding.java:

  1. Aggiungere un'istruzione import per importare la libreria nativa appena aggiunta.
  2. Scrivere le definizioni API per le API della libreria nativa di interesse.
  3. Assicurarsi che il progetto Android Studio venga compilato correttamente e che le API siano soddisfatte.

Tornare sul lato .NET, è ora possibile interagire con la libreria nativa:

  1. Eseguire dotnet build da template/android/NewBinding.Android.Binding per verificare che tutto sia collegato correttamente e buona scelta. (Nota: questo passaggio richiederà l'installazione di JDK 17)
  2. Fare riferimento a tutte le dipendenze dell'associazione Android aggiungendo il codice seguente a template/sample/MauiSample.csproj per ogni dipendenza. Sostituire {yourDependencyLibrary.aar} con il file con estensione aar necessario per la dipendenza da associare. Nota: le dipendenze gradle/maven spesso devono essere referenziate in modo esplicito, perché non vengono raggruppate automaticamente nella libreria. Il file build.gradle.kts è configurato per copiare le dipendenze in una cartella bin/outputs/deps a cui fare riferimento nell'applicazione)
<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>

Nota

È possibile rinominare la classe segnaposto DotnetNewBinding per riflettere meglio la libreria nativa di cui viene eseguito il wrapping. Per altri esempi e suggerimenti per la scrittura delle definizioni API, vedere la sezione seguente: Modificare un'associazione esistente.

Usare le API nell'app .NET

Il modello include un'app di esempio .NET MAUI in template/sample/MauiSample, che fa riferimento ai progetti di associazione .NET e rende immediatamente pronte per l'uso le librerie native.

Se si è interessati a usare le proprie app .NET MAUI, .NET per Android, .NET per iOS e/o .NET per Mac Catalyst, tuttavia, è possibile modificarli modificando i file di progetto dell'app .NET per fare riferimento alle librerie di binding:

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

Modificare un'associazione esistente

Se la superficie API esistente non espone le funzionalità necessarie nel proprio progetto, è il momento di apportare modifiche personalizzate.

iOS e Mac Catalyst

All'interno del progetto Xcode troverai uno o più file Swift che definiscono la superficie API pubblica per l'associazione. Ad esempio, il register metodo per Firebase Messaging è definito come:

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

Nota

I tipi di API wrapper nativi che verranno usati dall'associazione .NET devono essere dichiarati come public e devono essere annotati anche con @objc(NameOfType) i metodi publice e possono anche trarre vantaggio da annotazioni @objc(methodName:parameter1:) simili in cui vengono specificati il nome e i parametri che consentono di influenzare l'associazione che verrà generata da sharpie obiettivo.

In questo metodo è possibile notare che la superficie dell'API pubblica usa solo i tipi di cui .NET per iOS è già a conoscenza: NSData, StringNSError e un callback.

Firebase.MaciOS.Binding Nel progetto il file ApiDefinitions.cs contiene la definizione di associazione per questa API wrapper nativa:

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

Si supponga di voler aggiungere un metodo per annullare la registrazione. Il codice Swift sarà simile al seguente:

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

L'altra metà consiste nell'aggiornare il file ApiDefinitions.cs nel progetto di associazione per esporre questo nuovo metodo. È possibile procedere in due modi:

  1. È possibile aggiungere manualmente il codice richiesto
  2. Quando il progetto di associazione viene compilato, l'obiettivo sharpie viene eseguito e un file ApiDefinitions.cs viene generato all'interno della cartella nativa/macios/bin/sharpie (questo percorso varia in base al progetto su cui si sta lavorando naturalmente ). È possibile provare a trovare le modifiche pertinenti da questo file e copiarle manualmente oppure provare a copiare l'intero file e osservare il diff per trovare la parte necessaria.

In questo caso, le modifiche apportate a ApiDefinitions.cs saranno:

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

Dopo aver apportato queste modifiche, è possibile ricompilare il progetto di binding e la nuova API sarà pronta per l'uso dal progetto MAUI .NET.

Nota

I progetti di associazione per Mac/iOS non usano generatori di origine e quindi il sistema di progetto e intelliSense potrebbero non conoscere le nuove API fino a quando non si ricompila il progetto di associazione e ricaricare la soluzione in modo che il riferimento al progetto rilevi l'assembly più recente. Il progetto dell'app deve comunque essere compilato indipendentemente dagli errori intelliSense.

Android

All'interno del progetto Android Studio è disponibile una directory del modulo che contiene un file Java che definisce la superficie api pubblica per l'associazione. Ad esempio, il initialize metodo per Facebook è definito come segue:

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

    // ...
}

In questo metodo è possibile notare che la superficie dell'API pubblica usa solo i tipi di cui .NET per Android è già a conoscenza: Activity e Boolean.

Nel progetto Facebook.Android.Binding il file Transforms/Metadata.xml contiene solo alcuni xml per descrivere come eseguire il mapping del nome del pacchetto Java (com.microsoft.mauifacebook) a uno spazio dei nomi più descrittivo C# (Facebook). In genere i binding Android sono più "automatici" rispetto a Mac/iOS a questo punto e raramente è necessario apportare modifiche a questi file di trasformazione.

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

Si supponga di voler aggiungere un metodo per registrare un evento. Il codice Java sarà simile al seguente:

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

Da questa semplice modifica, il progetto di associazione non richiede aggiornamenti per i file Transforms/Metadata.xml o altri file. È possibile ricompilare semplicemente il progetto binding e la nuova API sarà pronta per l'uso dal progetto MAUI .NET.

Nota

I progetti di associazione per Android non usano generatori di origine e quindi il sistema di progetto e intelliSense potrebbero non conoscere le informazioni sulla nuova API finché non si ricompila il progetto di associazione e ricaricare la soluzione in modo che il riferimento al progetto rilevi l'assembly più recente. Il progetto dell'app deve comunque essere compilato indipendentemente dagli errori intelliSense.