Android.dll

androidmono

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:

  1. Java application reflects through Android framework SDK jar and outputs an XML file that represents the object model.
  2. 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).
  3. Tag all the methods with the [MethodImpl(MethodImplOptions.InternalCall)] attribute.
  4. 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…