Picture above represents the results of 3 sleepless nights. No, I didn’t rewrite the Android framework. I generated a bunch of proxy classes to access them from Mono though. Rough idea of how it works:
- Java application reflects through Android framework SDK jar and outputs an XML file that represents the object model.
- C# application generates thousands of code files of said object model. (This is similar to jni4net, but that doesn’t work on anything but Windows).
- Tag all the methods with the [MethodImpl(MethodImplOptions.InternalCall)] attribute.
- Implement the method calls at runtime with a combination of dynamically created expression tree delegates and mono_add_internal_call.
The class contents actually have no code, so the total dll size is pretty small (800k). Here’s what the LinearLayout “implementation” looks like:
namespace android.widget
{
public class LinearLayout : android.view.ViewGroup
{
public class LayoutParams : android.view.ViewGroup.MarginLayoutParams
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern java.lang.String debug(java.lang.String arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public extern LayoutParams(android.content.Context arg0, android.util.AttributeSet arg1);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public extern LayoutParams(int arg0, int arg1);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public extern LayoutParams(int arg0, int arg1, float arg2);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public extern LayoutParams(android.view.ViewGroup.LayoutParams arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public extern LayoutParams(android.view.ViewGroup.MarginLayoutParams arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
internal extern LayoutParams();
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern void setGravity(int arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
protected override extern void onLayout(bool arg0, int arg1, int arg2, int arg3, int arg4);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public override extern int getBaseline();
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
protected override extern void onMeasure(int arg0, int arg1);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
protected override extern bool checkLayoutParams(android.view.ViewGroup.LayoutParams arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern new android.widget.LinearLayout.LayoutParams generateLayoutParams(android.util.AttributeSet arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
protected virtual extern new android.widget.LinearLayout.LayoutParams generateLayoutParams(android.view.ViewGroup.LayoutParams arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
protected virtual extern new android.widget.LinearLayout.LayoutParams generateDefaultLayoutParams();
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern bool isBaselineAligned();
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern void setBaselineAligned(bool arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern int getBaselineAlignedChildIndex();
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern void setBaselineAlignedChildIndex(int arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern float getWeightSum();
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern void setWeightSum(float arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern void setOrientation(int arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern int getOrientation();
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern void setHorizontalGravity(int arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public virtual extern void setVerticalGravity(int arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public extern LinearLayout(android.content.Context arg0, android.util.AttributeSet arg1);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
public extern LinearLayout(android.content.Context arg0);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
internal extern LinearLayout();
}
}
A year of on and off hacking coming to fruition soon…