Another potential way to implement "bind only what you need" would be to remain fully in C# and place the burden on the user to provide the metadata needed to perform JNI interop. While this can be cumbersome and tricky for lots of API, for a few small uses it might be acceptable.
Downsides:
User must manually provide the metadata needed by JNI
Only supports C# -> Java invocations, users cannot override methods or listen for events
Open questions:
Can we determine the method signature from the parameters the user gives us? Or would they need to provide the signature as well?
Proposed API
// Create a new "com.googleplay.services.ApiClient" type instance
var api_client = new UntypedJavaObject ("com.googleplay.services", "ApiClient");
// or with constructor parameters
var api_client = new UntypedJavaObject ("com.googleplay.services", "ApiClient", "my_api_key");
// Invoke a method with 'void' return
api_client.InvokeMethod ("setApiKey", "my_api_key");
// Invoke a method with 'int' return
var quota = api_client.InvokeMethod<int> ("getRemainingQuota");
// Get an 'int' field
var quota = api_client.GetField<int> ("API_VERSION");
// Set an 'int' field
api_client.SetField ("API_VERSION", 34);
Would also need a static version:
var api_client = new UntypedStaticJavaObject ("com.googleplay.services", "ApiClient");
var quota = api_client.GetField<int> ("API_VERSION");
Interop with Classic Java.Lang.Object
Use a JLO as an "untyped" parameter type
var view = FindViewById (Resources.layout);
var map = new UntypedJavaObject ("com.mapbox.maps", "MapView");
map.InvokeMethod ("attachToView", view);
Return a JLO from an "untyped" return type
var map = new UntypedJavaObject ("com.mapbox.maps", "MapView");
var view = map.InvokeMethod<Android.Views.View> ("getAttachedView");
Cast a JLO that was bound as Object to an "untyped" type
var view = FindViewById (Resources.layout);
var unknown_jlo = view.GetThing ();
var untyped = UntypedJavaObject.FromObject (view);
Cast an "untyped" type to a known JLO
var map = new UntypedJavaObject ("com.mapbox.maps", "MapView");
var untyped = map.InvokeMethod<UntypedJavaObject> ("getAttachedView");
var view= untyped.JavaCast<Android.Views.View> ();
Execute an unbound method on a JLO
var view = FindViewById (Resources.layout);
var untyped = UntypedJavaObject.FromObject (view);
untyped.InvokeMethod ("newUnboundMethod");
Summary
Another potential way to implement "bind only what you need" would be to remain fully in C# and place the burden on the user to provide the metadata needed to perform JNI interop. While this can be cumbersome and tricky for lots of API, for a few small uses it might be acceptable.
Downsides:
Open questions:
Proposed API
Would also need a
static
version:Interop with Classic
Java.Lang.Object
Use a
JLO
as an "untyped" parameter typeReturn a
JLO
from an "untyped" return typeCast a
JLO
that was bound asObject
to an "untyped" typeCast an "untyped" type to a known
JLO
Execute an unbound method on a
JLO
Sample
Converting the sample from https://github.com/Redth/MapboxSlimBindingDemo/tree/main: