Binding van Java-bibliotheken

Het bibliotheekecosysteem van derden voor Android is enorm. Daarom is het vaak zinvol om een bestaande Android-bibliotheek te gebruiken dan om een nieuwe te maken.

Met .NET voor Android kunt u dit doen met een Bindingsbibliotheek waarmee de bibliotheek automatisch wordt verpakt met C#-wrappers, zodat u Java-code kunt aanroepen via C#-aanroepen.

Dit wordt geïmplementeerd met managed Callable Wrappers (MCW). MCW is een JNI-brug die wordt gebruikt wanneer beheerde code Java-code moet aanroepen. Beheerde aanroepbare wrappers bieden ook ondersteuning voor subklassen van Java-typen en voor het overschrijven van virtuele methoden op Java-typen. Op dezelfde manier, wanneer android-runtimecode (ART) beheerde code wil aanroepen, doet deze dit via een andere JNI-brug die bekend staat als Android Callable Wrappers (ACW). Deze architectuur wordt geïllustreerd in het volgende diagram:

Architectuur voor Android JNI-brug

Een bindingsbibliotheek is een assembly met beheerde aanroepbare wrappers voor Java-typen. Hier is bijvoorbeeld een Java-type, MyClassdat we willen verpakken in een bindingsbibliotheek:

package com.contoso.mycode;

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

Nadat we een bindingsbibliotheek hebben gegenereerd voor de .jar die deze bevat MyClass, kunnen we deze instantiëren en methoden aanroepen vanuit C#:

var instance = new MyClass ();

string result = instance.MyMethod (42);

Als u deze bindingsbibliotheek wilt maken, gebruikt u de sjabloon .NET voor Android genaamd Android Java Binding Library. Het resulterende bindingsproject maakt een .NET-assembly met de MCW-klassen, .jar.aar-bestanden/ en resources voor Android-bibliotheekprojecten die erin zijn ingesloten. Door te verwijzen naar de assembly van de resulterende bindingsbibliotheek, kunt u een bestaande Java-bibliotheek hergebruiken in uw .NET voor Android-project.

Wanneer u verwijst naar typen in uw bindingsbibliotheek, moet u de naamruimte van uw bindingsbibliotheek gebruiken. Normaal gesproken voegt u boven aan uw C#-bronbestanden een using instructie toe die de .NET-naamruimteversie van de Java-pakketnaam is. Als de naam van het Java-pakket voor uw afhankelijke .jar bijvoorbeeld het volgende is:

com.contoso.package

Vervolgens plaatst u de volgende using instructie boven aan uw C#-bronbestanden om toegang te krijgen tot typen in het afhankelijke .jar bestand:

using Com.Contoso.Package;

Wanneer u een bestaande Android-bibliotheek bindt, moet u rekening houden met de volgende punten:

  • Zijn er externe afhankelijkheden voor de bibliotheek? – Alle Java-afhankelijkheden die vereist zijn voor de Android-bibliotheek, moeten worden opgenomen in het .NET voor Android-project via een NuGet-pakket of als AndroidLibrary. Alle systeemeigen assembly's moeten als AndroidNativeLibrary aan het bindingsproject worden toegevoegd.

  • Welke versie van de Android-API is het doel van de Android-bibliotheek? – Het is niet mogelijk om het Android-API-niveau te downgraden; zorg ervoor dat het bindingsproject voor .NET voor Android hetzelfde API-niveau (of hoger) als de Android-bibliotheek heeft.

Java-API's aanpassen aan C⧣

De .NET voor Android Binding Generator wijzigt enkele Java-idiomen en -patronen zodat deze overeenkomen met .NET-patronen. In de volgende lijst wordt beschreven hoe Java is toegewezen aan C#/.NET:

  • Setter-/Getter-methoden in Java zijn eigenschappen in .NET.

  • Velden in Java zijn eigenschappen in .NET.

  • Listeners/listenerinterfaces in Java zijn gebeurtenissen in .NET. De parameters van methoden in de callback-interfaces worden vertegenwoordigd door een EventArgs subklasse.

  • Een statische geneste klasse in Java is een geneste klasse in .NET.

  • Een interne klasse in Java is een geneste klasse met een instantieconstructor in C#.

Een systeemeigen bibliotheek opnemen in een binding

Het kan nodig zijn om een .so-bibliotheek op te nemen in een .NET voor Android-bindingsproject als onderdeel van het binden van een Java-bibliotheek. Wanneer de verpakte Java-code wordt uitgevoerd, kan .NET voor Android de JNI-aanroep niet uitvoeren en wordt het foutbericht java.lang.UnsatisfiedLinkError: Systeemeigen methode niet gevonden: wordt weergegeven in de logcat-out voor de toepassing.

De oplossing hiervoor is om de .so-bibliotheek handmatig te laden met een aanroep naar Java.Lang.JavaSystem.LoadLibrary. Stel dat een .NET voor Android-project de gedeelde bibliotheek libpocketsphinx_jni.so heeft opgenomen in het bindingsproject met een buildactie van AndroidNativeLibrary, dan wordt de .so-bibliotheek geladen door het volgende codefragment (uitgevoerd voordat u de gedeelde bibliotheek gebruikt):

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

Bindingscenario's

Met de volgende handleidingen voor bindingsscenario's kunt u een Java-bibliotheek (of bibliotheken) binden voor integratie in uw app: