One problem often identified by any type of developer is code reuse. This problem is especially important in mobile development when the application needs to be split up into multiple apps used for the same purpose. This can come in many forms like a “Lite” (usually free) and “Full” (usually paid) version of an application. At MichiganLabs, we recently split an application into two branded versions of the same application (lets call them A and B). The application icons are different, the launch screens are different, some of the nomenclature used in the applications are different, but the general functionality is the same. We did this for an iOS and Android version of the application. The iOS version uses Xamarin Studio and the Android version uses Intellij with the ADT plug-in. We also wanted both applications to be free and wanted to strategically do this in order to reuse as much code as possible.
There are a few strategies to reuse code in this context. The proper way to do a Free vs Paid app is to charging money through in-app billing which “unlocks” new content after receiving confirmation from the service provider that a purchase has been made. Since we didn’t want to charge for either of the applications, this process wouldn’t work for us. The simplest method is to create a variable in the application that defines if the application is “A” or “B”, then have if statements for all the places where there are differences between “A” and “B”. The problem with this solution is the difficulty involved with publishing to the app store. The app bundle identifiers need to change for each app and this does not work well with version control.
We wanted to land somewhere in the middle of these two strategies so we decided to try a slightly different approach. Because of the unique constraints of our application, we created a “library” that holds the core functionality of the application. Each of the two applications calls into the library for the functionality of the application and the application checks the bundle name to decide which resources to use (resources for “A” or “B”).
We have an Android and iOS version of these applications. The Android version is created using Intellij with the ADT plug in. The iOS version is created using Xamarin Studio. The solution we implemented was basically the same for both platforms, but each platform uses slightly different terminology. Android calls them library projects where in Xamarin, we use “file linking” and don’t have a separate project for the shared code.
In Intellij, they include support for Android library projects. Library projects are simply ways for other android project to reference shared code and resources. They are very easy to set up (command line or through Intellij), and even easier to reference from other projects (command line or through Intellij). There are even tutorials out there on how to turn an application project into a library project (just in case you screw it up in the beginning). Library projects are great and many “libraries” are already using this approach (such as ActionBarSherlock)
For iOS, we utilized a method Xamarin provides called File Linking. This is exactly like creating a symbolic link to files that are external to the project, except Xamarin keeps those symbolic links so they are platform independent (in this case, Mac/Linux/Windows). In order to keep the code organized, three folders were created for the iOS version of the apps. The first two folders are Xamarin “Projects”. The last folder just a folder containing all the files shared between the two projects. See the link above for details on how to add links to the files in each of the Xamarin projects.
- Project A
Project A Specific Resources
Project B Specific Resources
Was it worth it?
So the last major question to answer about all this decision making is “Was it worth it (do the benefits outweigh the cost of making this decision)?” The amount of time that will be saved in the long run, combined with the amount of code that we can easily reuse definitely outweighs the amount of time taken to setup this project. When we want to make a change to the core functionality of each app, we will just have to make a change to the library code and it will take effect in both applications.