Partilhar via


Introdução à interoperabilidade de bibliotecas nativas

Este artigo aborda como começar a usar a Interoperabilidade de Biblioteca Nativa usando Maui.NativeLibraryInterop para simplificar a configuração.

Estas instruções descrevem as etapas básicas, os principais pontos de decisão e os exemplos orientadores para a criação de associações por meio da Interoperabilidade de Biblioteca Nativa. Para obter mais orientações sobre API específica e detalhes de implementação, consulte a documentação para os SDKs nativos e bibliotecas de interesse.

Pré-requisitos

Pré-requisitos de instalação:

Observação

É possível instalar o SDK do Android e/ou o Xcode Command Line Tools de forma independente. No entanto, a instalação do Xcode Command Line Tools normalmente é tratada por meio do Xcode. Da mesma forma, a instalação do SDK do Android também é normalmente tratada através do Android Studio e/ou da .NET MAUI VS Code Extension conforme a documentação do .NET MAUI Primeiros Passos.

Criar uma nova ligação

A maneira mais fácil de começar a criar uma nova associação é clonando o modelo de no repositório Maui.NativeLibraryInterop e fazendo modificações a partir daí. Para entender melhor o escopo completo de como o Maui.NativeLibraryInterop está configurado atualmente, leia mais na documentação de visão geral do .

Configurar as bibliotecas de vinculação do .NET

O modelo inclui bibliotecas de vinculação .NET inicial para Android e .NET para iOS.

Atualize as bibliotecas de vinculação para refletir as plataformas de destino e a versão .NET, conforme necessário em seu aplicativo .NET.

Observação

Por exemplo: Se você pretende criar apenas uma associação do iOS usando o .NET 9, você pode:

  1. Exclua a biblioteca de vinculação do Android em template/android/NewBinding.Android.Bindinge
  2. Atualize o framework de destino em template/macios/NewBinding.MaciOS.Binding/NewBinding.MaciOS.Binding.csproj para net9.0-ios.

Configurar os projetos e bibliotecas de wrapper nativos

O modelo também inclui projetos iniciais do Android Studio e projetos Xcode.

Atualize os projetos nativos para refletir as plataformas e versões de destino, conforme necessário, em seu aplicativo .NET e inclua as bibliotecas nativas de interesse com as etapas a seguir.

Configuração: iOS & Mac Catalyst

O projeto Xcode está localizado em template/macios/native/NewBinding.

Atualize o projeto Xcode para refletir as plataformas e versões de destino, conforme suportado em seu aplicativo .NET. No projeto Xcode, clique na estrutura de nível superior e em Targets > General:

  1. Adicione/remova quaisquer destinos de suporte conforme necessário.
  2. Ajuste a versão do iOS conforme necessário.

Traga a biblioteca nativa para iOS e/ou MacCatalyst para seu projeto Xcode, através de qualquer método que funcione melhor para sua biblioteca e suas necessidades (por exemplo, CocoaPods, Swift Package Manager).

Configuração: Android

O projeto Android Studio está localizado em template/android/native.

Atualize o projeto do Android Studio para refletir as versões de destino suportadas em seu aplicativo .NET.

  1. Navegue até o ficheiro build.gradle.kts (:app)
  2. Atualize a versão compileSdk conforme necessário

Traga a biblioteca nativa do Android usando o Gradle

  1. Adicione a dependência do pacote no bloco de dependências do arquivo de build.gradle.kts (:app) .
  2. Adicione o repositório ao bloco no arquivo de settings.gradle.kts .
  3. Sincronize o projeto com arquivos gradle (através do botão no canto superior direito do Android Studio).

Criar a interface da API

Crie a interface de API entre seus projetos nativos e seus projetos de vinculação .NET com as etapas a seguir.

Definição de API: iOS & Mac Catalyst

No lado nativo, faça atualizações em template/macios/native/NewBinding/NewBinding/DotnetNewBinding.swift:

  1. Adicione uma instrução import para importar a biblioteca nativa que você acabou de adicionar.
  2. Escreva as definições de API para as APIs de biblioteca nativa de interesse.
  3. Certifique-se de que o projeto Xcode seja compilado com êxito e que esteja satisfeito com as APIs.

De volta ao lado do .NET, agora estamos prontos para interoperar com a biblioteca nativa:

  1. Execute dotnet build a partir do template/macios/NewBinding.MaciOS.Binding para testar se tudo está conectado corretamente e pronto.
  2. Use o sharpie objetivo para gerar as ligações C# para suas atualizações da API Swift:
    1. Navegue até template/macios/NewBinding.MaciOS.Binding/bin/Debug/net9.0-ios/NewBinding.MaciOS.Binding.resources/NewBindingiOS.xcframework/ios-arm64/NewBinding.framework na pasta de saída dos projetos de vinculação MaciOS.
    2. Execute sharpie xcode -sdks para obter uma lista de valores válidos do SDK de destino para o comando bind. Selecione o valor que se alinha com a plataforma e a versão que você está segmentando para usar com o próximo comando, por exemplo, iphoneos18.0.
    3. Execute sharpie bind nos arquivos de cabeçalho no xcframework criado pelo projeto de vinculação:
      sharpie bind --output=sharpie-out --namespace=NewBindingMaciOS --sdk=iphoneos18.0 --scope=Headers Headers/NewBinding-Swift.h
      
    4. Atualize o conteúdo de template/macios/NewBinding.MaciOS.Binding/ApiDefinition.cs, substituindo-o pelo conteúdo 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, e ajustando conforme necessário (por exemplo, a nomenclatura).
    5. Execute novamente o dotnet build a partir do template/macios/NewBinding.MaciOS.Binding.

Consulte também a documentação objetiva-sharpie para saber mais sobre esta ferramenta.

Definição de API: Android

No lado nativo, efetue atualizações em template/android/native/newbinding/src/main/java/com/example/newbinding/DotnetNewBinding.java:

  1. Adicione uma instrução import para importar a biblioteca nativa que você acabou de adicionar.
  2. Escreva as definições de API para as APIs de biblioteca nativa de interesse.
  3. Certifique-se de que o projeto do Android Studio seja compilado com êxito e que esteja satisfeito com as funcionalidades das APIs.

De volta ao lado do .NET, agora estamos prontos para interoperar com a biblioteca nativa:

  1. Execute dotnet build a partir do template/android/NewBinding.Android.Binding para testar se tudo está conectado corretamente e está pronto para funcionar. (Nota: Esta etapa exigirá que você tenha o JDK 17 instalado)
  2. Faça referência a quaisquer dependências de vinculação do Android, adicionando um item de @(AndroidMavenLibrary) ao exemplo de modelo /MauiSample.csproj, para cada dependência maven que está a ser vinculada no seu projeto Android nativo. Isso habilitará a verificação de dependência Java para seu projeto e fará com que compilações subsequentes produzam avisos de compilação ou erros para dependências ausentes. Você pode resolver esses avisos/erros adicionando elementos @(AndroidMavenLibrary) ou @(PackageReference) conforme sugerido para satisfazer a cadeia de dependência da biblioteca nativa Java à qual você está vinculando. (Observação: as dependências gradle/maven geralmente precisam ser explicitamente referenciadas, pois não são agrupadas automaticamente em sua biblioteca.)
<ItemGroup Condition="$(TargetFramework.Contains('android'))">
    <AndroidMavenLibrary Include="{DependencyGroupId}:{DependencyName}" Version="{DependencyVersion}" Bind="false" />
</ItemGroup>

Consulte também a referência AndroidMavenLibrary e a documentação de verificação de dependência Java para obter mais informações sobre este processo.

Observação

Você pode renomear o espaço reservado DotnetNewBinding classe para refletir melhor a biblioteca nativa que está sendo encapsulada. Para obter mais exemplos e dicas para escrever as definições de API, leia mais na seção abaixo: Modificar uma ligação existente.

Consumir as APIs em seu aplicativo .NET

O modelo inclui um aplicativo de exemplo .NET MAUI em template/sample/MauiSample, que faz referência aos projetos de vinculação .NET e torna as bibliotecas nativas imediatamente prontas para uso!

Se você estiver interessado em usar seus próprios aplicativos .NET MAUI, .NET para Android, .NET para iOS e/ou .NET para Mac Catalyst, no entanto, você pode fazer isso modificando seus arquivos de projeto de aplicativo .NET para fazer referência às bibliotecas de vinculação:

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

Modificar uma ligação existente

Se a superfície da API existente não expõe a funcionalidade que você precisa em seu próprio projeto, é hora de fazer suas próprias modificações!

iOS & Mac Catalyst

Dentro do projeto Xcode, você encontrará um ou mais arquivos Swift que definem a superfície da API pública para a ligação. Por exemplo, o método register para Firebase Messaging é definido 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?)
        })
    }
    // ...
}

Observação

Os tipos de API de wrapper nativos que serão usados pela Vinculação .NET devem ser declarados como public, precisam ser anotados com @objc(NameOfType), e os métodos também devem ser public. Além disso, podem se beneficiar de anotações semelhantes @objc(methodName:parameter1:), onde o nome e os parâmetros são especificados, ajudando a influenciar a vinculação que o sharpie objetivo gerará.

Você pode ver neste método que a superfície de API pública usa apenas tipos que o .NET para iOS já conhece: NSData, String, NSError e um retorno de chamada.

No projeto Firebase.MaciOS.Binding, o arquivo ApiDefinitions.cs contém a definição de associação para essa API de 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);
        // ...
    }

Digamos que você queira adicionar um método para cancelar o registro. O código Swift seria mais ou menos assim:

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

A outra metade consistirá em atualizar o arquivo ApiDefinitions.cs no projeto de vinculação para expor este novo método. Há duas maneiras de fazer isso:

  1. Você pode adicionar manualmente o código necessário
  2. Depois de criar o projeto de vinculação, pode executar a ferramenta objective sharpie para gerar um arquivo ApiDefinitions.cs. Você pode tentar encontrar as alterações relevantes deste arquivo e copiá-las manualmente, ou tentar copiar todo o arquivo e olhar para o diff para encontrar a parte que você precisa.

Neste caso, as alterações ao ApiDefinitions.cs seriam:

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

Depois de fazer essas alterações, você pode reconstruir o projeto Binding e a nova API estará pronta para uso do seu projeto .NET MAUI.

Observação

Projetos de vinculação para Mac/iOS não estão usando geradores de código-fonte e, portanto, o sistema de projeto e o intellisense podem não saber sobre as novas APIs até que você tenha reconstruído o projeto de vinculação e recarregado a solução para que a referência do projeto pegue o assembly mais recente. Seu projeto de aplicativo ainda deve ser compilado, independentemente dos erros do intellisense.

Androide

Dentro do projeto Android Studio você encontrará um diretório de módulo que contém um arquivo java definindo a superfície de API pública para a ligação. Por exemplo, o método initialize para Facebook é definido como abaixo:

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

    // ...
}

Você pode ver neste método que a superfície de API pública usa apenas tipos que o .NET para Android já conhece: Activity e Boolean.

No projeto Facebook.Android.Binding, o ficheiro Transforms/Metadata.xml contém apenas alguns arquivos XML para descrever como mapear o nome do pacote do Java (com.microsoft.mauifacebook) para um nome do espaço de nomes mais amigável em C# (Facebook). Geralmente as ligações do Android são mais 'automáticas' do que o Mac / iOS neste momento, e você raramente deve precisar fazer alterações nesses arquivos de transformação.

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

Digamos que você queira adicionar um método para registrar um evento. O código java seria mais ou menos assim:

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

A partir desta simples alteração, o projeto de vinculação não requer atualizações para o Transforms/Metadata.xml ou outros ficheiros. Você pode simplesmente reconstruir o projeto Binding e a nova API estará pronta para uso a partir do seu projeto .NET MAUI.

Observação

Projetos de vinculação para Android não estão usando geradores de código-fonte e, portanto, o sistema de projeto e o intellisense podem não saber sobre as novas APIs até que você tenha reconstruído o projeto de vinculação e recarregado a solução para que a referência do projeto pegue o assembly mais recente. Seu projeto de aplicativo ainda deve ser compilado, independentemente dos erros do intellisense.