Mono on Android: State of the Union

Having mostly finished up my surprisingly successful ROM Manager and ClockworkMod Recovery, I finally turned my attentions back to androidmono. Though Miguel recently announced the MonoDroid project, there's still room for a open source/hobbyist version. :) (And I need something to work on when I am bored)
When I put the project down a few months ago, I had very rough bindings to the Java API. I recently dumped the approach I took (albeit very cool), in favor of using jni4net. jni4net is a similar project that allows embedding a JVM into Microsoft's CLR, or vice versa. It only took a little bit of tweaking to make it work on Dalvik with Mono (I also hacked off a lot of unnecessary stuff that jni4net provides). So the following file:



Gives you this activity:

(Note: the code above is being displayed from my github repo and may change and leave the image out of date.)
I hacked up a Java/C# project to reflect on the Android SDK jar and create a C# android project that binds to the Java APIs via JNI. So, how it sort of works:
  • Create a class library and start coding up your services and activities.
  • Create a matching Java project (using the Android template as found on github) that uses the same namespace as your C# project.
  • Create "native" method stubs for all the overridden methods on your C#/Java doppleganger types. See here for an example.
  • The native methods get bound to the C# implementations at runtime automagically at runtime.

  • There's still a lot of work left to do: MonoDevelop template and plugin, a tool to create Java dopplegangers for each C# object via reflection, soft debugger support, translating Java's "OnSomeEvent" interfaces into true C# events/delegates, convenence extension methods, support for constructors (a Java constructor can not be "native"), and more. I wouldn't even say this is in Alpha stages yet, but it *works*.

    18 comments:

    Jae said...

    Awesome! So jni4net is going to be cross-platform now? :)

    PWobst said...

    Great work! Thanks for being bored every once in a while ;-)

    Scott said...

    This is great news! I've been waiting for a way to start .NET coding on my new Incredible. I can understand your priorities going to your non-free products, but please keep up the good work on Mono!

    robert101 said...

    Does Mono for android allow stuff from .NET 3.5 or are we limited to 1.1 for now?

    Morgan said...

    Nice work!

    chad said...
    This comment has been removed by the author.
    Anonymous said...

    public static implicit operator java.lang.String(System.String m)
    {
    return new java.lang.String(m);
    }

    Koush said...

    Anonymous:
    http://developer.android.com/reference/android/widget/TextView.html#setText(java.lang.CharSequence)

    You can't have implicit operators on interface types. It takes a charsequence parameter. Not java.Lang.String.

    But the operator is implemented and would work if the parameter were java.Lang.string.

    Damian said...

    Really appreciate the work you've put into this - a long time ago I put together a Java-COM bridge (J-Integra) and I know how much work it is to do this kind of thing.

    I'm getting build errors running build.sh in MonoJavaBridge - it doesn't find generated/android... files.

    These are not in the http://github.com/koush/jni4net.n.gitgit repository as far as I can see - I manually fetched this to jni4net.n

    Should they be being generated as part of the build? I don't see anything in the csproj files to do so.

    Thanks,
    Damian

    Damian said...

    To clarify, if I go to ~/src/androidmono/jni/MonoJavaBridge/android

    and do an xbuild, I get errors such as "Source file `generated/android/net/ConnectivityManager.cs' could not be found".

    Indeed there is no generated/android/net folder - not sure if this should have been generated as part of the build ....

    Regards,
    Damian

    Jim said...

    Thanks for your efforts! This is great. Have you gotten your .NET+OpenGLES wrapper working on android ( http://www.koushikdutta.com/2008/08/net-compact-framework-wrapper-for.html )? And has anyone manged to migrate those to Visual Studio 2010 [Express]?

    e.semog said...

    You mention creating some doppleganger stubs from reflection. In case you were interested, I have published an open source project that does this for C# classes. It is currently set to output C# code, but it could be modified to output Java code. Feel free to take a look at it here: http://code.google.com/p/doppleganger/

    Best of luck in your work on getting Mono to run on the Android platform. I am very interested in having this ability.

    Engaged and Planning said...

    @Damian - I had to grab the jni4net.n directory from the master branch and manually merge it into the devel branch.

    Also, I had to rebuild the bindings from scratch using the jni/MonoJavaBridge/JavaObjectModelGenerator project, after changing String androidSDK in JarListener.java to point to my android SDK's android.jar instead of koush's.

    Then, I needed to regenerate the android.dll source files by running the MonoDroid project (see the readme.txt).

    Then I had to delete the jni/MonoJavaBridge/android/generated directory, and copy jni/MonoJavaBridge/bin/generated into jni/MonoJavaBridge/android.

    I also removed the */net folders from the android project and re-added the sources - not sure if that did anything. The affected folders were generated/android/net, generated/java/net and generated/javax/net.

    Couple of other things I had to do:
    Remove the (java.lang.String) casts in the HelloWorld Activity. Seems koush found a way to generate overloads for .Net strings somehow?

    Also, I had to modify the return type of one of the methods in ArrayList.cs from returning ListIterator to returning Iterator. I think there were already exceptions hard-coded for other similar classes, but ArrayList wasn't added to the exception list (see jni/MonoJavaBridge/MonoDroid/NetProxyGenerator.cs, line 141. We may need to add ArrayList to the if statement here).


    Also, that's as far as I got. I haven't yet been able to get the MonoDevelop plugin to build (says it is missing MonoDevelop.Debugger and MonoDevelop.Debugger.Soft assemblies). I'm thinking this is an issue with my config. I'm using MonoDevelop 2.4 from badgerports.org

    Koush said...

    Hey, sorry, been busy with non-Mono stuff again. If you want to hop onto irc.freenode.net and PM Koush, I can give you a better status on the project and some instructions. You shouldn't have needed to merge master into devel on jni4net.

    Engaged and Planning said...

    @koush Sorry, I don't have access to IRC at work, and my 6 month old daughter keeps me away from the computer at home heh.

    Engaged and Planning said...

    If you have access to google Wave, I started a wave. Search for tag:"androidmono" - I should be the only one there: "Late Breaking AndroidMono Build Issues/Instructions" wave.

    Koush said...

    Link to the wave?

    Engaged and Planning said...

    https://wave.google.com/wave/waveref/googlewave.com/w+8vSV9-MEA