During the last six months I have written the same mobile app for the three major (or to-be major) platforms, that is iOS, Android and Windows Phone. The app called WORTOMAT is a simple game in which you have to find words in a grid of 25 characters. There are plenty of Boggle clones out there, each with a different twist or distinctive design but none with a German dictionary, so this was what I was going for.
Owning an iPhone I started out with the iOS version where I had some basic experience using Xcode and the Cocoatouch API. The main tasks where figuring out the UIKit application logic to load the different screens, to build the GUI with the UIKit widgets and find the appropriate Objective-C methods for handling my data structures. After getting used to the strange nomenclature, the latter was actually pretty easy. For instance you can get an item from an NSArray or NSMutableArray with [myarray objectAtIndex:index]. To add an object you use [myarray addObject:name], you clear it with [myarray removeAllObjects]and so on.
If you don't use Automatic Reference Counting (ARC) you have to take care for memory management yourself. It's not that hard when you understand how it works: you need to release memory of an object you own, when either you create an object yourself with alloc, new, copy or mutableCopy or you take the ownership of an existing object with retain.
Objective-C being a superset of C you might want to use some oldschool programming idioms once in a while. That is a bit weird because you might encounter a gap that exists between the C world and the object-oriented Objective-C world, that will be bridged by strange-sounding methods. For instance to copy a NSString with strcpy() you have to use:
strcpy(s, [self.gridstring cStringUsingEncoding:NSASCIIStringEncoding])
Luckily typing method names like this and the Objective-C object method name syntax is made easy with the code completion of the Xcode editor.
Everyone is using the Model View Controler paradigm these days. However, what this means exactly remains a matter of debate. Apple realizes the seperation of concerns through the distinction between controller or model code and views that can be graphically designed with the Interface Builder that has become an integral part of Xcode with version 4 (see Apple MVC docs). In the course of this you declare variables in the code, that you hook up to events and GUI elements.
Apple offers several types of base application templates, among them a multi-page application that uses a NavigationController to switch between the individual pages. To pass data between pages that are usually represented by distinct objects, you can use a delegate protocol. I did not use the pre-built NavigationController but built on the methodpresentModalViewController (deprecated in iOS 6.0) of the UIViewController object. In that case you set a delegate object, navigate to the new page that calls the delegate before it returns to the calling page:
[self presentModalViewController:newpage animated:YES];
For presenting tabular data, there's the UITableView with a UITableViewController, where you implement various functions to supply data for and render the individual rows. It's quite easy to render the player's hiscores in a different color because there is a method that gets called for each row. There you can place code that conditionally sets the row's background color. In fact it was a bit harder because I wanted to split each row in several fields. Therefore I implemented my own class inheriting UITableViewCell. Overriding the methodlayoutSubviews you can control the appearance of the row in detail.
To interface with the REST service on the game server, I have used synchronous and asynchronous HTTP from the ASIHTTPRequest library. Using the TouchJSON library simplifies serializing and unserializing JSON data. The Toast library provides simple Toast-style notifications, as known from Android.
App Store review was painless, although the App Store guidelines are kind of intimidating. Setting up the requisite certificates for signing your app has become much easier in Xcode 4, where you can use the organizer to do it all. After uploading your app you have to wait almost two weeks to get it approved. That's a drag, as you have to repeat this cycle for every update to the app.
Using Xcode and the iPhone simulator is a pleasure. The iPhone simulator is reasonably fast. It's so fast that I could do much of the development on the Macbook on the subway instead of plugging in a real device. The Cocoatouch API is comprehensive and well documented, although Apple seems to be changing their web site structure quite often, so you encounter stale links when you Google for documentation.
After that I started porting WORTOMAT to Android. I had some experience with Java so I had to get behind the anatomy of Android applications and the API. This is where the problem starts. Although there have been some changes to iOS over the years as well, they were not as fundamental and backwards incompatible. For instance the Action Bar is now a requirement for apps, but there's no Action Bar in Android 2.3.3 (there are some 3rd party projects that emulate it, but that's a different story). You want to use the built-in options menu? You won't when you are targeting a recent Android version, because it got deprecated with the introduction of the Action Bar. That leaves you with a minSdkVersionand a targetSdkVersion of 10, if you want to support 2.3 devices up to the latest Android devices.
The Android UI model has evolved over the years, too. Back in the days Activities where the fundamental unit you would use to build your applications. Then Google introduced Fragments, which is not a bad idea at all, because it allows you to use the same concepts on smartphones and tablets with a different layout. There are no Fragments in the Android 2.3 SDK proper, but you can add support for them through the Android Support Library.
After porting the initial code for loading the word lists to Android I encountered serious problems with the performance because the garbage collector was going wild. I learned that the garbage collector is frequently a source of performance problems on the Android platform and restructured my app accordingly, which was probably a good thing anway. It's actually quite hard to predict the performance of the garbage collector. Even more so, when you are using a third party library, that for instance creates a lot of temporary objects.
To load data from the REST service and display the result in a new screen you launch a so called Intent which in turn loads a new Activity. To wait for the Intent to return some result you start it with the method startActivityForResult():
Intent intent = new Intent(WORTOMAT.this, HiscoreList.class);
In the onActivityResult() handler the PICK_GAME designator serves to discern the originating Intent. A result code can be used to check the success or failure of an operation.
The hardest part was figuring out how to build the lists that are used to display games and hiscores. The Android model is quite involved and requires the implementation of a special ListAdapter for this purpose. In the code you need to hook up the layout, that is defined in XML files with the data. All in all it took several files to implement a simple hiscore list:
For communicating with the REST service I was using the Android Asynchronous Http Client, because it provides POST support with a simple interface for assembling the parameters. JSON decoding is provided by the Android SDK itself.
It's not a great deal of fun to use Eclipse because it is painfully slow. I know Java can be reasonably fast, but I guess this is what you get when you get carried away with overdesign in Design Patterns to create Factories from FactoryFactory objects or something like that (OSGI). I know that Eclipse is not an IDE but an "application platform" that can be used to build other things, but if this is the result you'd better build on a different foundation. The same machine (Mac 4GB RAM) runs Xcode and Visual Studio smoothly.
That said, the Android Plugin works decently. You can edit your Java and XML code, compile, debug, deploy and sign your apps (although for signing some intervention on the command line is required). The GUI editor was not of much use so I restrained myself to editing the XML descriptions of it. Code completion and syntax check does not work without problems. For example, sometimes Eclipse won't find XML attributes, that are valid for a particular element.
It's hard to believe that IBM and others reportedly spent 50 million dollars on the development of Eclipse. I mean, it's not so hard when you think about all that overengineering that's obviously going on. But it's hard to imagine that from the 50 millions dollars they spent obviously nothing went into usability testing. For one, you can't just "Open" a project. I know, this might again be some different usage paradigm but I bet that 9 out of 10 developers are used to looking for this menu item when they want to open a project (and the software will consequently fail the usability test case). Install a new plugin? That would be in the "Help" menu, right?
The Android emulator is virtually useless, as it is so slow that you can barely use it. The best solution I found to make if halfway work, was the installation of the Intel Hardware Accelerated Execution Manager (HAXM), a kernel module that speeds up an Android virtual machine based on the Intel architecture (opposed to ARM).
Getting the WORTOMAT app in the Play Store was easy, although the Developer Console could use some work. Actually I found it quite irritating that there's no review process at all. Where Apple sets the barrier too high, Google might set it too low. I noticed that I hurried to release several updates to the Android app in a row, instead of doing it properly. Of course this is my own fault, but it's might also be a psychological fact that is founded in a missing review process (the reportedly low quality of Android apps may confirm this assumption).
Again, the Windows Phone platform shows some similarities and differences to the Android and iOS world. Somehow they also propose some kind of MVC model for developing applications, on the other hand the navigation paradigm is quite different. Based on Silverlight, there's an XAML (some Silverlight XML application) description for every page, with so called code-behind that defines the corresponding class. My experience is confined to C#, but the model is the same with Visual Basic and C++.
For instance, to navigate to a new page, you use the Navigate method of theNavigationService with the XAML file name of the new page as the argument. This is essentially like navigating to a new web page, only the runtime instantiates the class, executing the constructor. This is, where you place your code. For whatever reason I had a hard time getting behind some of the GUI elements ("controls") Silverlight offers. There are no labels, so you have to use Textblocks. However, Textblocks (opposed to Textbox) are not derived from controls, so they lack a Background property to set the background color. You have to go a roundabout way of wrapping the Textbox in a Grid which has a background color you can set.
For editing the GUI you use a separate programm called (Expression) Blend that offers pixel perfect editing of controls. It's quite complex as is the Silverlight component model, so it takes some time to get used to it. It was easy using it when I had components with a static color in the beginning. It wasn't that much fun, when I changed to dynamic colors and Blend chose to render all controls black as a result. Similar to Android I found myself editing the X(A)ML files more often than not.
When you give a control a name in the "x" namespace (you assign the x:Name attribute of an element) you can refer to it in code without any additional coding. Sometimes, though, when you add a new element in Blend, the Visual Studio editor doesn't take notice of that and marks the symbol as a syntax error, even when you have the project updated. Building the project does work, though.
I did not have much fun browsing the documentation on the Net, because most of the time you will find methods with the same name that belong to different versions of Silverlight or Windows Presentation Foundation (WPF), and you always have to figure out what works and what doesn't on the particular Silverlight version Windows Phone is using. Sometimes the omissions of the Silverlight version are just annoying, such as the missing journal of the navigation stack.
I had mixed experiences with the Windows Phone Simulator. It's a Hyper-V virtual machine, so you need to have a computer with hardware virtualization features (VT on Intel). As a sidenote, it is not possible to have HAXM (see the Android part) and Hyper-V enabled (this is not about running it at the same time) on the same machine. To enable the Hyper-V feature in Windows you need to have HAXM uninstalled and vice versa. On my Mac Mini I never got networking to work, because there were problems with the built-in Broadcom wireless adapter, while setting up the Virtual Network Switch with the USB Wifi stick did not work out. On another PC it worked fine without any problems or additional configuration.
WORTOMAT for Windows Phone ist the only version of the game that includes the option to change the colors of the GUI. After some initial research this should have been easy, but it turned out harder than promised. Part of the problem was that at that point I already had set up the GUI with a custom style for the buttons I had derived from the stock Button in Blend. The style makes use of the Setter element in the XAML file and unfortunately in the Silverlight version for Windows Phone 7 this element doesn' support dynamic data binding (this has changed in Windows Phone 8). So I had to redesign the GUI from ground up and use the Background, Foreground and BorderBrush properties on the element itself. In the code-behind you need to create an object that implements the INotifyPropertyChangedinterface. More than once I wondered why my colors did not get assigned to a new control because I forgot to change its DataContext to the object of this class. In general data binding is quite nice and I will make more use of it on my next project.
Implementing the hiscore and games list was quite easy, because it was sufficient to just assign the ItemsSource of the ListBox component. Rendering the player's hiscores in a different color was a bit harder, but in the end an IValueConverter that conditionally converts the dynamicall bound color did the trick.
C# and Java as programming languages are so similar that you can't help but ask why the world needed both of them. On the other hand, when you know Java you will be able to program in C# and barely notice. In summary I like C# a bit more because it's more stringent as an object oriented programming language with some functional features and has less incompatible features such as simple types that get in the way sometimes. Autoboxing in Java doesn't always help.
Like Android Windows Phone prescribes that HTTP requests are made asynchronous as not to block the GUI thread. I chose the RestSharp library for that, because it contains an implementation of the POST method that offers the same simple interface as GET requests including the handling of parameters. RestSharp includes JSON deserialization but I needed more flexibility and did not really figure out how to use attributes for hooking in my own deserializer so I did that manually with the Json.NET library.
The Windows SDK offers a nice way of implementing a trial version of your app, where the user can download the app for free and buy later. This is made easy for the programmer through a simple API that he can use for checking the license information (although there is no in-app purchase before Windows Phone 8)
Using the Windows Developer web frontend for submitting your applications is not too hard, but sometimes it's a bit confusing. For instance when I changed the app description slightly and removed a screenshot I was surprised to learn that my app got submitted for review again. Even worse, you can't cancel an active submission yourself, nor can you submit another version when you have an update in submission. That means, when you uploaded a version of your app that you find a bug in, you have to wait until Microsoft has approved it, until you can submit a new version with your bugfix! The only way around this for now is to write an email to the support.
In the end there's not a too big difference when you try to judge the overall API of the three mobile platforms. Cocoatouch and Silverlight seem a little less confusing than the Android API but then there are certain tasks you can realize easier in Android than on the other platforms. All of them are quite comprehensive, but the existence of very popular convience libraries for JSON, REST etc. show that there's still room for improvement.
In terms of documentation and tooling Apple provides the best experience. Xcode is a great and very responsive editing environment. Through the organizer you can get all other jobs done, such as profile provisioning, handling of developer and distribution certificates and so on. The tools for performance profiling and tracing are unmatched by Android tools. Although I kind of like Objective-C, the language looks a bit old when compared to C# and the like. Visual Studio includes the XAML profiler and the code profiler which provide a visual representation of the running application. Android development tools, in comparison, appear much less polished and usable.
UPDATE: Some commenters on Reddit have rightly pointed out that I am missing the fact that Android is the only platform that can be used on multiple operating systems for development. Even more, it is the only one you can use on a Linux box. So I added this to the table below.
|Development Tools||ok, slow||comprehensive, fast||comprehensive, fast|
|Programming Language||Java||Objective-C||C#, Visual Basic, C++|
|Documentation||ok, but terse||comprehensive, well structured||sometimes confusing|
|App Approval||none||takes up to two weeks||takes a week|
|Developer Web Console||could use some work||comprehensive, sometimes slow||fast, but missing features|
|Development System||Linux, Windows, Mac||Mac||Windows|