Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A associação de um arquivo de biblioteca Android (um arquivo .aar ou .jar) raramente é uma tarefa simples; geralmente requer esforço adicional para mitigar problemas resultantes das diferenças entre Java e .NET. Esses problemas impedirão que o .NET para Android vincule a biblioteca do Android e se apresente como mensagens de erro no log de build. Este guia fornecerá algumas dicas para solucionar os problemas, listar alguns dos problemas/cenários mais comuns e fornecer possíveis soluções para vincular com êxito a biblioteca do Android.
Ao vincular uma biblioteca Android existente, é necessário ter em mente os seguintes pontos:
As dependências externas da biblioteca – todas as dependências Java exigidas pela biblioteca do Android devem ser incluídas no projeto .NET para Android por meio de um pacote NuGet ou como uma AndroidLibrary.
O nível de API do Android que a biblioteca do Android está visando – não é possível ter um nível de API inferior no Android; certifique-se de que o binding project .NET para Android está visando o mesmo nível de API (ou superior) que a biblioteca do Android.
Dica
O wiki do repositório GitHub do Binding Tooling é um ótimo recurso e contém informações adicionais de solução de problemas que podem ajudar em casos específicos.
A primeira etapa para solucionar problemas com a associação de uma biblioteca do .NET para Android é habilitar a saída de diagnóstico do MSBuild. Depois de habilitar a saída de diagnóstico, recompile o projeto de associação do .NET para Android e examine o log de build para localizar pistas sobre qual é a causa do problema.
Também pode ser útil descompilar a biblioteca do Android e examinar os tipos e métodos que o .NET para Android está tentando associar. Isso é abordado com mais detalhes posteriormente neste guia.
Descompilando uma biblioteca do Android
Inspecionar as classes e métodos das classes Java pode fornecer informações valiosas que ajudarão na ligação de uma biblioteca. JD-GUI é um utilitário gráfico que pode exibir o código-fonte Java dos arquivos CLASS contidos em um JAR.
Para descompilar uma biblioteca do Android, abra o arquivo . JAR com o descompilador Java. Se a biblioteca for um arquivo .AAR, o código-fonte Java estará na entrada classes.jar do arquivo. Veja a seguir um exemplo de captura de tela do uso do JD-GUI para analisar o JAR do Picasso:
Depois de descompilar a biblioteca do Android, examine o código-fonte. De um modo geral, procure :
Classes que têm características de ofuscação – 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
importinstruções para bibliotecas não referenciadas – identifique a biblioteca não referenciada e adicione essas dependências ao projeto de associação do .NET para Android com uma associação apropriada do NuGet ou com uma ação de build de AndroidLibrary.
Observação
A descompilação de uma biblioteca Java pode ser proibida ou sujeita a restrições legais com base nas leis locais ou na licença sob a qual a biblioteca Java foi publicada. Se necessário, conte com os serviços de um profissional jurídico antes de tentar descompilar uma biblioteca Java e inspecionar o código-fonte.
Inspecione api.xml
Como parte da criação de um projeto de associação, o .NET para Android gerará um nome de arquivo XML obj/Debug/api.xml:
Esse arquivo fornece uma lista de todas as APIs Java que o .NET para Android está tentando associar. O conteúdo desse arquivo pode ajudar a identificar quaisquer tipos ou métodos ausentes, associação duplicada. Embora a inspeção desse arquivo seja tediosa e demorada, ela pode fornecer pistas sobre o que pode estar causando problemas de vinculação. Por exemplo, api.xml pode revelar que uma propriedade está retornando um tipo inadequado ou que há dois tipos que compartilham o mesmo nome gerenciado.
Problemas conhecidos
Esta seção listará algumas das mensagens de erro ou sintomas comuns que ocorrem ao tentar vincular uma biblioteca do Android.
Problema: tipos C# ausentes na saída gerada.
A associação .dll compila, mas perde alguns tipos Java ou a origem C# gerada não é compilada devido a um erro informando que há tipos ausentes.
Causas possíveis::
Esse erro pode ocorrer devido a vários motivos, conforme listado abaixo:
A biblioteca que está sendo vinculada pode fazer referência a uma segunda biblioteca Java. Se a API pública da biblioteca associada usar tipos da segunda biblioteca, você também deverá fazer referência a uma associação gerenciada para a segunda biblioteca.
Java permite derivar uma classe pública de uma classe não pública, mas isso não tem suporte no .NET. Como o gerador de associação não gera associações para classes não públicas, classes derivadas como essas não podem ser geradas corretamente. Para corrigir isso, remova a entrada de metadados para essas classes derivadas usando o nó de remoção no Metadata.xml ou corrija os metadados que estão tornando a classe não pública pública. Embora a última solução crie a vinculação para que o código-fonte C# seja compilado, a classe não pública não deve ser usada.
Por exemplo:
<attr path="/api/package[@name='com.some.package']/class[@name='SomeClass']" name="visibility">public</attr>As ferramentas que ofuscam bibliotecas Java podem interferir no Gerador de Associação do .NET para Android e em sua capacidade de gerar classes wrapper C#. O snippet a seguir mostra como atualizar Metadata.xml para desofuscar um nome de classe:
<attr path="/api/package[@name='{package_name}']/class[@name='{name}']" name="obfuscated">false</attr>
Problema: a fonte C# gerada não é compilada devido à incompatibilidade de tipo de parâmetro
A fonte C# gerada não compila. Os tipos de parâmetro do método substituído não correspondem.
Causas possíveis::
O .NET para Android inclui uma variedade de campos Java que são mapeados para enums nas associações C#. Isso pode causar incompatibilidades de tipo nas associações geradas. Para resolver isso, as assinaturas de método criadas a partir do gerador de associação precisam ser modificadas para usar as enumerações. Para obter mais informações, consulte Criando enumerações.
Problema: tipos EventArgs personalizados duplicados
A compilação falha devido a tipos personalizados duplicados de EventArgs. Ocorre um erro como este:
error CS0102: The type `Com.Google.Ads.Mediation.DismissScreenEventArgs' already contains a definition for `p0'
Causas possíveis::
Isso ocorre porque há algum conflito entre os tipos de eventos que vêm de mais de um tipo de "ouvinte" de interface que compartilha métodos com nomes idênticos. Por exemplo, se houver duas interfaces Java como visto no exemplo abaixo, o gerador criará DismissScreenEventArgs para ambos MediationBannerListener e MediationInterstitialListener, resultando no erro.
// Java:
public interface MediationBannerListener {
void onDismissScreen(MediationBannerAdapter p0);
}
public interface MediationInterstitialListener {
void onDismissScreen(MediationInterstitialAdapter p0);
}
Isso é feito propositalmente para evitar nomes longos em tipos de argumento de evento. Para evitar esses conflitos, é necessária alguma transformação de metadados. Edite Transforms\Metadata.xml e adicione um argsType atributo em qualquer uma das interfaces (ou no método de interface):
<attr path="/api/package[@name='com.google.ads.mediation']/
interface[@name='MediationBannerListener']/method[@name='onDismissScreen']"
name="argsType">BannerDismissScreenEventArgs</attr>
<attr path="/api/package[@name='com.google.ads.mediation']/
interface[@name='MediationInterstitialListener']/method[@name='onDismissScreen']"
name="argsType">IntersitionalDismissScreenEventArgs</attr>
<attr path="/api/package[@name='android.content']/
interface[@name='DialogInterface.OnClickListener']"
name="argsType">DialogClickEventArgs</attr>
Problema: A classe não implementa o método de interface
Uma mensagem de erro é produzida indicando que uma classe gerada não implementa um método necessário para uma interface que a classe gerada implementa. No entanto, olhando para o código gerado, você pode ver que o método está implementado.
Aqui está um exemplo do erro:
obj\Debug\generated\src\Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.cs(8,23):
error CS0738: 'Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter' does not
implement interface member 'Oauth.Signpost.Http.IHttpRequest.Unwrap()'.
'Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.Unwrap()' cannot implement
'Oauth.Signpost.Http.IHttpRequest.Unwrap()' because it does not have the matching
return type of 'Java.Lang.Object'
Causas possíveis::
Esse é um problema que ocorre com a vinculação de métodos Java com tipos de retorno covariantes. Neste exemplo, o método Oauth.Signpost.Http.IHttpRequest.UnWrap() precisa retornar Java.Lang.Object. No entanto, o método Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.UnWrap() tem um tipo de retorno de HttpURLConnection. Há duas maneiras de corrigir esse problema:
Adicione uma declaração de classe parcial para
HttpURLConnectionRequestAdaptere implementeIHttpRequest.Unwrap()explicitamente:namespace Oauth.Signpost.Basic { partial class HttpURLConnectionRequestAdapter { Java.Lang.Object OauthSignpost.Http.IHttpRequest.Unwrap() { return Unwrap(); } } }Remova a covariância do código C# gerado. Isso envolve a adição da seguinte transformação a Transforms\Metadata.xml o que fará com que o código C# gerado tenha um tipo de retorno de
Java.Lang.Object:<attr path="/api/package[@name='oauth.signpost.basic']/class[@name='HttpURLConnectionRequestAdapter']/method[@name='unwrap']" name="managedReturn">Java.Lang.Object </attr>
Problema: Colisões de nomes em classes/propriedades internas
Visibilidade conflitante em objetos herdados.
Em Java, não é necessário que uma classe derivada tenha a mesma visibilidade que seu pai. Java apenas corrigirá isso para você. Em C#, isso precisa ser explícito, portanto, você precisa garantir que todas as classes na hierarquia tenham a visibilidade apropriada. O exemplo a seguir mostra como alterar um nome de pacote Java de com.evernote.android.job para Evernote.AndroidJob:
<!-- 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>
Problema: Uma biblioteca .so exigida pela vinculação não está carregando
Alguns projetos de associação também podem depender da funcionalidade em uma biblioteca .so . É possível que o .NET para Android não carregue automaticamente a biblioteca .so . Quando o código Java encapsulado for executado, o .NET para Android falhará ao fazer a chamada JNI e a mensagem de erro java.lang.UnsatisfiedLinkError: Método nativo não encontrado: aparecerá no logcat out 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 .NET para Android tenha a biblioteca compartilhada libpocketsphinx_jni.so incluída 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");