Associação de uma biblioteca Java

A comunidade Android tem muitas bibliotecas Java que talvez você queira usar em seu aplicativo; este guia explica como incorporar bibliotecas Java em seu aplicativo Xamarin.Android criando uma Biblioteca de Associações.

Visão geral

O ecossistema de biblioteca de terceiros para Android é enorme. Por isso, frequentemente faz sentido usar uma biblioteca existente do Android do que criar uma nova. O Xamarin.Android oferece duas maneiras de usar essas bibliotecas:

  • Crie uma Biblioteca de Associações que encapsula automaticamente a biblioteca com wrappers C# para que você possa invocar o código Java por meio de chamadas C#.

  • Use a JNI (Java Native Interface) para invocar chamadas diretamente no código da biblioteca Java. O JNI é uma estrutura de programação que permite que o código Java chame e seja chamado por aplicativos ou bibliotecas nativos.

Este guia explica a primeira opção: como criar uma Biblioteca de Associações que encapsula uma ou mais bibliotecas Java existentes em um assembly ao qual você pode vincular em seu aplicativo. Para obter mais informações sobre como usar o JNI, consulte Trabalhando com JNI.

O Xamarin.Android implementa associações usando MCW (Managed Callable Wrappers). MCW é uma ponte JNI usada quando o código gerenciado precisa invocar o código Java. Os wrappers callable gerenciados também dão suporte para subclasse de tipos Java e para substituir métodos virtuais em tipos Java. Da mesma forma, sempre que o código ART (Runtime do Android) quiser invocar o código gerenciado, ele o fará por meio de outra ponte JNI conhecida como ACW (Android Callable Wrappers). Essa arquitetura é ilustrada no diagrama a seguir:

Arquitetura da ponte JNI do Android

Uma Biblioteca de Associações é um assembly que contém Wrappers Callable Gerenciados para tipos Java. Por exemplo, aqui está um tipo Java, MyClass, que desejamos encapsular em uma Biblioteca de Associações:

package com.xamarin.mycode;

public class MyClass
{
    public String myMethod (int i) { ... }
}

Depois de gerarmos uma Biblioteca de Associações para o .jar que contém MyClass, podemos instanciá-la e chamar métodos nela do C#:

var instance = new MyClass ();

string result = instance.MyMethod (42);

Para criar essa Biblioteca de Associações, use o modelo Biblioteca de Associações Java do Xamarin.Android. O projeto de associação resultante cria um assembly do .NET com as classes MCW, arquivos .jar e recursos para projetos da Biblioteca do Android inseridos nele. Você também pode criar bibliotecas de associações para arquivos android (. Arquivos AAR) e projetos da Biblioteca Android do Eclipse. Ao referenciar o assembly de DLL da Biblioteca de Associações resultante, você pode reutilizar uma biblioteca Java existente em seu projeto Xamarin.Android.

Ao referenciar tipos em sua Biblioteca de Associação, você deve usar o namespace da biblioteca de associação. Normalmente, você adiciona uma using diretiva na parte superior dos arquivos de origem C# que é a versão do namespace do .NET do nome do pacote Java. Por exemplo, se o nome do pacote Java para seu .jar associado for o seguinte:

com.company.package

Em seguida, você colocaria a seguinte using instrução na parte superior dos arquivos de origem C# para acessar tipos no arquivo .jar associado:

using Com.Company.Package;

Ao associar uma biblioteca existente do Android, é necessário ter os seguintes pontos em mente:

  • Há dependências externas para a biblioteca? – Todas as dependências java exigidas pela biblioteca do Android devem ser incluídas no projeto Xamarin.Android como um ReferenceJar ou como um EmbeddedReferenceJar. Todos os assemblies nativos devem ser adicionados ao projeto de associação como um EmbeddedNativeLibrary.

  • Qual versão da API do Android o destino da biblioteca do Android? – Não é possível "fazer downgrade" do nível da API do Android; verifique se o projeto de associação do Xamarin.Android está direcionando o mesmo nível de API (ou superior) que a biblioteca do Android.

  • Qual versão do JDK foi usada para compilar a biblioteca? – Erros de associação podem ocorrer se a biblioteca do Android foi criada com uma versão diferente do JDK do que em uso pelo Xamarin.Android. Se possível, recompile a biblioteca do Android usando a mesma versão do JDK usada pela instalação do Xamarin.Android.

Ações de Build

Ao criar uma Biblioteca de Associações, você define ações de build no .jar ou . Arquivos AAR que você incorpora ao projeto da Biblioteca de Associações – cada ação de build determina como o .jar ou o . O arquivo AAR será inserido (ou referenciado por) em sua Biblioteca de Associações. A lista a seguir resume estas ações de build:

  • EmbeddedJar – Insere o .jar na DLL da Biblioteca de Associações resultante como um recurso inserido. Essa é a ação de build mais simples e usada com mais frequência. Use essa opção quando quiser que o .jar seja compilado automaticamente no código de bytes e empacotado na Biblioteca de Associações.

  • InputJar – Não insira o .jar na biblioteca de associações resultante .DLL. A biblioteca de associações .DLL terá uma dependência desse .jar no runtime. Use essa opção quando não quiser incluir o .jar em sua Biblioteca de Associações (por exemplo, por motivos de licenciamento). Se você usar essa opção, deverá garantir que o .jar de entrada esteja disponível no dispositivo que executa seu aplicativo.

  • LibraryProjectZip – Insere um . Arquivo AAR na biblioteca de associações resultante .DLL. Isso é semelhante ao EmbeddedJar, exceto que você pode acessar recursos (bem como código) no associado. Arquivo AAR. Use essa opção quando quiser inserir um . AAR em sua Biblioteca de Associações.

  • ReferenceJar – Especifica uma referência .jar: um .jar de referência é um .jar que um dos seus .jar ou . Os arquivos AAR dependem. Esse .jar de referência é usado apenas para atender a dependências de tempo de compilação. Quando você usa essa ação de build, as associações C# não são criadas para o .jar de referência e não são inseridas na biblioteca de associações resultante .DLL. Use essa opção quando você criar uma Biblioteca de Associações para o .jar de referência, mas ainda não tiver feito isso. Essa ação de build é útil para empacotar vários .jars (e/ou . AARs) em várias bibliotecas de associações interdependentes.

  • EmbeddedReferenceJar – Insira um .jar de referência no .DLL resultante da Biblioteca de Associações. Use essa ação de build quando quiser criar associações C# para o .jar de entrada (ou . AAR) e todos os seus .jar(s) de referência em sua Biblioteca de Associações.

  • EmbeddedNativeLibrary – Insira um .so nativo na associação. Essa ação de build é usada para arquivos .so que são exigidos pelo arquivo .jar que está sendo associado. Pode ser necessário carregar manualmente a biblioteca .so antes de executar o código da biblioteca Java. Isso é descrito abaixo.

Essas ações de build são explicadas mais detalhadamente nos guias a seguir.

Além disso, as seguintes ações de build são usadas para ajudar a importar a documentação da API Java e convertê-las na documentação XML do C#:

  • JavaDocJar é usado para apontar para o Jar de arquivo Javadoc para uma biblioteca Java que está em conformidade com um estilo de pacote Maven (geralmente FOOBAR-javadoc**.jar**).
  • JavaDocIndex é usado para apontar para index.html o arquivo dentro do HTML da documentação de referência da API.
  • JavaSourceJar é usado para complementar JavaDocJar, para primeiro gerar JavaDoc de fontes e, em seguida, tratar os resultados como JavaDocIndex, para uma biblioteca Java que está em conformidade com um estilo de pacote Maven (geralmente FOOBAR-sources**.jar**).

A documentação da API deve ser o doclet padrão do Java8, Java7 ou Java6 SDK (todos eles são formatos diferentes) ou o estilo DroidDoc.

Incluindo uma biblioteca nativa em uma associação

Pode ser necessário incluir uma biblioteca .so em um projeto de associação do Xamarin.Android como parte da associação de uma biblioteca Java. Quando o código Java encapsulado for executado, o Xamarin.Android falhará ao fazer a chamada JNI e a mensagem de erro java.lang.UnsatisfiedLinkError: método nativo não encontrado: aparecerá no logcat para o aplicativo.

A correção para isso é carregar manualmente a biblioteca .so com uma chamada para Java.Lang.JavaSystem.LoadLibrary. Por exemplo, supondo que um projeto Xamarin.Android tenha biblioteca compartilhada libpocketsphinx_jni.so incluído no projeto de associação com uma ação de build de EmbeddedNativeLibrary, o snippet a seguir (executado antes de usar a biblioteca compartilhada) carregará a biblioteca .so :

Java.Lang.JavaSystem.LoadLibrary("pocketsphinx_jni");

Adaptando APIs Java a C⧣

O Gerador de Associação do Xamarin.Android alterará alguns padrões e expressões Java para corresponder aos padrões do .NET. A lista a seguir descreve como o Java é mapeado para C#/.NET:

  • Os métodos Setter/Getter em Java são Propriedades no .NET.

  • Os campos em Java são Propriedades no .NET.

  • Ouvintes/interfaces de ouvinte em Java são eventos no .NET. Os parâmetros dos métodos nas interfaces de retorno de chamada serão representados por uma EventArgs subclasse.

  • Uma classe Estática Aninhada em Java é uma classe Aninhada no .NET.

  • Uma classe Inner em Java é uma classe Aninhada com um construtor de instância em C#.

Cenários de associação

Os seguintes guias de cenário de associação podem ajudá-lo a associar uma biblioteca Java (ou bibliotecas) para incorporação em seu aplicativo:

  • Associando um . JAR é um passo a passo para criar bibliotecas de associações para arquivos .jar .

  • Associando um . O AAR é um passo a passo para criar bibliotecas de associações para . Arquivos AAR. Leia este passo a passo para saber como associar bibliotecas do Android Studio.

  • Associar um projeto de biblioteca do Eclipse é um passo a passo para criar bibliotecas de associação de projetos de biblioteca do Android. Leia este passo a passo para saber como associar projetos de biblioteca android do Eclipse.

  • Personalizar Associações explica como fazer modificações manuais na associação para resolve erros de build e formatar a API resultante para que ela seja mais "semelhante a C#".

  • A solução de problemas de associações lista cenários comuns de erro de associação, explica possíveis causas e oferece sugestões para resolver esses erros.