Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

Windows Phone 7, Android and iOS with Mono III: Shared Libraries

We’ve got the basics functioning across all three platforms but at the moment we’ve written all our code within the confines of three different projects with no code shared between them. Of course, one of the reasons for using MonoTouch/MonoDroid is to try to reuse and share as much code as possible between the platforms. That and hopefully we don’t need to spend too much time writing obnoxious Java or Objective-C code.

Now we could simply share files between the three projects, after it’s just .NET code but I want to be a little more adventurous. I’m going to create a class library that each of my three platform projects can access. Now I’m actually going to have platform specific class library project files, but the rest of the files contained within the project will be common across all projects.

Unfortunately I don’t know of an easy way to do this, so I’ll show you the long way – if someone does know an easier way to do this, please let me know because this way is painful.

Windows Phone 7

- Add a new project to your Windows Phone 7 application based on the Windows Phone Class Library template. In my case my shared library is going to be called BuiltToRoam.General but rather than leave it in the solution folder, I’m going to go up a level, create a folder called Shared and create the project in there. This will give me a folder structure as follows:

\CrossPlatform
    \Shared
        \BuiltToRoam.General
    \NicksNetTravels
    \NicksNetTravelsAndroid
    \NicksNetTravelsiOS

- In the new project rename Class1.cs to Utility.cs and add the following simple extension method:

namespace BuiltToRoam.General {     
  public static class Utility {         
    public static T EnumParse<T>(this string enumValue, bool ignoreCase = true) where T : struct {
             try {
                 if (string.IsNullOrEmpty(enumValue)) return default(T);
                 return (T)Enum.Parse(typeof(T), enumValue, ignoreCase);
             }
             catch {
                 return default(T);
             }
         }
     }
}

As you can probably work out all this method does is parse a string and return the appropriate enumeration value (strongly typed of course!).

- Right-click your Windows Phone 7 application project in the Solution Explorer window and select Add Reference; Select the BuiltToRoam.General project and add it as a reference.

- Now, just to test that this works, modify the MainPage constructor (in MainPage.xaml.cs) as follows:

public enum Wp7EnumTest {
First,
Second
}
 
public MainPage() {
InitializeComponent();

var test = ("First").EnumParse<Wp7EnumTest>();
}
 

- Build and run. Set a breakpoint after the EnumParse line to check that this works.

 

iOS

This is where it starts to get messy. Essentially you want to create an empty project stub for both iOS and Android. You can’t call them the same as the WP7 project because then you’ll end up with a file conflict; yet if you give them a different name they’ll create a new project folder which won’t contain the same files. There are actually two options here: Option 1 is that you just live with the fact that you’ll have multiple project folders – Visual Studio allows you to add files as links which means that you can have the files in one project (eg the Windows Phone 7 project you just created) and then as links in the iOS and Android projects. Option 2, which I prefer, is to create the project stubs with a slightly different name, and then move them into the same directory as the Windows Phone 7 project file. Then you can add literally the same files as the projects will be in the same folder. Here I’m going to go with Option 2, so if it didn’t make sense when I described it, then hopefully it will by the end of this.

- In MonoDevelop, right-click the Solution node in the Solution window and select Add > Add New Project. Select the MonoTouch Library Project from under the C# > iPhone and iPad node. Give you project a name, in this case BuiltToRoam.General.iOS, and click Forward to create the new project.

- Right-click the newly created project and select Delete (this might seem odd since what we actually want to do is to remove it from the solution, rather than deleting the project). When prompted, select “Remove” from the dialog (if you select “Delete from Disk” it will do just that, which is not what we want).

- In Finder, locate the newly created project file (in this case BuiltToRoam.Genera.iOS.csproj) and move it from where it was created into the shared project folder (in this case \Shared\BuiltToRoam.General).

- Back in MonoDevelop, right-click the Solution node. This time select Add > Add Existing Project and navigate to the shared project folder and select the project you just moved.

- Right-click the References folder of your iOS application project (ie NicksNetTravelsiOS) and select Edit References. Select the Projects tab and check the box alongside the shared project you just added (ie BuiltToRoam.General.iOS).

- Right-click the shared project and select Add > Add Files. Select Utilities.cs and click Open to add the file to your project

- Modify the code in Main.cs to include the following code to test the code in the referenced assembly works.

public enum iOSEnumTest{
    First,
    Second
}
 
public class Application  {
  static void Main (string[] args) {
   var test = ("First").EnumParse<iOSEnumTest>();

   UIApplication.Main (args);           
  }
}

- Again, set a breakpoint after the EnumParse line to validate that this code works.

Note: You may find that your breakpoints aren’t hit for some reason. This may be because you’re running without attaching the debugger. To run with the debugger select Run > Run With > Mono Soft Debugger for iPhone

 

Android

Ok, last one. We’re going to follow basically the same process over again. Perhaps I should make a project template for this….. volunteers?

- File > Add > New Project. Select the Mono for Android Class Library from the Mono for Android node. Give your project a name, in this case BuiltToRoam.General.Android, and click OK to create the class library.

- Like we did in the iOS case: Right-click on the newly created project and click Remove. Find the project file (ie BuiltToRoam.General.Android.csproj) in Windows Explorer and move it into the shared project folder.

- Right-click the solution node in Solution Explorer and select Add > Existing Project. Locate the shared project file and click Open to add it to the solution.

- Right-click the Android application project and select Add Reference. Select the Projects tab, select the BuiltToRoam.General.Android project and add it as a reference.

- Right-click the shared project file and select Add > Existing Item. Find Utilities.cs and click Add.

- To verify that this works, add the following code to Activity1.cs

public enum AndroidEnumTest {
    First,
    Second
}

protected override void OnCreate(Bundle bundle) {
    var test = ("First").EnumParse<AndroidEnumTest>();
    ...
}

- Set a break point after the EnumParse line to verify this works.

So there you have it, the ability to share whole projects between WP7, Android and iOS. It wasn’t that hard after all.

Comments (2) -

  • Jeff

    4/23/2011 8:16:47 PM |

    Are you using a Mac or a PC or both for these projects?  It looks like from the examples you are using one platform but I can't figure out how you can do that.

  • Nick

    4/23/2011 8:45:34 PM |

    Unfortunately you have to use a Mac to do ios dev. I'm using a PC to do the WP7 and Android development. I'm also using svn as my source code repository to allow me to easily share code between the platforms.

Pingbacks and trackbacks (2)+

Comments are closed