Compartir a través de


Introducción a la interoperabilidad de biblioteca nativa

En este artículo se explica cómo empezar a trabajar con la interoperabilidad de biblioteca nativa mediante Maui.NativeLibraryInterop para simplificar la configuración.

En estas instrucciones se describen los pasos básicos, los puntos de decisión clave y los ejemplos rectores para crear enlaces a través de la interoperabilidad de biblioteca nativa. Para obtener más instrucciones sobre los detalles específicos de la API y la implementación, consulte la documentación de los SDK nativos y las bibliotecas de interés.

Requisitos previos

Instalación de requisitos previos:

Nota:

Es posible instalar el Android SDK o las Herramientas de línea de comandos de Xcode de forma independiente. Sin embargo, la instalación de las Herramientas de línea de comandos de Xcode se controla normalmente a través de Xcode . Del mismo modo, la instalación de Android SDK también se controla usualmente a través de Android Studio o de la Extensión de VS Code de .NET MAUI según la documentación de introducción a .NET MAUI.

Creación de un nuevo enlace

La manera más fácil de empezar a crear un nuevo enlace es clonar la plantilla en el repositorio Maui.NativeLibraryInterop y realizar las modificaciones desde allí. Para comprender mejor todo el alcance de la configuración actual de Maui.NativeLibraryInterop, lea más información en la documentación de información general.

Configuración de las bibliotecas de enlace de .NET

La plantilla incluye .NET de inicio para Android y .NET para bibliotecas de enlace de iOS.

Actualice las bibliotecas de enlace para que reflejen las plataformas de destino y la versión de .NET según sea necesario en su aplicación .NET.

Nota:

Por ejemplo, si tiene como objetivo crear solo un enlace de iOS mediante .NET 9, puede hacer lo siguiente:

  1. Elimine la biblioteca de enlace de Android en template/android/NewBinding.Android.Binding y
  2. Actualice la plataforma de destino en template/macios/NewBinding.MaciOS.Binding/NewBinding.MaciOS.Binding.csproj para que se establezca en net9.0-ios.

Configuración de los proyectos y bibliotecas del contenedor nativo

La plantilla también incluye proyectos iniciales de Android Studio y proyectos de Xcode.

Actualice los proyectos nativos para que reflejen las plataformas y versiones de destino según sea necesario en su aplicación .NET e incluya las bibliotecas nativas de interés con los pasos siguientes.

Configuración: iOS y Mac Catalyst

El proyecto Xcode se encuentra en template/macios/native/NewBinding.

Actualice el proyecto Xcode para que refleje las plataformas y versiones de destino que se admiten en su aplicación .NET. En el proyecto Xcode, haga clic en el marco de nivel superior y en Destinos > General:

  1. Agregue o quite los destinos de soporte según sea necesario.
  2. Ajuste la versión de iOS según sea necesario.

Incorpore la biblioteca nativa para iOS o MacCatalyst en el proyecto Xcode, a través del método que mejor funcione para su biblioteca y sus necesidades (por ejemplo, CocoaPods, Swift Package Manager).

Configuración: Android

El proyecto de Android Studio se encuentra en template/android/native.

Actualice el proyecto de Android Studio para que refleje las versiones de destino admitidas en su aplicación .NET.

  1. Vaya al archivo build.gradle.kts (:app)
  2. Actualice la versión de compileSdk según sea necesario

Incorpore la biblioteca nativa de Android a través de Gradle

  1. Agregue la dependencia de paquete en el bloque de dependencias del archivo build.gradle.kts (:app).
  2. Agregue el repositorio al bloque dependencyResolutionManagementrepositories en el archivo settings.gradle.kts.
  3. Sincronice el proyecto con los archivos gradle (a través del botón de la esquina superior derecha de Android Studio).

Creación de la interfaz de API

Cree la interfaz de API entre los proyectos nativos y los proyectos de enlace de .NET con los pasos siguientes.

Definición de API: iOS y Mac Catalyst

En el lado nativo, realice actualizaciones en template/macios/native/NewBinding/NewBinding/DotnetNewBinding.swift:

  1. Agregue una instrucción import para importar la biblioteca nativa que acaba de agregar.
  2. Escriba las definiciones de API para las API de biblioteca nativas de interés.
  3. Asegúrese de que el proyecto Xcode se compila correctamente y que está satisfecho con las API.

De vuelta en el lado .NET, ahora estamos listos para la interoperabilidad con la biblioteca nativa:

  1. Ejecute dotnet build desde template/macios/NewBinding.MaciOS.Binding para probar que todo está conectado correctamente y listo para funcionar.
  2. Usa Objective Sharpie para generar las vinculaciones de C# para las actualizaciones de la API de Swift.
    1. Vaya a template/macios/NewBinding.MaciOS.Binding/bin/Debug/net9.0-ios/NewBinding.MaciOS.Binding.resources/NewBindingiOS.xcframework/ios-arm64/NewBinding.framework en el directorio de salida de los proyectos de enlace de MaciOS.
    2. Ejecute sharpie xcode -sdks para obtener una lista de valores válidos del SDK de destino para el comando bind. Seleccione el valor que se alinea con la plataforma y la versión que va a usar con el comando siguiente, por ejemplo, iphoneos18.0.
    3. Ejecute sharpie bind para los archivos de encabezado del xcframework creado por el proyecto de enlace.
      sharpie bind --output=sharpie-out --namespace=NewBindingMaciOS --sdk=iphoneos18.0 --scope=Headers Headers/NewBinding-Swift.h
      
    4. Actualice el contenido de template/macios/NewBinding.MaciOS.Binding/ApiDefinition.cs reemplazándolo por el contenido de template/macios/NewBinding.MaciOS.Binding/bin/Debug/net9.0-ios/NewBinding.MaciOS.Binding.resources/NewBindingiOS.xcframework/ios-arm64/NewBinding.framework/sharpie-out/ApiDefinitions.cs y ajuste según sea necesario (por ejemplo, nomenclatura).
    5. Vuelva a ejecutar dotnet build desde template/macios/NewBinding.MaciOS.Binding.

Consulte también la documentación de objective-sharpie para obtener más información sobre esta herramienta.

Definición de API: Android

En el lado nativo, realice actualizaciones en template/android/native/newbinding/src/main/java/com/example/newbinding/DotnetNewBinding.java:

  1. Agregue una instrucción import para importar la biblioteca nativa que acaba de agregar.
  2. Escriba las definiciones de API para las API de biblioteca nativas de interés.
  3. Asegúrese de que el proyecto de Android Studio se compila correctamente y que está satisfecho con las API.

De vuelta en el lado .NET, ahora estamos listos para la interoperabilidad con la biblioteca nativa:

  1. Ejecute dotnet build desde template/android/NewBinding.Android.Binding para probar que todo está conectado correctamente y listo para funcionar. (Nota: Este paso requerirá que tenga JDK 17 instalado)
  2. Haga referencia a las dependencias de vinculación de Android agregando un elemento @(AndroidMavenLibrary) a template/sample/MauiSample.csproj para cada dependencia de maven vinculada en su proyecto Android nativo. Esto habilitará la comprobación de dependencias de Java para el proyecto y hará que las compilaciones posteriores generen advertencias o errores de compilación para las dependencias que faltan. Puede solucionar estas advertencias o errores agregando elementos @(AndroidMavenLibrary) o @(PackageReference) como se sugiere para satisfacer la cadena de dependencias de Java para la biblioteca nativa que está enlazando. (Nota: Las dependencias de gradle/maven a menudo deben hacerse referencia explícitamente, ya que no se agrupan automáticamente en la biblioteca).
<ItemGroup Condition="$(TargetFramework.Contains('android'))">
    <AndroidMavenLibrary Include="{DependencyGroupId}:{DependencyName}" Version="{DependencyVersion}" Bind="false" />
</ItemGroup>

Consulte también la referencia de AndroidMavenLibrary y la documentación de verificación de dependencias de Java para más información sobre este proceso.

Nota:

Puede cambiar el nombre del marcador de posición para la clase DotnetNewBinding, para que refleje mejor la biblioteca nativa que está conteniendo. Para obtener más ejemplos y sugerencias para escribir las definiciones de API, lea más en la sección siguiente: Modificar un enlace existente.

Consumir las API en la aplicación .NET

La plantilla incluye una aplicación de ejemplo .NET MAUI en template/sample/MauiSample, lo que hace referencia a los proyectos de enlace de .NET y hace que las bibliotecas nativas estén listas para usarse inmediatamente.

Sin embargo, si está interesado en usar sus propias aplicaciones .NET MAUI, .NET para Android, .NET para iOS o .NET para Mac Catalyst, puede hacerlo modificando los archivos de proyecto de la aplicación .NET para hacer referencia a las bibliotecas de enlace:

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

Modificación de un enlace existente

Si la superficie de API existente no expone la funcionalidad que necesita en su propio proyecto, es el momento de realizar sus propias modificaciones.

iOS y Mac Catalyst

Dentro del proyecto Xcode, encontrará uno o varios archivos Swift que definen la superficie de API pública para el enlace. Por ejemplo, el método register para Firebase Messaging se define como:

@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:

Los tipos de API de contenedor nativo que usará el enlace de .NET deben declararse como public y deben anotarse con @objc(NameOfType) y los métodos también deben ser public, además, pueden beneficiarse de anotaciones similares @objc(methodName:parameter1:) donde se especifican el nombre y los parámetros que ayudan a influir en el enlace que generará Objective Sharpie.

Puede ver en este método que la superficie de API pública solo usa tipos que .NET para iOS ya conoce: NSData, String, NSError y una devolución de llamada.

En el proyecto Firebase.MaciOS.Binding, el archivo ApiDefinitions.cs contiene la definición de enlace para esta API de contenedor nativo:

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

Supongamos que quiere agregar un método para anular el registro. El código Swift debería tener un aspecto parecido al siguiente:

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

La otra parte consistirá en actualizar el archivo ApiDefinitions.cs en el proyecto de enlace para exponer este nuevo método. Hay dos maneras de hacerlo:

  1. Puede agregar manualmente el código necesario
  2. Después de compilar el proyecto de enlace, puede ejecutar la herramienta objective sharpie para generar un archivo ApiDefinitions.cs. Puede intentar encontrar los cambios relevantes de este archivo y copiarlos manualmente, o intentar copiar todo el archivo y examinar la diferencia para encontrar la parte que necesita.

En este caso, los cambios en ApiDefinitions.cs serían:

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

Una vez realizados estos cambios, puede recompilar el proyecto de enlace y la nueva API estará lista para usarse desde el proyecto .NET MAUI.

Nota:

Los proyectos de enlace para Mac/iOS no usan generadores de origen, por lo que es posible que el sistema de proyectos e IntelliSense no conozcan las nuevas API hasta que haya vuelto a compilar el proyecto de enlace y vuelva a cargar la solución para que la referencia del proyecto recoja el ensamblado más reciente. Su proyecto de aplicación todavía debe compilarse independientemente de los errores de IntelliSense.

Android

Dentro del proyecto de Android Studio encontrará un directorio de módulos que contiene un archivo java que define la superficie de API pública para el enlace. Por ejemplo, el método initialize para Facebook se define como se indica a continuación:

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

    // ...
}

Puede ver en este método que la superficie de API pública solo usa tipos que .NET para Android ya conoce: Activity y Boolean.

En el proyecto Facebook.Android.Binding, el archivo Transforms/Metadata.xml contiene solo algunos xml para describir cómo asignar el nombre del paquete java (com.microsoft.mauifacebook) a un espacio de nombres más amigable para C# (Facebook). Por lo general, los enlaces Android son más "automáticos" que Mac/iOS en este punto, y rara vez debería necesitar hacer cambios en estos archivos de transformación.

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

Supongamos que quiere agregar un método para registrar un evento. El código java debería tener un aspecto parecido al siguiente:

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

A partir de este simple cambio, el proyecto de enlace no requiere actualizaciones del archivo Transforms/Metadata.xml u otros. Simplemente puede recompilar el proyecto de enlace y la nueva API estará lista para usarse desde el proyecto .NET MAUI.

Nota:

Los proyectos de enlace para Android no usan generadores de origen, por lo que es posible que el sistema de proyectos e IntelliSense no conozcan las nuevas API hasta que haya vuelto a compilar el proyecto de enlace y vuelva a cargar la solución para que la referencia del proyecto recoja el ensamblado más reciente. Su proyecto de aplicación todavía debe compilarse independientemente de los errores de IntelliSense.