Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Uma Biblioteca de Ligação Java .NET para Android tenta automatizar grande parte do trabalho necessário para ligar uma biblioteca Android existente com a ajuda de uma ferramenta por vezes conhecida como Gerador de Ligações. Ao ligar uma biblioteca Java, o .NET para Android inspeciona as classes Java e gera uma lista de todos os pacotes, tipos e membros a vincular. Esta lista de APIs está armazenada num ficheiro XML que pode ser encontrado em {project directory}\obj{Configuration}\api.xml.
O Gerador de Ligações utilizará o ficheiroapi.xml como orientação para gerar as classes de wrapper C# necessárias. O seguinte excerto é um exemplo do conteúdo de api.xml:
<api>
<package name="android">
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object"
extends-generic-aware="java.lang.Object"
final="true"
name="Manifest"
static="false"
visibility="public">
<constructor deprecated="not deprecated" final="false"
name="Manifest" static="false" type="android.Manifest"
visibility="public">
</constructor>
</class>
...
</api>
Neste exemplo, api.xml declara uma classe no android pacote chamado Manifest que estende o java.lang.Object.
Em muitos casos, é necessária assistência humana para que a API Java se assemelhe mais ao '.NET' ou para corrigir problemas que impedem a compilação do conjunto de associação. Por exemplo, pode ser necessário alterar os nomes dos pacotes Java para espaços de nomes .NET, renomear uma classe ou alterar o tipo de retorno de um método.
Estas alterações não devem ser conseguidas modificandoapi.xml diretamente. Em vez disso, as alterações são registadas em ficheiros XML especiais fornecidos pelo modelo Java Binding Library. Ao compilar o conjunto de binding .NET para Android, o Gerador de Ligações será influenciado por estes ficheiros de mapeamento ao criar o conjunto de binding
O ficheiroMetadata.xml é o mais importante destes ficheiros, pois permite alterações gerais à ligação, tais como:
Renomear namespaces, classes, métodos ou campos para que sigam as convenções do .NET.
Remover namespaces, classes, métodos ou campos que não são necessários.
Mover classes para diferentes namespaces.
Adicionar classes de suporte adicionais para que o design do binding siga padrões do framework .NET.
ficheiro de transformação Metadata.xml
Como já aprendemos, o ficheiro Metadata.xml é usado pelo Gerador de Ligações para influenciar a criação do assembly de ligação. O formato de metadados utiliza a sintaxe XPath .
Esta implementação é quase uma implementação completa do XPath 1.0 e, por isso, suporta itens do padrão 1.0. Este ficheiro é um poderoso mecanismo baseado em XPath para alterar, adicionar, ocultar ou mover qualquer elemento ou atributo no ficheiro API. Todos os elementos da regra na especificação de metadados incluem um path atributo para identificar o(s) nó(s) ao qual a regra deve ser aplicada. Seguem-se os tipos de elementos disponíveis:
- add-node – Adiciona um nó filho ao nó especificado pelo atributo path.
- attr – Define o valor de um atributo do elemento especificado pelo atributo caminho.
- remove-node – Remove nós que correspondam a um XPath especificado.
Segue-se um exemplo de ficheiro Metadata.xml :
<metadata>
<!-- Normalize the namespace for .NET -->
<attr path="/api/package[@name='com.evernote.android.job']"
name="managedName">Evernote.AndroidJob</attr>
<!-- Don't need these packages for the .NET for Android binding/public API -->
<remove-node path="/api/package[@name='com.evernote.android.job.v14']" />
<remove-node path="/api/package[@name='com.evernote.android.job.v21']" />
<!-- Change a parameter name from the generic p0 to a more meaningful one. -->
<attr path="/api/package[@name='com.evernote.android.job']/class[@name='JobManager']/method[@name='forceApi']/parameter[@name='p0']"
name="name">api</attr>
</metadata>
Segue-se a lista alguns dos elementos XPath mais usados para as APIs Java:
interface– Usado para localizar uma interface Java. por exemplo,/interface[@name='AuthListener'].class– Usado para localizar uma classe . por exemplo,/class[@name='MapView'].method– Usado para localizar um método numa classe ou interface Java. por exemplo,/class[@name='MapView']/method[@name='setTitleSource'].parameter– Identificar um parâmetro para um método. por exemplo,/parameter[@name='p0']
Adição de tipos
O add-node elemento irá indicar ao projeto .NET for Android binding para adicionar uma nova classe ao api.xml. Por exemplo, o seguinte excerto direcionará o Gerador de Ligação para criar uma classe com um construtor e um único campo:
<add-node path="/api/package[@name='org.alljoyn.bus']">
<class abstract="false" deprecated="not deprecated" final="false" name="AuthListener.AuthRequest" static="true" visibility="public" extends="java.lang.Object">
<constructor deprecated="not deprecated" final="false" name="AuthListener.AuthRequest" static="false" type="org.alljoyn.bus.AuthListener.AuthRequest" visibility="public" />
<field name="p0" type="org.alljoyn.bus.AuthListener.Credentials" />
</class>
</add-node>
Remoção de tipos
É possível instruir o Gerador de Bindings .NET para Android a ignorar um tipo de Java e não o ligar. Isto é feito adicionando um remove-node elemento XML ao ficheiroMetadata.xml :
<remove-node path="/api/package[@name='{package_name}']/class[@name='{name}']" />
Renomeação dos membros
Não se pode renomear membros editando diretamente o ficheiro api.xml porque o .NET para Android requer os nomes originais da Java Native Interface (JNI) para comunicar com o Java. Portanto, o atributo //class/@name não pode ser alterado; se for, a ligação não funcionará.
Considere o caso em que queremos renomear um tipo, android.Manifest.
Para conseguir isso, podemos tentar editar api.xml diretamente e renomear a classe assim:
<attr path="/api/package[@name='android']/class[@name='Manifest']"
name="name">NewName</attr>
Isto resultará no Gerador de Ligações a criar o seguinte código C# para a classe wrapper:
[Register ("android/NewName")]
public class NewName : Java.Lang.Object { ... }
Note que a classe wrapper foi renomeada para NewName, enquanto o tipo Java original ainda é Manifest. Já não é possível que a classe de ligação .NET para Android aceda a quaisquer métodos em android.Manifest; a classe wrapper está ligada a um tipo Java inexistente.
Para alterar corretamente o nome "gerenciado" de um tipo (ou método) enrolado, é necessário definir o managedName atributo como mostrado neste exemplo:
<attr path="/api/package[@name='android']/class[@name='Manifest']"
name="managedName">NewName</attr>
A utilização managedName é necessária ao tentar renomear qualquer membro, como classes, interfaces, métodos e parâmetros.
Renomeação EventArg das classes de invólucro
Quando o gerador de bindings .NET para Android identifica um método definidor para um tipo de ouvinte, um evento C# e uma subclasse serão gerados para suportar uma API no estilo .NET para o padrão de listener baseado em Java. Como exemplo, considere a seguinte classe e método Java:
com.someapp.android.mpa.guidance.NavigationManager.on2DSignNextManuever(NextManueverListener listener);
.NET para Android elimina o prefixo on do método setter e usa 2DSignNextManuever como base para o nome da EventArgs subclasse. A subclasse terá um nome semelhante a:
NavigationManager.2DSignNextManueverEventArgs
Este não é um nome legal para a classe C#. Para corrigir este problema, o autor da ligação deve usar o argsType atributo e fornecer um nome válido em C# para a EventArgs subclasse:
<attr path="/api/package[@name='com.someapp.android.mpa.guidance']/
interface[@name='NavigationManager.Listener']/
method[@name='on2DSignNextManeuver']"
name="argsType">NavigationManager.TwoDSignNextManueverEventArgs</attr>
Atributos suportados
As secções seguintes descrevem alguns dos atributos para transformar APIs Java.
argsType
Este atributo é colocado nos métodos setter para nomear a EventArg subclasse que será gerada para suportar os listeners Java. Isto é descrito com mais detalhe na secção Renomear EventArg Wrapper Classes neste guia.
nome_do_evento
Especifica um nome para um evento. Se o nome estiver vazio, impede a geração de eventos. Isto é descrito com mais detalhe na secção Nomear EventArg Wrapper Classes.
managedName
Isto é usado para alterar o nome de um pacote, classe, método ou parâmetro. Por exemplo, para mudar o nome da classe MyClass Java para NewClassName:
<attr path="/api/package[@name='com.my.application']/class[@name='MyClass']"
name="managedName">NewClassName</attr>
O exemplo seguinte ilustra uma expressão XPath para renomear o método java.lang.object.toString para Java.Lang.Object.NewManagedName:
<attr path="/api/package[@name='java.lang']/class[@name='Object']/method[@name='toString']"
name="managedName">NewMethodName</attr>
managedType
managedType é usado para alterar o tipo de retorno de um método. Em algumas situações, o Gerador de Ligações inferirá incorretamente o tipo de retorno de um método Java, o que resultará num erro em tempo de compilação. Uma possível solução nesta situação é alterar o tipo de retorno do método.
Por exemplo, o Gerador de Ligações acredita que o método de.neom.neoreadersdk.resolution.compareTo() Java deve devolver um int e tomar Object como parâmetros, o que resulta na mensagem de erro Erro CS0535: 'DE. Neom.Neoreadersdk.Resolution' não implementa o membro de interface 'Java.Lang.IComparable.CompareTo(Java.Lang.Object)'.
O snippet seguinte demonstra como alterar o tipo do primeiro parâmetro do método C# gerado de a DE.Neom.Neoreadersdk.Resolution para a Java.Lang.Object:
<attr path="/api/package[@name='de.neom.neoreadersdk']/
class[@name='Resolution']/
method[@name='compareTo' and count(parameter)=1 and
parameter[1][@type='de.neom.neoreadersdk.Resolution']]/
parameter[1]" name="managedType">Java.Lang.Object</attr>
managedReturn
Altera o tipo de retorno de um método. Isto não altera o atributo de retorno (pois alterações aos atributos de retorno podem resultar em alterações incompatíveis na assinatura JNI). No exemplo seguinte, o tipo de retorno append do método é alterado de SpannableStringBuilder para IAppendable:
<attr path="/api/package[@name='android.text']/
class[@name='SpannableStringBuilder']/
method[@name='append']"
name="managedReturn">Java.Lang.IAppendable</attr>
Ofuscado
Ferramentas que ofuscam bibliotecas Java podem interferir com o .NET for Android Binding Generator e a sua capacidade de gerar classes wrapper em C#. As características das classes ofuscadas incluem:
- O nome da classe inclui um $, ou seja, a$.class
- O nome da classe é totalmente composto por caracteres minúsculos, ou seja, a.class
Este excerto é um exemplo de como gerar um tipo C# "não ofuscado":
<attr path="/api/package[@name='{package_name}']/class[@name='{name}']"
name="obfuscated">false</attr>
propertyName
Este atributo pode ser usado para alterar o nome de uma propriedade gerida.
Um caso especializado de utilização propertyName envolve a situação em que uma classe Java tem apenas um método setter para um campo. Nesta situação, o Gerador de Binding iria querer criar uma propriedade apenas de escrita, algo que é desencorajado no .NET. O seguinte excerto mostra como "remover" as propriedades do .NET definindo o propertyName para uma cadeia vazia:
<attr path="/api/package[@name='org.java_websocket.handshake']/class[@name='HandshakeImpl1Client']/method[@name='setResourceDescriptor'
and count(parameter)=1
and parameter[1][@type='java.lang.String']]"
name="propertyName"></attr>
<attr path="/api/package[@name='org.java_websocket.handshake']/class[@name='HandshakeImpl1Client']/method[@name='getResourceDescriptor'
and count(parameter)=0]"
name="propertyName"></attr>
Note que os métodos setter e getter continuarão a ser criados pelo Bindings Generator, só que não serão convertidos para uma propriedade .NET.
remetente
Especifica qual parâmetro de um método deve atuar como o parâmetro sender quando o método é mapeado para um evento. O valor pode ser true ou false. Por exemplo:
<attr path="/api/package[@name='android.app']/
interface[@name='TimePickerDialog.OnTimeSetListener']/
method[@name='onTimeSet']/
parameter[@name='view']"
name="sender">true</ attr>
Visibilidade
Este atributo é usado para alterar a visibilidade de uma classe, método ou propriedade. Por exemplo, pode ser necessário promover um protected método Java para que o seu wrapper C# correspondente seja public:
<!-- Change the visibility of a class -->
<attr path="/api/package[@name='namespace']/class[@name='ClassName']" name="visibility">public</attr>
<!-- Change the visibility of a method -->
<attr path="/api/package[@name='namespace']/class[@name='ClassName']/method[@name='MethodName']" name="visibility">public</attr>